From 3f2457aa214f9ca3e3a7f86c702bfbf3df4d485e Mon Sep 17 00:00:00 2001 From: Apple Date: Tue, 1 May 2007 21:39:20 +0000 Subject: [PATCH] libutil-11.tar.gz --- Makefile | 97 +++++++++++++++++ _secure_path.3 | 75 ++++++++++++++ _secure_path.c | 73 +++++++++++++ getmntopts.3 | 221 +++++++++++++++++++++++++++++++++++++++ getmntopts.c | 188 +++++++++++++++++++++++++++++++++ humanize_number.3 | 148 ++++++++++++++++++++++++++ humanize_number.c | 147 ++++++++++++++++++++++++++ libutil.h | 166 ++++++++++++++++++++++++++++++ libutil.plist | 36 +++++++ libutil.txt | 238 ++++++++++++++++++++++++++++++++++++++++++ mntopts.h | 136 ++++++++++++++++++++++++ pidfile.3 | 249 ++++++++++++++++++++++++++++++++++++++++++++ pidfile.c | 243 +++++++++++++++++++++++++++++++++++++++++++ property.3 | 99 ++++++++++++++++++ property.c | 257 ++++++++++++++++++++++++++++++++++++++++++++++ realhostname.3 | 105 +++++++++++++++++++ realhostname.c | 184 +++++++++++++++++++++++++++++++++ realhostname_sa.3 | 133 ++++++++++++++++++++++++ trimdomain.3 | 85 +++++++++++++++ trimdomain.c | 114 ++++++++++++++++++++ uucplock.3 | 183 +++++++++++++++++++++++++++++++++ uucplock.c | 229 +++++++++++++++++++++++++++++++++++++++++ 22 files changed, 3406 insertions(+) create mode 100644 Makefile create mode 100644 _secure_path.3 create mode 100644 _secure_path.c create mode 100644 getmntopts.3 create mode 100644 getmntopts.c create mode 100644 humanize_number.3 create mode 100644 humanize_number.c create mode 100644 libutil.h create mode 100644 libutil.plist create mode 100644 libutil.txt create mode 100644 mntopts.h create mode 100644 pidfile.3 create mode 100644 pidfile.c create mode 100644 property.3 create mode 100644 property.c create mode 100644 realhostname.3 create mode 100644 realhostname.c create mode 100644 realhostname_sa.3 create mode 100644 trimdomain.3 create mode 100644 trimdomain.c create mode 100644 uucplock.3 create mode 100644 uucplock.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..19c1c9b --- /dev/null +++ b/Makefile @@ -0,0 +1,97 @@ +SHELL := /bin/sh + +VERSION = 1.0 +CC = cc +CPPFLAGS = -I$(SRCROOT) +CFLAGS = -Os -g3 -no-cpp-precomp -Wall $(RC_CFLAGS) +LDFLAGS = $(RC_CFLAGS) -install_name /usr/lib/libutil.dylib -compatibility_version $(VERSION) \ + -current_version $(VERSION) +INSTALL = install -c +LN = ln +MKDIR = mkdir +STRIP = strip +AR = ar +RANLIB = ranlib + +SRCROOT = . +OBJROOT = $(SRCROOT) +SYMROOT = $(OBJROOT) +DSTROOT = + +LIB := libutil1.0.dylib +SRCS := _secure_path.c getmntopts.c humanize_number.c \ + pidfile.c property.c realhostname.c trimdomain.c uucplock.c +HDRS := libutil.h mntopts.h +MAN3 := _secure_path.3 getmntopts.3 humanize_number.3 pidfile.3 \ + property.3 realhostname.3 realhostname_sa.3 trimdomain.3 uucplock.3 + +.SUFFIXES : +.SUFFIXES : .c .h .o + +.PHONY : +.PHONY : all installsrc installhdrs install clean installlib installman + +all : $(SYMROOT)/$(LIB) + +# +# xbs targets. +# +installsrc : + @if test ! -d $(SRCROOT); then \ + echo "$(INSTALL) -d $(SRCROOT)"; \ + $(INSTALL) -d $(SRCROOT); \ + fi + tar cf - . | (cd $(SRCROOT); tar xpf -) + @for i in `find $(SRCROOT) | grep "/\.svn$$"`; do \ + if test -d $$i ; then \ + echo "rm -rf $$i"; \ + rm -rf $$i; \ + fi; \ + done + +installhdrs : + $(INSTALL) -d $(DSTROOT)/usr/local/include + $(INSTALL) -m 0644 $(HDRS) $(DSTROOT)/usr/local/include + + +install : installhdrs installlib strip installman install-plist + +clean : + rm -f $(patsubst %.c,$(OBJROOT)/%.o,$(SRCS)) + rm -f $(SYMROOT)/*~ + rm -f $(SRCROOT)/.\#* + rm -f $(SYMROOT)/$(LIB) + +strip: + $(STRIP) -x -S $(DSTROOT)/usr/lib/$(LIB) + +# +# Internal targets and rules. +# +installlib : $(SYMROOT)/$(LIB) + $(INSTALL) -d $(DSTROOT)/usr/lib + $(INSTALL) -m 0755 $< $(DSTROOT)/usr/lib + $(LN) -fs libutil1.0.dylib $(DSTROOT)/usr/lib/libutil.dylib + +installman : + $(INSTALL) -d $(DSTROOT)/usr/local/share/man/man3 + @for i in $(MAN3); do\ + echo "$(INSTALL) -m 0444 $(SRCROOT)/$$i $(DSTROOT)/usr/local/share/man/man3/"; \ + $(INSTALL) -m 0444 $(SRCROOT)/$$i $(DSTROOT)/usr/local/share/man/man3; \ + done + +$(OBJROOT)/%.o : $(SRCROOT)/%.c \ + $(patsubst %.h,$(SRCROOT)/%.h,$(HDRS)) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@ + +$(SYMROOT)/$(LIB) : $(patsubst %.c,$(OBJROOT)/%.o,$(SRCS)) + $(CC) -dynamiclib $(LDFLAGS) -o $@ $? + +OSV = $(DSTROOT)/usr/local/OpenSourceVersions +OSL = $(DSTROOT)/usr/local/OpenSourceLicenses + +install-plist: + $(MKDIR) $(OSV) + $(INSTALL) $(SRCROOT)/libutil.plist $(OSV)/ + $(MKDIR) $(OSL) + $(INSTALL) $(SRCROOT)/libutil.txt $(OSL)/ diff --git a/_secure_path.3 b/_secure_path.3 new file mode 100644 index 0000000..7efb511 --- /dev/null +++ b/_secure_path.3 @@ -0,0 +1,75 @@ +.\" Copyright (c) 1997 David Nugent +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, is permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice immediately at the beginning of the file, without modification, +.\" this list of conditions, and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. This work was done expressly for inclusion into FreeBSD. Other use +.\" is permitted provided this notation is included. +.\" 4. Absolutely no warranty of function or purpose is made by the author +.\" David Nugent. +.\" 5. Modifications may be freely made to this file providing the above +.\" conditions are met. +.\" +.\" $FreeBSD: src/lib/libutil/_secure_path.3,v 1.13 2005/01/20 09:17:07 ru Exp $ +.\" +.Dd May 2, 1997 +.Os +.Dt _SECURE_PATH 3 +.Sh NAME +.Nm _secure_path +.Nd determine if a file appears to be secure +.Sh LIBRARY +.Lb libutil +.Sh SYNOPSIS +.In sys/types.h +.In libutil.h +.Ft int +.Fn _secure_path "const char *path" "uid_t uid" "gid_t gid" +.Sh DESCRIPTION +This function does some basic security checking on a given path. +It is intended to be used by processes running with root privileges +in order to decide whether or not to trust the contents of a given +file. +It uses a method often used to detect system compromise. +.Pp +A file is considered +.Sq secure +if it meets the following conditions: +.Bl -enum +.It +The file exists, and is a regular file (not a symlink, device +special or named pipe, etc.), +.It +Is not world writable. +.It +Is owned by the given uid or uid 0, if uid is not -1, +.It +Is not group writable or it has group ownership by the given +gid, if gid is not -1. +.El +.Sh RETURN VALUES +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 +function is used to log any failure of this function, including the +reason, at LOG_ERR priority. +.Sh SEE ALSO +.Xr lstat 2 , +.Xr syslog 3 +.Sh HISTORY +Code from which this function was derived was contributed to the +.Fx +project by Berkeley Software Design, Inc. +.Sh BUGS +The checks carried out are rudimentary and no attempt is made +to eliminate race conditions between use of this function and +access to the file referenced. diff --git a/_secure_path.c b/_secure_path.c new file mode 100644 index 0000000..69b0c64 --- /dev/null +++ b/_secure_path.c @@ -0,0 +1,73 @@ +/*- + * Based on code copyright (c) 1995,1997 by + * Berkeley Software Design, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, is permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice immediately at the beginning of the file, without modification, + * this list of conditions, and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. This work was done expressly for inclusion into FreeBSD. Other use + * is permitted provided this notation is included. + * 4. Absolutely no warranty of function or purpose is made by the authors. + * 5. Modifications may be freely made to this file providing the above + * conditions are met. + */ + +#include + +#include +#include + +#include +#include +#include +#include + +/* + * Check for common security problems on a given path + * It must be: + * 1. A regular file, and exists + * 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, + * -1 if security test failure + * 0 otherwise + */ + +int +_secure_path(const char *path, uid_t uid, gid_t gid) +{ + int r = -1; + struct stat sb; + const char *msg = NULL; + + if (lstat(path, &sb) < 0) { + if (errno == ENOENT) /* special case */ + r = -2; /* if it is just missing, skip the log entry */ + else + msg = "%s: cannot stat %s: %m"; + } + else if (!S_ISREG(sb.st_mode)) + msg = "%s: %s is not a regular file"; + else if (sb.st_mode & S_IWOTH) + msg = "%s: %s is world writable"; + else if ((int)uid != -1 && sb.st_uid != uid && sb.st_uid != 0) { + if (uid == 0) + msg = "%s: %s is not owned by root"; + else + msg = "%s: %s is not owned by uid %d"; + } else if ((int)gid != -1 && sb.st_gid != gid && (sb.st_mode & S_IWGRP)) + msg = "%s: %s is group writeable by non-authorised groups"; + else + r = 0; + if (msg != NULL) + syslog(LOG_ERR, msg, "_secure_path", path, uid); + return r; +} diff --git a/getmntopts.3 b/getmntopts.3 new file mode 100644 index 0000000..dde6fe4 --- /dev/null +++ b/getmntopts.3 @@ -0,0 +1,221 @@ +.\" $NetBSD: getmntopts.3,v 1.7 2004/02/24 15:12:51 wiz Exp $ +.\" +.\" Copyright (c) 1994 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)getmntopts.3 8.3 (Berkeley) 3/30/95 +.\" +.Dd April 11, 2003 +.Dt GETMNTOPTS 3 +.Os +.Sh NAME +.Nm getmntopts +.Nd scan mount options +.Sh LIBRARY +.Lb libutil +.Sh SYNOPSIS +.In mntopts.h +.Ft mntoptparse_t +.Fn getmntopts "const char *options" "const struct mntopt *mopts" "int *flagp" "int *altflagp" +.Ft const char * +.Fn getmntoptstr "mntoptparse_t mp" "const char *opt" +.Ft long +.Fn getmntoptnum "mntoptparse_t mp" "const char *opt" +.Ft void +.Fn freemntopts "mntoptparse_t mp" +.Sh DESCRIPTION +The +.Fn getmntopts +function takes a comma separated option list and a list +of valid option names, and computes the bitmask +corresponding to the requested set of options. +.Pp +The string +.Ar options +is broken down into a sequence of comma separated tokens. +Each token is looked up in the table described by +.Ar mopts +and the bits in +the word referenced by either +.Ar flagp +or +.Ar altflagp +(depending on the +.Dv m_altloc +field of the option's table entry) +are updated. +The flag words are not initialized by +.Fn getmntopts . +The table, +.Ar mopts , +has the following format: +.Bd -literal +struct mntopt { + const char *m_option; /* option name */ + int m_inverse; /* is this a negative option, e.g., "dev" */ + int m_flag; /* bit to set, e.g., MNT_RDONLY */ + int m_altloc; /* non-zero to use altflagp rather than flagp */ +}; +.Ed +.Pp +The members of this structure are: +.Bl -tag -width m_inverse +.It Fa m_option +the option name, +for example +.Dq suid . +.It Fa m_inverse +tells +.Fn getmntopts +that the name has the inverse meaning of the bit. +For example, +.Dq suid +is the string, whereas the mount flag is +.Dv MNT_NOSUID . +In this case, the sense of the string and the flag +are inverted, so the +.Fa m_inverse +flag should be set. +.It Fa m_flag +the value of the bit to be set or cleared in +the flag word when the option is recognized. +The bit is set when the option is discovered, +but cleared if the option name was preceded +by the letters +.Dq no . +The +.Fa m_inverse +flag causes these two operations to be reversed. +.It Fa m_altloc +the bit should be set or cleared in +.Ar altflagp +rather than +.Ar flagp . +.El +.Pp +Each of the user visible +.Dv MNT_ +flags has a corresponding +.Dv MOPT_ +macro which defines an appropriate +.Li "struct mntopt" +entry. +To simplify the program interface and ensure consistency across all +programs, a general purpose macro, +.Dv MOPT_STDOPTS , +is defined which contains an entry for all the generic VFS options. +In addition, the macros +.Dv MOPT_FORCE +and +.Dv MOPT_UPDATE +exist to enable the +.Dv MNT_FORCE +and +.Dv MNT_UPDATE +flags to be set. +Finally, the table must be terminated by an entry with a +.Dv NULL +first element. +.Pp +The +.Fn getmntoptstr +function returns the string value of the named option, if such a value +was set it the option string. +.Pp +The +.Fn getmntoptnum +returns the long value of the named option, if such a value was set it the +option string. +It prints an error message and exits if the value was not +set, or could not be converted from a string to a long. +.Pp +The +.Fn freemntopts +frees the storage used by +.Fn getmntopts . +.Sh EXAMPLES +Most commands will use the standard option set. +Local filesystems which support the +.Dv MNT_UPDATE +flag, would also have an +.Dv MOPT_UPDATE +entry. +This can be declared and used as follows: +.Bd -literal +#include \*[Lt]mntopts.h\*[Gt] + +static const struct mntopt mopts[] = { + MOPT_STDOPTS, + MOPT_UPDATE, + { NULL } +}; + +... +long val; +mntflags = mntaltflags = 0; +mntoptparse_t mp; +... +if ((mp = getmntopts(options, mopts, \*[Am]mntflags, \*[Am]mntaltflags)) == NULL) + err(1, NULL); +... +val = getmntoptnum(mp, "rsize"); +freemntopts(mp); +.Ed +.Sh RETURN VALUE +.Fn getmntopts +returns +.Dv NULL +if an error occurred. +.Fn getmntoptstr +returns +.Dv NULL +if the option does not have an argument, or the option string. +.Fn getmntoptnum +returns \-1 if an error occurred and +.Va getmnt_silent +is set. +.Sh DIAGNOSTICS +If the external integer variable +.Va getmnt_silent +is non-zero then the +.Fn getmntopts +function displays an error message and exits if an +unrecognized option is encountered. +By default +.Va getmnt_silent +is zero. +.Sh SEE ALSO +.Xr err 3 , +.Xr mount 8 +.Sh HISTORY +The +.Fn getmntopts +function appeared in +.Bx 4.4 . +It was moved to the utilities library and enhanced to retrieve option +values in +.Nx 2.0 . diff --git a/getmntopts.c b/getmntopts.c new file mode 100644 index 0000000..20d89bd --- /dev/null +++ b/getmntopts.c @@ -0,0 +1,188 @@ +/* $NetBSD: getmntopts.c,v 1.3 2003/08/07 16:44:58 agc Exp $ */ + +/*- + * Copyright (c) 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)getmntopts.c 8.3 (Berkeley) 3/29/95"; +#else +__RCSID("$NetBSD: getmntopts.c,v 1.3 2003/08/07 16:44:58 agc Exp $"); +#endif +#endif /* not lint */ + +#include + +#include +#include +#include +#include +#include + +#include + +int getmnt_silent = 0; + +static const char errmsg[] = "-o %s: option not supported"; + +struct mntoptparse { + const char *options; + const struct mntopt *mopts; + char *optbuf; + char **optarg; +}; + +const char * +getmntoptstr(mntoptparse_t mp, const char *opt) +{ + const struct mntopt *m; + + for (m = mp->mopts; m->m_option != NULL; m++) + if (strcasecmp(opt, m->m_option) == 0) + break; + + if (m->m_option == NULL) { + if (getmnt_silent == 0) + errx(1, errmsg, opt); + else + return NULL; + } + + return mp->optarg[m - mp->mopts]; +} + +long +getmntoptnum(mntoptparse_t mp, const char *opt) +{ + char *ep; + long rv; + void (*fun)(int, const char *, ...) = NULL; + const char *val = getmntoptstr(mp, opt); + + if (val == NULL) { + if (getmnt_silent == 0) + errx(1, "Missing %s argument", opt); + else + return -1; + } + + errno = 0; + rv = strtol(val, &ep, 0); + + if (*ep) + fun = errx; + + if (errno == ERANGE && (rv == LONG_MAX || rv == LONG_MIN)) + fun = err; + + if (fun) { + if (getmnt_silent != 0) + return -1; + (*fun)(1, "Invalid %s argument `%s'", opt, val); + } + return rv; +} + +void +freemntopts(mntoptparse_t mp) +{ + free(mp->optbuf); + free(mp->optarg); + free(mp); +} + +mntoptparse_t +getmntopts(const char *options, const struct mntopt *m0, int *flagp, + int *altflagp) +{ + const struct mntopt *m; + int negative; + char *opt, *p, *ctx = NULL; + int *thisflagp; + size_t nopts; + mntoptparse_t mp; + + for (nopts = 0, m = m0; m->m_option != NULL; ++m, nopts++) + continue; + + if ((mp = malloc(sizeof(struct mntoptparse))) == NULL) + return NULL; + + /* Copy option string, since it is about to be torn asunder... */ + if ((mp->optbuf = strdup(options)) == NULL) { + free(mp); + return NULL; + } + + if ((mp->optarg = calloc(nopts, sizeof(char *))) == NULL) { + free(mp->optbuf); + free(mp); + return NULL; + } + + mp->mopts = m0; + mp->options = options; + + for (opt = mp->optbuf; (opt = strtok_r(opt, ",", &ctx)) != NULL; opt = NULL) { + /* Check for "no" prefix. */ + if (opt[0] == 'n' && opt[1] == 'o') { + negative = 1; + opt += 2; + } else + negative = 0; + + /* + * for options with assignments in them (ie. quotas) + * ignore the assignment as it's handled elsewhere + */ + p = strchr(opt, '='); + if (p) { + *p++ = '\0'; + } + + /* Scan option table. */ + for (m = m0; m->m_option != NULL; ++m) + if (strcasecmp(opt, m->m_option) == 0) + break; + + /* Save flag, or fail if option is not recognised. */ + if (m->m_option) { + mp->optarg[m - m0] = p; + thisflagp = m->m_altloc ? altflagp : flagp; + if (negative == m->m_inverse) + *thisflagp |= m->m_flag; + else + *thisflagp &= ~m->m_flag; + } else if (!getmnt_silent) { + errx(1, errmsg, opt); + } + } + return mp; +} diff --git a/humanize_number.3 b/humanize_number.3 new file mode 100644 index 0000000..aa712a7 --- /dev/null +++ b/humanize_number.3 @@ -0,0 +1,148 @@ +.\" $NetBSD: humanize_number.3,v 1.4 2003/04/16 13:34:37 wiz Exp $ +.\" $FreeBSD: src/lib/libutil/humanize_number.3,v 1.8 2005/04/10 12:15:25 delphij Exp $ +.\" +.\" Copyright (c) 1999, 2002 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Luke Mewburn and by Tomas Svensson. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the 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. +.\" +.Dd May 25, 2004 +.Dt HUMANIZE_NUMBER 3 +.Os +.Sh NAME +.Nm humanize_number +.Nd format a number into a human readable form +.Sh LIBRARY +.Lb libutil +.Sh SYNOPSIS +.In libutil.h +.Ft int +.Fo humanize_number +.Fa "char *buf" "size_t len" "int64_t number" "const char *suffix" +.Fa "int scale" "int flags" +.Fc +.Sh DESCRIPTION +The +.Fn humanize_number +function formats the signed 64-bit quantity given in +.Fa number +into +.Fa buffer . +A space and then +.Fa suffix +is appended to the end. +The buffer pointed to by +.Fa buffer +must be at least +.Fa len +bytes long. +.Pp +If the formatted number (including +.Fa suffix ) +would be too long to fit into +.Fa buffer , +then divide +.Fa number +by 1024 until it will. +In this case, prefix +.Fa suffix +with the appropriate SI designator. +.Pp +The prefixes are: +.Bl -column "Prefix" "Description" "Multiplier" -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 +.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 . +To use a specific prefix, specify this as +.Fa scale +(multiplier = 1024 ^ scale). +This cannot be combined with any of the +.Fa scale +flags below. +.Pp +The following flags may be passed in +.Fa scale : +.Bl -tag -width ".Dv HN_DIVISOR_1000" -offset indent +.It Dv HN_AUTOSCALE +Format the buffer using the lowest multiplier possible. +.It Dv HN_GETSCALE +Return the prefix index number (the number of times +.Fa number +must be divided to fit) instead of formatting it to the buffer. +.El +.Pp +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. +.It Dv HN_NOSPACE +Do not put a space between +.Fa number +and the prefix. +.It Dv HN_B +Use +.Ql B +(bytes) as prefix if the original result does not have a prefix. +.It Dv HN_DIVISOR_1000 +Divide +.Fa number +with 1000 instead of 1024. +.El +.Sh RETURN VALUES +The +.Fn humanize_number +function returns the number of characters stored in +.Fa buffer +(excluding the terminating +.Dv NUL ) +upon success, or \-1 upon failure. +If +.Dv HN_GETSCALE +is specified, the prefix index number will be returned instead. +.Sh HISTORY +The +.Fn humanize_number +function first appeared in +.Nx 2.0 . diff --git a/humanize_number.c b/humanize_number.c new file mode 100644 index 0000000..8ab419b --- /dev/null +++ b/humanize_number.c @@ -0,0 +1,147 @@ +/* $NetBSD: humanize_number.c,v 1.8 2004/07/27 01:56:24 enami Exp $ */ + +/* + * Copyright (c) 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center, by Luke Mewburn and by Tomas Svensson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the 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. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +int +humanize_number(char *buf, size_t len, int64_t bytes, + const char *suffix, int scale, int flags) +{ + const char *prefixes, *sep; + int b, i, r, maxscale, s1, s2, sign; + int64_t divisor, max; + size_t baselen; + + assert(buf != NULL); + assert(suffix != NULL); + assert(scale >= 0); + + if (flags & HN_DIVISOR_1000) { + /* SI for decimal multiplies */ + divisor = 1000; + if (flags & HN_B) + prefixes = "B\0k\0M\0G\0T\0P\0E"; + else + prefixes = "\0\0k\0M\0G\0T\0P\0E"; + } else { + /* + * binary multiplies + * XXX IEC 60027-2 recommends Ki, Mi, Gi... + */ + divisor = 1024; + if (flags & HN_B) + prefixes = "B\0K\0M\0G\0T\0P\0E"; + else + prefixes = "\0\0K\0M\0G\0T\0P\0E"; + } + +#define SCALE2PREFIX(scale) (&prefixes[(scale) << 1]) + maxscale = 7; + + 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) { + sign = -1; + bytes *= -100; + baselen = 3; /* sign, digit, prefix */ + } else { + sign = 1; + bytes *= 100; + baselen = 2; /* digit, prefix */ + } + if (flags & HN_NOSPACE) + sep = ""; + else { + sep = " "; + baselen++; + } + baselen += strlen(suffix); + + /* Check if enough room for `x y' + suffix + `\0' */ + if (len < baselen + 1) + return (-1); + + if (scale & (HN_AUTOSCALE | HN_GETSCALE)) { + /* See if there is additional columns can be used. */ + for (max = 100, i = len - baselen; i-- > 0;) + max *= 10; + + for (i = 0; bytes >= max && i < maxscale; i++) + bytes /= divisor; + + if (scale & HN_GETSCALE) + return (i); + } else + for (i = 0; i < scale && i < maxscale; i++) + bytes /= 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; + 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, "%lld%s%s%s", + /* LONGLONG */ + (long long)(sign * ((bytes + 50) / 100)), + sep, SCALE2PREFIX(i), suffix); + + return (r); +} diff --git a/libutil.h b/libutil.h new file mode 100644 index 0000000..7135673 --- /dev/null +++ b/libutil.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) 1996 Peter Wemm . + * All rights reserved. + * Copyright (c) 2002 Networks Associates Technology, Inc. + * All rights reserved. + * + * Portions of this software were developed for the FreeBSD Project by + * ThinkSec AS and NAI Labs, the Security Research Division of Network + * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 + * ("CBOSS"), as part of the DARPA CHATS research program. + * + * Redistribution and use in source and binary forms, with or without + * modification, is permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * 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. + * + * $FreeBSD: src/lib/libutil/libutil.h,v 1.42 2006/02/18 11:25:28 des Exp $ + */ + +#ifndef _LIBUTIL_H_ +#define _LIBUTIL_H_ + +#include +#define PROPERTY_MAX_NAME 64 +#define PROPERTY_MAX_VALUE 512 + +/* for properties.c */ +typedef struct _property { + struct _property *next; + char *name; + char *value; +} *properties; + +#ifdef _SYS_PARAM_H_ +/* for pidfile.c */ +struct pidfh { + int pf_fd; + char pf_path[MAXPATHLEN + 1]; + dev_t pf_dev; + ino_t pf_ino; +}; +#endif + +/* Avoid pulling in all the include files for no need */ +struct termios; +struct winsize; +struct utmp; +struct in_addr; + +__BEGIN_DECLS +void clean_environment(const char * const *_white, + const char * const *_more_white); +int extattr_namespace_to_string(int _attrnamespace, char **_string); +int extattr_string_to_namespace(const char *_string, int *_attrnamespace); +void login(struct utmp *_ut); +int login_tty(int _fd); +int logout(const char *_line); +void logwtmp(const char *_line, const char *_name, const char *_host); +void trimdomain(char *_fullhost, int _hostsize); +int openpty(int *_amaster, int *_aslave, char *_name, + struct termios *_termp, struct winsize *_winp); +int forkpty(int *_amaster, char *_name, + struct termios *_termp, struct winsize *_winp); +int humanize_number(char *_buf, size_t _len, int64_t _number, + const char *_suffix, int _scale, int _flags); +const char *uu_lockerr(int _uu_lockresult); +int uu_lock(const char *_ttyname); +int uu_unlock(const char *_ttyname); +int uu_lock_txfr(const char *_ttyname, pid_t _pid); +int _secure_path(const char *_path, uid_t _uid, gid_t _gid); +properties properties_read(int fd); +void properties_free(properties list); +char *property_find(properties list, const char *name); +char *auth_getval(const char *name); +int realhostname(char *host, size_t hsize, const struct in_addr *ip); +struct sockaddr; +int realhostname_sa(char *host, size_t hsize, struct sockaddr *addr, + int addrlen); + +int kld_isloaded(const char *name); +int kld_load(const char *name); + +#ifdef _STDIO_H_ /* avoid adding new includes */ +char *fparseln(FILE *, size_t *, size_t *, const char[3], int); +#endif + +#ifdef _PWD_H_ +int pw_copy(int _ffd, int _tfd, const struct passwd *_pw, struct passwd *_old_pw); +struct passwd *pw_dup(const struct passwd *_pw); +int pw_edit(int _notsetuid); +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); +int pw_mkdb(const char *_user); +int pw_lock(void); +struct passwd *pw_scan(const char *_line, int _flags); +const char *pw_tempname(void); +int pw_tmp(int _mfd); +#endif + +#ifdef _SYS_PARAM_H_ +struct pidfh *pidfile_open(const char *path, mode_t mode, pid_t *pidptr); +int pidfile_write(struct pidfh *pfh); +int pidfile_close(struct pidfh *pfh); +int pidfile_remove(struct pidfh *pfh); +#endif + +__END_DECLS + +#define UU_LOCK_INUSE (1) +#define UU_LOCK_OK (0) +#define UU_LOCK_OPEN_ERR (-1) +#define UU_LOCK_READ_ERR (-2) +#define UU_LOCK_CREAT_ERR (-3) +#define UU_LOCK_WRITE_ERR (-4) +#define UU_LOCK_LINK_ERR (-5) +#define UU_LOCK_TRY_ERR (-6) +#define UU_LOCK_OWNER_ERR (-7) + +/* return values from realhostname() */ +#define HOSTNAME_FOUND (0) +#define HOSTNAME_INCORRECTNAME (1) +#define HOSTNAME_INVALIDADDR (2) +#define HOSTNAME_INVALIDNAME (3) + +/* fparseln(3) */ +#define FPARSELN_UNESCESC 0x01 +#define FPARSELN_UNESCCONT 0x02 +#define FPARSELN_UNESCCOMM 0x04 +#define FPARSELN_UNESCREST 0x08 +#define FPARSELN_UNESCALL 0x0f + +/* pw_scan() */ +#define PWSCAN_MASTER 0x01 +#define PWSCAN_WARN 0x02 + +/* humanize_number(3) */ +#define HN_DECIMAL 0x01 +#define HN_NOSPACE 0x02 +#define HN_B 0x04 +#define HN_DIVISOR_1000 0x08 + +#define HN_GETSCALE 0x10 +#define HN_AUTOSCALE 0x20 + +#endif /* !_LIBUTIL_H_ */ diff --git a/libutil.plist b/libutil.plist new file mode 100644 index 0000000..43785e7 --- /dev/null +++ b/libutil.plist @@ -0,0 +1,36 @@ + + + + + + OpenSourceCVS + cvs -d freebsdanoncvs@anoncvs.FreeBSD.org:/home/ncvs co libutil + OpenSourceImportDate + 2006-05-20 + OpenSourceLicense + BSD + OpenSourceLicenseFile + libutil.txt + OpenSourceProject + libutil + OpenSourceVersion + 2005-02-13 + OpenSourceWebsiteURL + http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libutil/ + + + OpenSourceImportDate + 2006-05-20 + OpenSourceLicense + BSD + OpenSourceLicenseFile + libutil.txt + OpenSourceProject + libutil + OpenSourceVersion + 1.3 + OpenSourceWebsiteURL + http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/lib/libutil/getmntopts.c?rev=1.3 + + + diff --git a/libutil.txt b/libutil.txt new file mode 100644 index 0000000..02cb993 --- /dev/null +++ b/libutil.txt @@ -0,0 +1,238 @@ +_secure_path.c: +/*- + * Based on code copyright (c) 1995,1997 by + * Berkeley Software Design, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, is permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice immediately at the beginning of the file, without modification, + * this list of conditions, and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. This work was done expressly for inclusion into FreeBSD. Other use + * is permitted provided this notation is included. + * 4. Absolutely no warranty of function or purpose is made by the authors. + * 5. Modifications may be freely made to this file providing the above + * conditions are met. + */ + +fparseln.c: +/* + * Copyright (c) 1997 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. + */ + +humanize_number.c: +/* + * Copyright (c) 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center, by Luke Mewburn and by Tomas Svensson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the 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. + */ + +pidfile.c: +/*- + * Copyright (c) 2005 Pawel Jakub Dawidek + * 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. + */ + +property.c: +/* + * + * Simple property list handling code. + * + * Copyright (c) 1998 + * Jordan "Perky" Hubbard. 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, + * verbatim and that no modifications are made prior to this + * point in the 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 HIS PETS 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, LIFE 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. + */ + +realhostname.c: +/*- + * Copyright (c) 1999 Brian Somers + * 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 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. + */ + +trimdomain.c: +/*- + * Copyright (c) 2001 Brian Somers + * Based on original work by Atsushi Murai + * 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 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. + * + */ + +uucplock.c: +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ diff --git a/mntopts.h b/mntopts.h new file mode 100644 index 0000000..0104178 --- /dev/null +++ b/mntopts.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* $NetBSD: mntopts.h,v 1.7 2006/02/12 01:32:06 chs Exp $ */ + +/*- + * Copyright (c) 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mntopts.h 8.7 (Berkeley) 3/29/95 + */ +#ifndef _MNTOPTS_H_ +#define _MNTOPTS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct mntopt { + const char *m_option; /* option name */ + int m_inverse; /* if a negative option, eg "dev" */ + int m_flag; /* bit to set, eg. MNT_RDONLY */ + int m_altloc; /* 1 => set bit in altflags */ +}; + +/* User-visible MNT_ flags. */ +#define MOPT_ASYNC { "async", 0, MNT_ASYNC, 0 } +#define MOPT_NODEV { "dev", 1, MNT_NODEV, 0 } +#define MOPT_NOEXEC { "exec", 1, MNT_NOEXEC, 0 } +#define MOPT_NOSUID { "suid", 1, MNT_NOSUID, 0 } +#define MOPT_RDONLY { "rdonly", 0, MNT_RDONLY, 0 } +#define MOPT_SYNC { "sync", 0, MNT_SYNCHRONOUS, 0 } +#define MOPT_UNION { "union", 0, MNT_UNION, 0 } +#define MOPT_USERQUOTA { "userquota", 0, 0, 0 } +#define MOPT_GROUPQUOTA { "groupquota", 0, 0, 0 } +#define MOPT_BROWSE { "browse", 1, MNT_DONTBROWSE, 0 } +#define MOPT_AUTOMOUNTED { "automounted",0, MNT_AUTOMOUNTED, 0 } +#define MOPT_DEFWRITE { "defwrite", 0, MNT_DEFWRITE, 0} +#define MOPT_NOATIME { "atime", 1, MNT_NOATIME, 0} +#define MOPT_IGNORE_OWNERSHIP { "owners", 1, MNT_IGNORE_OWNERSHIP, 0} +/* alias the deprecated name for compatibility */ +#define MOPT_PERMISSIONS { "perm", 1, MNT_IGNORE_OWNERSHIP, 0} +#define MOPT_QUARANTINE { "quarantine", 0, MNT_QUARANTINE, 0} + +/* Control flags. */ +#define MOPT_FORCE { "force", 0, MNT_FORCE, 0 } +#define MOPT_UPDATE { "update", 0, MNT_UPDATE, 0 } +#define MOPT_RELOAD { "reload", 0, MNT_RELOAD, 0 } + +/* Support for old-style "ro", "rw" flags. */ +#define MOPT_RO { "ro", 0, MNT_RDONLY, 0 } +#define MOPT_RW { "rw", 1, MNT_RDONLY, 0 } + +/* This is parsed by mount(8), but is ignored by specific mount_*(8)s. */ +#define MOPT_AUTO { "auto", 0, 0, 0 } + +#define MOPT_FSTAB_COMPAT \ + MOPT_RO, \ + MOPT_RW, \ + MOPT_AUTO + +/* Standard options which all mounts can understand. */ +#define MOPT_STDOPTS \ + MOPT_USERQUOTA, \ + MOPT_GROUPQUOTA, \ + MOPT_FSTAB_COMPAT, \ + MOPT_NODEV, \ + MOPT_NOEXEC, \ + MOPT_NOSUID, \ + MOPT_RDONLY, \ + MOPT_UNION, \ + MOPT_BROWSE, \ + MOPT_AUTOMOUNTED, \ + MOPT_DEFWRITE, \ + MOPT_NOATIME, \ + MOPT_PERMISSIONS, \ + MOPT_IGNORE_OWNERSHIP, \ + MOPT_QUARANTINE + +typedef struct mntoptparse *mntoptparse_t; +mntoptparse_t getmntopts(const char *, const struct mntopt *, int *, int *); +const char *getmntoptstr(mntoptparse_t, const char *); +long getmntoptnum(mntoptparse_t, const char *); +void freemntopts(mntoptparse_t); + +extern int getmnt_silent; + +#ifdef __cplusplus +} +#endif + +#endif /* _MNTOPTS_H_ */ diff --git a/pidfile.3 b/pidfile.3 new file mode 100644 index 0000000..070ddab --- /dev/null +++ b/pidfile.3 @@ -0,0 +1,249 @@ +.\" Copyright (c) 2005 Pawel Jakub Dawidek +.\" 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: src/lib/libutil/pidfile.3,v 1.5 2006/03/04 15:20:28 keramida Exp $ +.\" +.Dd August 22, 2005 +.Dt PIDFILE 3 +.Os +.Sh NAME +.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/param.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_close "struct pidfh *pfh" +.Ft int +.Fn pidfile_remove "struct pidfh *pfh" +.Sh DESCRIPTION +The +.Nm pidfile +family of functions allows daemons to handle PID files. +It uses +.Xr flock 2 +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 with the +.Xr flock 2 +system call. +If a file can not be locked, a PID of an already running daemon is returned in +the +.Fa pidptr +argument (if it is not +.Dv NULL ) . +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 +.Fa path +argument is +.Dv NULL , +.Pa /var/run/ Ns Ao Va progname Ac Ns Pa .pid +file will be used. +.Pp +The +.Fn pidfile_write +function writes process' PID into a previously opened file. +.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 +.Fn pidfile_remove +function closes and removes a pidfile. +.Sh RETURN VALUES +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. +.Rv -std pidfile_write pidfile_close pidfile_remove +.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 +and +.Fn pidfile_close +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"); +} + +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. +.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 flock 2 , +.Xr fstat 2 , +.Xr write 2 , +and +.Xr unlink 2 +calls. +.Sh SEE ALSO +.Xr flock 2 , +.Xr open 2 , +.Xr daemon 3 +.Sh AUTHORS +.An -nosplit +The +.Nm pidfile +functionality is based on ideas from +.An John-Mark Gurney Aq jmg@FreeBSD.org . +.Pp +The code and manual page was written by +.An Pawel Jakub Dawidek Aq pjd@FreeBSD.org . diff --git a/pidfile.c b/pidfile.c new file mode 100644 index 0000000..88b300e --- /dev/null +++ b/pidfile.c @@ -0,0 +1,243 @@ +/*- + * Copyright (c) 2005 Pawel Jakub Dawidek + * 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. + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static int _pidfile_remove(struct pidfh *pfh, int freeit); + +static int +pidfile_verify(struct pidfh *pfh) +{ + struct stat sb; + + if (pfh == NULL || pfh->pf_fd == -1) + return EINVAL; + /* + * 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 EINVAL; + return (0); +} + +static int +pidfile_read(const char *path, pid_t *pidptr) +{ + char buf[16], *endptr; + int error, fd, i; + + fd = open(path, O_RDONLY); + 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); + 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; + + pfh = malloc(sizeof(*pfh)); + if (pfh == NULL) + return (NULL); + + if (path == NULL) { + snprintf(pfh->pf_path, sizeof(pfh->pf_path), "/var/run/%s.pid", + getprogname()); + } else { + strlcpy(pfh->pf_path, path, sizeof(pfh->pf_path)); + } + if (strlen(pfh->pf_path) == sizeof(pfh->pf_path) - 1) { + free(pfh); + errno = ENAMETOOLONG; + return (NULL); + } + + /* + * 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. + */ + fd = open(pfh->pf_path, + O_WRONLY | O_CREAT | O_EXLOCK | O_TRUNC | O_NONBLOCK, mode); + if (fd == -1) { + if (errno == EWOULDBLOCK && pidptr != NULL) { + errno = pidfile_read(pfh->pf_path, pidptr); + if (errno == 0) + errno = EEXIST; + } + free(pfh); + return (NULL); + } + /* + * 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; + + /* + * Check remembered descriptor, so we don't overwrite some other + * file if pidfile was closed and descriptor reused. + */ + errno = pidfile_verify(pfh); + if (errno != 0) { + /* + * Don't close descriptor, because we are not sure if it's ours. + */ + 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; + + error = pidfile_verify(pfh); + if (error != 0) { + errno = error; + return (-1); + } + + if (close(pfh->pf_fd) == -1) + error = errno; + free(pfh); + if (error != 0) { + errno = error; + return (-1); + } + return (0); +} + +static int +_pidfile_remove(struct pidfh *pfh, int freeit) +{ + int error; + + error = pidfile_verify(pfh); + if (error != 0) { + errno = error; + return (-1); + } + + if (unlink(pfh->pf_path) == -1) + error = errno; + if (flock(pfh->pf_fd, LOCK_UN) == -1) { + if (error == 0) + 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); +} + +int +pidfile_remove(struct pidfh *pfh) +{ + + return (_pidfile_remove(pfh, 1)); +} diff --git a/property.3 b/property.3 new file mode 100644 index 0000000..79c787d --- /dev/null +++ b/property.3 @@ -0,0 +1,99 @@ +.\" +.\" Copyright (c) 1998 Jordan Hubbard +.\" +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD: src/lib/libutil/property.3,v 1.18 2005/01/20 09:17:07 ru Exp $ +.\" " +.Dd October 7, 1998 +.Os +.Dt PROPERTIES 3 +.Sh NAME +.Nm properties_read , +.Nm propery_find , +.Nm properties_free +.Nd "functions to allow creating simple property lists from ASCII file data" +.Sh LIBRARY +.Lb libutil +.Sh SYNOPSIS +.In sys/types.h +.In libutil.h +.Ft properties +.Fn properties_read "int fd" +.Ft char * +.Fn property_find "properties list" "const char *name" +.Ft void +.Fn properties_free "properties list" +.Sh DESCRIPTION +.Bd -literal +typedef struct _properties { + struct _properties *next; + char *name; + char *value; +} *properties; +.Ed +.Pp +The function +.Fn properties_read +reads +.Fa name = value +pairs from the file descriptor passed in +.Fa fd +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 +function returns the associated value string for the property named +.Fa name +if found, otherwise NULL. +The value returned may be up to +.Dv PROPERTY_MAX_VALUE +bytes in length. +.Pp +The +.Fn properties_free +function is used to free the structure returned by +.Fn properties_read +when it is no longer needed. +.Sh FILE FORMAT +Each property in the file is assumed to have the format of +.Fa name = value +where +.Fa name +is an alphanumeric string (and any punctuation not including the `=' character) +and +.Fa value +is an arbitary 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 +be a comment and will be ignored. +.Sh SEE ALSO +.Xr auth_getval 3 +.Sh AUTHORS +.An Jordan Hubbard +.Sh BUGS +Simplistic. diff --git a/property.c b/property.c new file mode 100644 index 0000000..6d1b7f7 --- /dev/null +++ b/property.c @@ -0,0 +1,257 @@ +/* + * + * Simple property list handling code. + * + * Copyright (c) 1998 + * Jordan "Perky" Hubbard. 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, + * verbatim and that no modifications are made prior to this + * point in the 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 HIS PETS 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, LIFE 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static properties +property_alloc(char *name, char *value) +{ + properties n; + + if ((n = (properties)malloc(sizeof(struct _property))) == NULL) + return (NULL); + n->next = NULL; + 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 +properties_read(int fd) +{ + properties head, ptr; + char hold_n[PROPERTY_MAX_NAME + 1]; + 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, last_state; + int ch = 0, blevel = 0; + + n = v = bp = max = 0; + head = ptr = NULL; + state = last_state = LOOK; + while (state != STOP) { + if (state != COMMIT) { + if (bp == max) { + last_state = state; + state = FILL; + } else + ch = buf[bp++]; + } + switch(state) { + case FILL: + if ((max = read(fd, buf, sizeof buf)) < 0) { + properties_free(head); + return (NULL); + } + 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 = 0; + } + continue; + + case LOOK: + if (isspace((unsigned char)ch)) + continue; + /* Allow shell or lisp style comments */ + else if (ch == '#' || ch == ';') { + state = COMMENT; + continue; + } + else if (isalnum((unsigned char)ch) || ch == '_') { + if (n >= PROPERTY_MAX_NAME) { + n = 0; + state = COMMENT; + } + else { + hold_n[n++] = ch; + state = NAME; + } + } + else + state = COMMENT; /* Ignore the rest of the line */ + break; + + case COMMENT: + if (ch == '\n') + state = LOOK; + break; + + case NAME: + if (ch == '\n' || !ch) { + hold_n[n] = '\0'; + hold_v[0] = '\0'; + v = n = 0; + state = COMMIT; + } + else if (isspace((unsigned char)ch)) + continue; + else if (ch == '=') { + hold_n[n] = '\0'; + v = n = 0; + state = VALUE; + } + else + hold_n[n++] = ch; + break; + + case VALUE: + if (v == 0 && ch == '\n') { + hold_v[v] = '\0'; + v = n = 0; + state = COMMIT; + } + else if (v == 0 && isspace((unsigned char)ch)) + continue; + else if (ch == '{') { + state = MVALUE; + ++blevel; + } + else if (ch == '\n' || !ch) { + hold_v[v] = '\0'; + v = n = 0; + state = COMMIT; + } + else { + if (v >= PROPERTY_MAX_VALUE) { + state = COMMENT; + v = n = 0; + break; + } + else + hold_v[v++] = ch; + } + break; + + case MVALUE: + /* multiline value */ + if (v >= PROPERTY_MAX_VALUE) { + warn("properties_read: value exceeds max length"); + state = COMMENT; + n = v = 0; + } + else if (ch == '}' && !--blevel) { + hold_v[v] = '\0'; + v = n = 0; + state = COMMIT; + } + else { + hold_v[v++] = ch; + if (ch == '{') + ++blevel; + } + break; + + case COMMIT: + 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; + v = n = 0; + break; + + case STOP: + /* we don't handle this here, but this prevents warnings */ + break; + } + } + if (head == NULL && (head = property_alloc(NULL, NULL)) == NULL) + return (NULL); + + return (head); +} + +char * +property_find(properties list, const char *name) +{ + 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); +} + +void +properties_free(properties list) +{ + properties tmp; + + while (list) { + tmp = list->next; + if (list->name) + free(list->name); + if (list->value) + free(list->value); + free(list); + list = tmp; + } +} diff --git a/realhostname.3 b/realhostname.3 new file mode 100644 index 0000000..3148e27 --- /dev/null +++ b/realhostname.3 @@ -0,0 +1,105 @@ +.\" Copyright (c) 1999 Brian Somers +.\" 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 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. +.\" +.\" $FreeBSD: src/lib/libutil/realhostname.3,v 1.10 2005/02/13 22:25:14 ru Exp $ +.\" +.Dd April 6, 1999 +.Os +.Dt REALHOSTNAME 3 +.Sh NAME +.Nm realhostname +.Nd "convert an IP number to the real host name" +.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" +.Sh DESCRIPTION +The function +.Fn realhostname +converts +.Ar ip +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 +.Ar ip . +.Pp +.Ar host +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 does not work both ways or if the host name is longer +than +.Ar hsize +bytes, +.Xr inet_ntoa 3 +is used to convert +.Ar ip +to an ASCII form. +.Pp +If the string written to +.Ar host +is +.Ar hsize +bytes long, +.Ar host +will not be NUL terminated. +.Sh RETURN VALUES +The +.Fn realhostname +function will return one of the following constants which are defined in +.In libutil.h : +.Pp +.Bl -tag -width XXX -offset XXX +.It Li HOSTNAME_FOUND +A valid host name was found. +.It Li HOSTNAME_INCORRECTNAME +A host name was found, but it did not resolve back to the passed +.Ar ip . +.Ar host +now contains the numeric value of +.Ar ip . +.It Li HOSTNAME_INVALIDADDR +.Ar ip +could not be resolved. +.Ar host +now contains the numeric value of +.Ar ip . +.It Li HOSTNAME_INVALIDNAME +A host name was found, but it could not be resolved back to any ip number. +.Ar host +now contains the numeric value of +.Ar ip . +.El +.Sh SEE ALSO +.Xr gethostbyaddr 3 , +.Xr gethostbyname 3 , +.Xr inet_ntoa 3 , +.Xr realhostname_sa 3 diff --git a/realhostname.c b/realhostname.c new file mode 100644 index 0000000..57bc651 --- /dev/null +++ b/realhostname.c @@ -0,0 +1,184 @@ +/*- + * Copyright (c) 1999 Brian Somers + * 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 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. + */ + +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include "libutil.h" + +struct sockinet { + u_char si_len; + u_char si_family; + u_short si_port; +}; + +int +realhostname(char *host, size_t hsize, const struct in_addr *ip) +{ + char trimmed[MAXHOSTNAMELEN]; + int result; + struct hostent *hp; + + result = HOSTNAME_INVALIDADDR; + hp = gethostbyaddr((const char *)ip, sizeof(*ip), AF_INET); + + if (hp != NULL) { + strlcpy(trimmed, hp->h_name, sizeof(trimmed)); + trimdomain(trimmed, strlen(trimmed)); + if (strlen(trimmed) <= hsize) { + char lookup[MAXHOSTNAMELEN]; + + strncpy(lookup, hp->h_name, sizeof(lookup) - 1); + lookup[sizeof(lookup) - 1] = '\0'; + hp = gethostbyname(lookup); + if (hp == NULL) + result = HOSTNAME_INVALIDNAME; + else for (; ; hp->h_addr_list++) { + if (*hp->h_addr_list == NULL) { + result = HOSTNAME_INCORRECTNAME; + break; + } + if (!memcmp(*hp->h_addr_list, ip, sizeof(*ip))) { + strncpy(host, trimmed, hsize); + return HOSTNAME_FOUND; + } + } + } + } + + strncpy(host, inet_ntoa(*ip), hsize); + + return result; +} + +int +realhostname_sa(char *host, size_t hsize, struct sockaddr *addr, int addrlen) +{ + int result, error; + char buf[NI_MAXHOST]; + + result = HOSTNAME_INVALIDADDR; + +#ifdef INET6 + /* 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)) { + struct sockaddr_in6 *sin6; + + sin6 = (struct sockaddr_in6 *)addr; + + 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 *)&lsin; + addrlen = lsin.sin_len; + } +#endif + + error = getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0, + NI_NAMEREQD); + if (error == 0) { + struct addrinfo hints, *res, *ores; + struct sockaddr *sa; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = addr->sa_family; + hints.ai_flags = AI_CANONNAME | AI_PASSIVE; + hints.ai_socktype = SOCK_STREAM; + + error = getaddrinfo(buf, NULL, &hints, &res); + if (error) { + result = HOSTNAME_INVALIDNAME; + goto numeric; + } + for (ores = res; ; res = res->ai_next) { + if (res == NULL) { + freeaddrinfo(ores); + result = HOSTNAME_INCORRECTNAME; + goto numeric; + } + sa = res->ai_addr; + if (sa == NULL) { + freeaddrinfo(ores); + result = HOSTNAME_INCORRECTNAME; + goto numeric; + } + if (sa->sa_len == addrlen && + sa->sa_family == addr->sa_family) { + ((struct sockinet *)sa)->si_port = ((struct 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; +#endif + if (!memcmp(sa, addr, sa->sa_len)) { + result = HOSTNAME_FOUND; + if (ores->ai_canonname == NULL) { + freeaddrinfo(ores); + goto numeric; + } + strlcpy(buf, ores->ai_canonname, + sizeof(buf)); + trimdomain(buf, hsize); + if (strlen(buf) > hsize && + addr->sa_family == AF_INET) { + freeaddrinfo(ores); + goto numeric; + } + strncpy(host, buf, hsize); + break; + } + } + } + freeaddrinfo(ores); + } else { + numeric: + if (getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0, + NI_NUMERICHOST) == 0) + strncpy(host, buf, hsize); + } + + return result; +} + + diff --git a/realhostname_sa.3 b/realhostname_sa.3 new file mode 100644 index 0000000..d1bf063 --- /dev/null +++ b/realhostname_sa.3 @@ -0,0 +1,133 @@ +.\" Copyright (C) 1995, 1996, 1997, 1998, 1999, and 2000 WIDE Project. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the project 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 PROJECT 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 PROJECT 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. +.\" +.\" Copyright (c) 1999 Brian Somers +.\" 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 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. +.\" +.\" $FreeBSD: src/lib/libutil/realhostname_sa.3,v 1.11 2005/02/13 22:25:14 ru Exp $ +.\" +.Dd January 11, 2000 +.Os +.Dt REALHOSTNAME_SA 3 +.Sh NAME +.Nm realhostname_sa +.Nd "convert a" +.Vt "struct sockaddr" +to the real host name +.Sh LIBRARY +.Lb libutil +.Sh SYNOPSIS +.In sys/types.h +.In netinet/in.h +.In libutil.h +.Ft int +.Fn realhostname_sa "char *host" "size_t hsize" "struct sockaddr *addr" "int addrlen" +.Sh DESCRIPTION +The function +.Fn realhostname_sa +converts +.Ar addr +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 +.Ar addr . +.Pp +.Ar host +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 does not work both ways or if the host name is longer +than +.Ar hsize +bytes, +.Xr getnameinfo 3 +with NI_NUMERICHOST specified, is used to convert +.Ar addr +to an ASCII form. +.Pp +If the string written to +.Ar host +is +.Ar hsize +bytes long, +.Ar host +will not be NUL terminated. +.Sh RETURN VALUES +The +.Fn realhostname_sa +function will return one of the following constants which are defined in +.In libutil.h : +.Pp +.Bl -tag -width XXX -offset XXX +.It Li HOSTNAME_FOUND +A valid host name was found. +.It Li HOSTNAME_INCORRECTNAME +A host name was found, but it did not resolve back to the passed +.Ar ip . +.Ar host +now contains the numeric value of +.Ar ip . +.It Li HOSTNAME_INVALIDADDR +.Ar ip +could not be resolved. +.Ar host +now contains the numeric value of +.Ar ip . +.It Li HOSTNAME_INVALIDNAME +A host name was found, but it could not be resolved back to any ip number. +.Ar host +now contains the numeric value of +.Ar ip . +.El +.Sh SEE ALSO +.Xr getaddrinfo 3 , +.Xr getnameinfo 3 , +.Xr realhostname 3 diff --git a/trimdomain.3 b/trimdomain.3 new file mode 100644 index 0000000..c370812 --- /dev/null +++ b/trimdomain.3 @@ -0,0 +1,85 @@ +.\" Copyright (c) 1999 Brian Somers +.\" 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 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. +.\" +.\" $FreeBSD: src/lib/libutil/trimdomain.3,v 1.8 2004/07/02 23:52:20 ru Exp $ +.\" +.Dd April 7, 1999 +.Os +.Dt TRIMDOMAIN 3 +.Sh NAME +.Nm trimdomain +.Nd "trim the current domain name from a host name" +.Sh LIBRARY +.Lb libutil +.Sh SYNOPSIS +.In sys/types.h +.In libutil.h +.Ft void +.Fn trimdomain "char *fullhost" "int hostsize" +.Sh DESCRIPTION +The function +.Fn trimdomain +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 +name is determined by calling +.Xr gethostname 3 +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 +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 +.Ar hostsize . +.Pp +If the passed +.Ar fullname +is actually a +.Dv DISPLAY +specification of the form +.Sm off +.Ar host . domain : nn Oo . +.Ar nn +.Oc +.Sm on +and the domain name is the same as the local domain name, +.Fn trimdomain +will remove the embedded domain name, copying the screen and display +numbers to the end of the base host name and resulting in +.Sm off +.Ar host : nn Op . Ar nn . +.Sm on +.Sh RETURN VALUES +The +.Fn trimdomain +function does not return a value. +.Sh SEE ALSO +.Xr gethostname 3 diff --git a/trimdomain.c b/trimdomain.c new file mode 100644 index 0000000..6287e84 --- /dev/null +++ b/trimdomain.c @@ -0,0 +1,114 @@ +/*- + * Copyright (c) 2001 Brian Somers + * Based on original work by Atsushi Murai + * 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 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. + * + */ + +#include + +#include + +#include +#include +#include + +static int isDISP(const char *); + +/*- + * Trim the current domain name from fullhost, but only if the result + * is less than or equal to hostsize in length. + * + * This function understands $DISPLAY type fullhosts. + * + * For example: + * + * trimdomain("abcde.my.domain", 5) -> "abcde" + * trimdomain("abcde.my.domain", 4) -> "abcde.my.domain" + * trimdomain("abcde.my.domain:0.0", 9) -> "abcde:0.0" + * trimdomain("abcde.my.domain:0.0", 8) -> "abcde.my.domain:0.0" + */ +void +trimdomain(char *fullhost, int hostsize) +{ + static size_t dlen; + static int first = 1; + static char domain[MAXHOSTNAMELEN]; + char *end, *s; + size_t len; + + if (first) { + /* XXX: Should we assume that our domain is this persistent ? */ + first = 0; + if (gethostname(domain, sizeof(domain) - 1) == 0 && + (s = strchr(domain, '.')) != NULL) + memmove(domain, s + 1, strlen(s + 1) + 1); + else + domain[0] = '\0'; + dlen = strlen(domain); + } + + if (domain[0] == '\0') + return; + + s = fullhost; + end = s + hostsize + 1; + 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'; + } 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); + } + } + } +} + +/* + * Is the given string NN or NN.NN where ``NN'' is an all-numeric string ? + */ +static int +isDISP(const char *disp) +{ + size_t w; + int res; + + w = strspn(disp, "0123456789"); + res = 0; + if (w > 0) { + if (disp[w] == '\0') + res = 1; /* NN */ + else if (disp[w] == '.') { + disp += w + 1; + w = strspn(disp, "0123456789"); + if (w > 0 && disp[w] == '\0') + res = 1; /* NN.NN */ + } + } + return (res); +} diff --git a/uucplock.3 b/uucplock.3 new file mode 100644 index 0000000..7ed6bcb --- /dev/null +++ b/uucplock.3 @@ -0,0 +1,183 @@ +.\" +.\" Copyright (c) 1996 Brian Somers +.\" +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD: src/lib/libutil/uucplock.3,v 1.19 2005/02/13 22:25:14 ru Exp $ +.\" " +.Dd March 30, 1997 +.Os +.Dt UUCPLOCK 3 +.Sh NAME +.Nm uu_lock , +.Nm uu_unlock , +.Nm uu_lockerr +.Nd acquire and release control of a serial device +.Sh LIBRARY +.Lb libutil +.Sh SYNOPSIS +.In sys/types.h +.In libutil.h +.Ft int +.Fn uu_lock "const char *ttyname" +.Ft int +.Fn uu_lock_txfr "const char *ttyname" "pid_t pid" +.Ft int +.Fn uu_unlock "const char *ttyname" +.Ft const char * +.Fn uu_lockerr "int uu_lockresult" +.Sh DESCRIPTION +The +.Fn uu_lock +function attempts to create a lock file called +.Pa /var/spool/lock/LCK.. +with a suffix given by the passed +.Fa ttyname . +If the file already exists, it is expected to contain the process +id of the locking program. +.Pp +If the file does not already exist, or the owning process given by +the process id found in the lock file is no longer running, +.Fn uu_lock +will write its own process id into the file and return success. +.Pp +.Fn uu_lock_txfr +transfers lock ownership to another process. +.Fn uu_lock +must have previously been successful. +.Pp +.Fn uu_unlock +removes the lockfile created by +.Fn uu_lock +for the given +.Fa ttyname . +Care should be taken that +.Fn uu_lock +was successful before calling +.Fn uu_unlock . +.Pp +.Fn uu_lockerr +returns an error string representing the error +.Fa uu_lockresult , +as returned from +.Fn uu_lock . +.Sh RETURN VALUES +.Fn uu_unlock +returns 0 on success and -1 on failure. +.Pp +.Fn uu_lock +may return any of the following values: +.Pp +.Dv UU_LOCK_INUSE : +The lock is in use by another process. +.Pp +.Dv UU_LOCK_OK : +The lock was successfully created. +.Pp +.Dv UU_LOCK_OPEN_ERR : +The lock file could not be opened via +.Xr open 2 . +.Pp +.Dv UU_LOCK_READ_ERR : +The lock file could not be read via +.Xr read 2 . +.Pp +.Dv UU_LOCK_CREAT_ERR : +Cannot create temporary lock file via +.Xr creat 2 . +.Pp +.Dv UU_LOCK_WRITE_ERR : +The current process id could not be written to the lock file via a call to +.Xr write 2 . +.Pp +.Dv UU_LOCK_LINK_ERR : +Cannot link temporary lock file via +.Xr link 2 . +.Pp +.Dv UU_LOCK_TRY_ERR : +Locking attempts are failed after 5 tries. +.Pp +If a value of +.Dv UU_LOCK_OK +is passed to +.Fn uu_lockerr , +an empty string is returned. +Otherwise, a string specifying +the reason for failure is returned. +.Fn uu_lockerr +uses the current value of +.Va errno +to determine the exact error. +Care should be made not to allow +.Va errno +to be changed between calls to +.Fn uu_lock +and +.Fn uu_lockerr . +.Pp +.Fn uu_lock_txfr +may return any of the following values: +.Pp +.Dv UU_LOCK_OK : +The transfer was successful. +The specified process now holds the device +lock. +.Pp +.Dv UU_LOCK_OWNER_ERR : +The current process does not already own a lock on the specified device. +.Pp +.Dv UU_LOCK_WRITE_ERR : +The new process id could not be written to the lock file via a call to +.Xr write 2 . +.Sh ERRORS +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 +for further details. +.Pp +.Fn uu_unlock +will set the global variable +.Va errno +to reflect the reason that the lock file could not be removed. +Refer to the description of +.Xr unlink 2 +for further details. +.Sh SEE ALSO +.Xr lseek 2 , +.Xr open 2 , +.Xr read 2 , +.Xr write 2 +.Sh BUGS +It is possible that a stale lock is not recognised as such if a new +processes is assigned the same processes id as the program that left +the stale lock. +.Pp +The calling process must have write permissions to the +.Pa /var/spool/lock +directory. +There is no mechanism in place to ensure that the +permissions of this directory are the same as those of the +serial devices that might be locked. diff --git a/uucplock.c b/uucplock.c new file mode 100644 index 0000000..2de06d2 --- /dev/null +++ b/uucplock.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#ifndef lint +static const char sccsid[] = "@(#)uucplock.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "libutil.h" + +#define MAXTRIES 5 + +#define LOCKTMP "LCKTMP..%d" +#define LOCKFMT "LCK..%s" + +#define GORET(level, val) { err = errno; uuerr = (val); \ + goto __CONCAT(ret, level); } + +/* Forward declarations */ +static int put_pid (int fd, pid_t pid); +static pid_t get_pid (int fd,int *err); + +/* + * uucp style locking routines + */ + +int +uu_lock(const char *tty_name) +{ + int fd, tmpfd, i; + pid_t pid, pid_old; + char lckname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN], + lcktmpname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN]; + int err, uuerr; + + pid = getpid(); + (void)snprintf(lcktmpname, sizeof(lcktmpname), _PATH_UUCPLOCK LOCKTMP, + pid); + (void)snprintf(lckname, sizeof(lckname), _PATH_UUCPLOCK LOCKFMT, + tty_name); + if ((tmpfd = creat(lcktmpname, 0664)) < 0) + GORET(0, UU_LOCK_CREAT_ERR); + + for (i = 0; i < MAXTRIES; i++) { + if (link (lcktmpname, lckname) < 0) { + if (errno != EEXIST) + GORET(1, UU_LOCK_LINK_ERR); + /* + * file is already locked + * check to see if the process holding the lock + * still exists + */ + if ((fd = open(lckname, O_RDONLY)) < 0) + GORET(1, UU_LOCK_OPEN_ERR); + + if ((pid_old = get_pid (fd, &err)) == -1) + GORET(2, UU_LOCK_READ_ERR); + + close(fd); + + if (kill(pid_old, 0) == 0 || errno != ESRCH) + GORET(1, UU_LOCK_INUSE); + /* + * The process that locked the file isn't running, so + * we'll lock it ourselves + */ + (void)unlink(lckname); + } else { + if (!put_pid (tmpfd, pid)) + GORET(3, UU_LOCK_WRITE_ERR); + break; + } + } + GORET(1, (i >= MAXTRIES) ? UU_LOCK_TRY_ERR : UU_LOCK_OK); + +ret3: + (void)unlink(lckname); + goto ret1; +ret2: + (void)close(fd); +ret1: + (void)close(tmpfd); + (void)unlink(lcktmpname); +ret0: + errno = err; + return uuerr; +} + +int +uu_lock_txfr(const char *tty_name, pid_t pid) +{ + int fd, err; + char lckname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN]; + + snprintf(lckname, sizeof(lckname), _PATH_UUCPLOCK LOCKFMT, tty_name); + + if ((fd = open(lckname, O_RDWR)) < 0) + return UU_LOCK_OWNER_ERR; + if (get_pid(fd, &err) != getpid()) + err = UU_LOCK_OWNER_ERR; + else { + lseek(fd, (off_t)0, SEEK_SET); + err = put_pid(fd, pid) ? 0 : UU_LOCK_WRITE_ERR; + } + close(fd); + + return err; +} + +int +uu_unlock(const char *tty_name) +{ + char tbuf[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN]; + + (void)snprintf(tbuf, sizeof(tbuf), _PATH_UUCPLOCK LOCKFMT, tty_name); + return unlink(tbuf); +} + +const char * +uu_lockerr(int uu_lockresult) +{ + static char errbuf[128]; + const char *fmt; + + switch (uu_lockresult) { + case UU_LOCK_INUSE: + return "device in use"; + case UU_LOCK_OK: + return ""; + case UU_LOCK_OPEN_ERR: + fmt = "open error: %s"; + break; + case UU_LOCK_READ_ERR: + fmt = "read error: %s"; + break; + case UU_LOCK_CREAT_ERR: + fmt = "creat error: %s"; + break; + case UU_LOCK_WRITE_ERR: + fmt = "write error: %s"; + break; + case UU_LOCK_LINK_ERR: + fmt = "link error: %s"; + break; + case UU_LOCK_TRY_ERR: + fmt = "too many tries: %s"; + break; + case UU_LOCK_OWNER_ERR: + fmt = "not locking process: %s"; + break; + default: + fmt = "undefined error: %s"; + break; + } + + (void)snprintf(errbuf, sizeof(errbuf), fmt, strerror(errno)); + return errbuf; +} + +static int +put_pid(int fd, pid_t pid) +{ + char buf[32]; + int len; + + len = sprintf (buf, "%10d\n", (int)pid); + return write (fd, buf, (size_t)len) == len; +} + +static pid_t +get_pid(int fd, int *err) +{ + int bytes_read; + char buf[32]; + pid_t pid; + + bytes_read = read (fd, buf, sizeof (buf) - 1); + if (bytes_read > 0) { + buf[bytes_read] = '\0'; + pid = (pid_t)strtol (buf, (char **) NULL, 10); + } else { + pid = -1; + *err = bytes_read ? errno : EINVAL; + } + return pid; +} + +/* end of uucplock.c */ -- 2.47.2