Browse Source

* Added /etc/shadow support (Config selectable)
* Moved some file paths from code into <paths.h>

David McCullough 22 years ago
parent
commit
2345725967

+ 3 - 0
extra/Configs/Config.arm

@@ -77,6 +77,9 @@ DO_C99_MATH = false
 # Also omits strto(u)ll, and (u)lltostr from the library if `false'.
 HAS_LONG_LONG = false
 
+# Set this to 'false if you don't need shadow password support.
+HAS_SHADOW = false
+
 # Set this to `false' if you don't have/need locale support; `true' otherwise.
 # Note: Currently only affects the ctype functions.  You must also generate
 # a locale file for anything but the C locale.  See directory extra/locale for

+ 3 - 0
extra/Configs/Config.cross.arm.uclinux

@@ -73,6 +73,9 @@ DO_C99_MATH = false
 # Also omits strto(u)ll, and (u)lltostr from the library if `false'.
 HAS_LONG_LONG = true
 
+# Set this to 'false if you don't need shadow password support.
+HAS_SHADOW = false
+
 # Set this to `false' if you don't have/need locale support; `true' otherwise.
 # Note: Currently only affects the ctype functions.  You must also generate
 # a locale file for anything but the C locale.  See directory extra/locale for

+ 3 - 0
extra/Configs/Config.i386

@@ -73,6 +73,9 @@ DO_C99_MATH = false
 # Also omits strto(u)ll, and (u)lltostr from the library if `false'.
 HAS_LONG_LONG = true
 
+# Set this to 'false if you don't need shadow password support.
+HAS_SHADOW = false
+
 # Set this to `false' if you don't have/need locale support; `true' otherwise.
 # Note: Currently only affects the ctype functions.  You must also generate
 # a locale file for anything but the C locale.  See directory extra/locale for

+ 3 - 0
extra/Configs/Config.m68k

@@ -73,6 +73,9 @@ DO_C99_MATH = false
 # Also omits strto(u)ll, and (u)lltostr from the library if `false'.
 HAS_LONG_LONG = true
 
+# Set this to 'false if you don't need shadow password support.
+HAS_SHADOW = false
+
 # Set this to `false' if you don't have/need locale support; `true' otherwise.
 # Note: Currently only affects the ctype functions.  You must also generate
 # a locale file for anything but the C locale.  See directory extra/locale for

+ 3 - 0
extra/Configs/Config.m68k.coff

@@ -73,6 +73,9 @@ DO_C99_MATH = false
 # Also omits strto(u)ll, and (u)lltostr from the library if `false'.
 HAS_LONG_LONG = true
 
+# Set this to 'false if you don't need shadow password support.
+HAS_SHADOW = false
+
 # Set this to `false' if you don't have/need locale support; `true' otherwise.
 # Note: Currently only affects the ctype functions.  You must also generate
 # a locale file for anything but the C locale.  See directory extra/locale for

+ 3 - 0
extra/Configs/Config.mips

@@ -72,6 +72,9 @@ DO_C99_MATH = false
 # Also omits strto(u)ll, and (u)lltostr from the library if `false'.
 HAS_LONG_LONG = true
 
+# Set this to 'false if you don't need shadow password support.
+HAS_SHADOW = false
+
 # Set this to `false' if you don't have/need locale support; `true' otherwise.
 # Note: Currently only affects the ctype functions.  You must also generate
 # a locale file for anything but the C locale.  See directory extra/locale for

+ 3 - 0
extra/Configs/Config.mipsel

@@ -72,6 +72,9 @@ DO_C99_MATH = false
 # Also omits strto(u)ll, and (u)lltostr from the library if `false'.
 HAS_LONG_LONG = true
 
+# Set this to 'false if you don't need shadow password support.
+HAS_SHADOW = false
+
 # Set this to `false' if you don't have/need locale support; `true' otherwise.
 # Note: Currently only affects the ctype functions.  You must also generate
 # a locale file for anything but the C locale.  See directory extra/locale for

+ 3 - 0
extra/Configs/Config.powerpc

@@ -73,6 +73,9 @@ DO_C99_MATH = false
 # Also omits strto(u)ll, and (u)lltostr from the library if `false'.
 HAS_LONG_LONG = true
 
+# Set this to 'false if you don't need shadow password support.
+HAS_SHADOW = false
+
 # Set this to `false' if you don't have/need locale support; `true' otherwise.
 # Note: Currently only affects the ctype functions.  You must also generate
 # a locale file for anything but the C locale.  See directory extra/locale for

+ 3 - 0
extra/Configs/Config.sh

@@ -97,6 +97,9 @@ DO_C99_MATH = false
 # Also omits strto(u)ll, and (u)lltostr from the library if `false'.
 HAS_LONG_LONG = false
 
+# Set this to 'false if you don't need shadow password support.
+HAS_SHADOW = false
+
 # Set this to `false' if you don't have/need locale support; `true' otherwise.
 # Note: Currently only affects the ctype functions.  You must also generate
 # a locale file for anything but the C locale.  See directory extra/locale for

+ 3 - 0
include/paths.h

@@ -63,6 +63,9 @@
 #define _PATH_UTMP	"/var/run/utmp"
 #define	_PATH_VI	"/usr/bin/vi"
 #define _PATH_WTMP	"/var/log/wtmp"
+#define _PATH_LOCALE	"/usr/lib/locale"
+#define _PATH_PASSWD	"/etc/passwd"
+#define _PATH_GROUP	"/etc/group"
 
 /* Provide trailing slash, since mostly used for building pathnames. */
 #define	_PATH_DEV	"/dev/"

+ 6 - 0
libc/pwd_grp/Makefile

@@ -27,6 +27,12 @@ include $(TOPDIR)Rules.mak
 CSRC= pwent.c getpwnam.c getpwuid.c putpwent.c getpw.c fgetpwent.c \
 	__getgrent.c grent.c getgrnam.c getgrgid.c fgetgrent.c \
 	initgroups.c __getpwent_r.c
+
+ifeq ($(HAS_SHADOW),true)
+CSRC+= lckpwdf.c spent.c getspnam.c getspuid.c putspent.c sgetspent.c \
+	fgetspent.c __getspent_r.c __sgetspent_r.c
+endif
+
 COBJS=$(patsubst %.c,%.o, $(CSRC))
 OBJS=$(COBJS)
 

+ 57 - 0
libc/pwd_grp/__getspent_r.c

@@ -0,0 +1,57 @@
+/*
+ * __getspent_r.c - Based on __getpwent_r.c
+ * 
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <shadow.h>
+
+
+int __getspent_r(struct spwd * spwd, char * line_buff, size_t buflen, int spwd_fd)
+{
+	char *endptr;
+	int line_len;
+
+	/* We use the restart label to handle malformatted lines */
+  restart:
+	/* Read the shadow line into the static buffer using a minimal of
+	   syscalls. */
+	if ((line_len = read(spwd_fd, line_buff, buflen)) <= 0)
+		return -1;
+	endptr = strchr(line_buff, '\n');
+	if (endptr != NULL)
+		lseek(spwd_fd, (long) (1 + endptr - (line_buff + line_len)),
+			  SEEK_CUR);
+	else {						/* The line is too long - skip it. :-\ */
+
+		do {
+			if ((line_len = read(spwd_fd, line_buff, buflen)) <= 0)
+				return -1;
+		} while (!(endptr = strchr(line_buff, '\n')));
+		lseek(spwd_fd, (long) (endptr - line_buff) - line_len + 1,
+			  SEEK_CUR);
+		goto restart;
+	}
+
+	if (__sgetspent_r(line_buff, spwd, line_buff, buflen) < 0)
+		goto restart;
+
+	return 0;
+}

+ 161 - 0
libc/pwd_grp/__sgetspent_r.c

@@ -0,0 +1,161 @@
+/*
+ * __sgetspent_r.c - Based on __getpwent_r.c
+ * 
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <shadow.h>
+
+
+int __sgetspent_r(const char * string, struct spwd * spwd, char * line_buff, size_t buflen)
+{
+	char *field_begin;
+	char *endptr;
+	char *lstchg_ptr=NULL;
+	char *min_ptr=NULL;
+	char *max_ptr=NULL;
+	char *warn_ptr=NULL;
+	char *inact_ptr=NULL;
+	char *expire_ptr=NULL;
+	char *flag_ptr=NULL;
+	int i;
+
+	if (string != line_buff) {
+		if (strlen(string) >= buflen)
+			return -1;
+		strcpy(line_buff, string);
+	}
+
+	if (*line_buff == '#' || *line_buff == ' ' || *line_buff == '\n' ||
+		*line_buff == '\t')
+		return -1;
+
+	field_begin = strchr(line_buff, '\n');
+	if (field_begin != NULL)
+		*field_begin = '\0';
+
+	/* We've read the line; now parse it. */
+	field_begin = line_buff;
+	for (i = 0; i < 9; i++) {
+		switch (i) {
+		case 0:
+			spwd->sp_namp = field_begin;
+			break;
+		case 1:
+			spwd->sp_pwdp = field_begin;
+			break;
+		case 2:
+			lstchg_ptr = field_begin;
+			break;
+		case 3:
+			min_ptr = field_begin;
+			break;
+		case 4:
+			max_ptr = field_begin;
+			break;
+		case 5:
+			warn_ptr = field_begin;
+			break;
+		case 6:
+			inact_ptr = field_begin;
+			break;
+		case 7:
+			expire_ptr = field_begin;
+			break;
+		case 8:
+			flag_ptr = field_begin;
+			break;
+		}
+		if (i < 8) {
+			field_begin = strchr(field_begin, ':');
+			if (field_begin == NULL) {
+				if (i==4 || i==7)
+					break;
+				return -1;
+			}
+			*field_begin++ = '\0';
+		}
+	}
+
+	if (*lstchg_ptr == '\0') {
+		spwd->sp_lstchg = -1;
+	} else {
+		spwd->sp_lstchg = (gid_t) strtoul(lstchg_ptr, &endptr, 10);
+		if (*endptr != '\0')
+			return -1;
+	}
+
+	if (*min_ptr == '\0') {
+		spwd->sp_min = -1;
+	} else {
+		spwd->sp_min = (gid_t) strtoul(min_ptr, &endptr, 10);
+		if (*endptr != '\0')
+			return -1;
+	}
+
+	if (*max_ptr == '\0') {
+		spwd->sp_max = -1;
+	} else {
+		spwd->sp_max = (gid_t) strtoul(max_ptr, &endptr, 10);
+		if (*endptr != '\0')
+			return -1;
+	}
+
+	if (warn_ptr == NULL) {
+		/* Support for old format */
+		spwd->sp_warn = -1;
+		spwd->sp_inact = -1;
+		spwd->sp_expire = -1;
+		spwd->sp_flag = 0;
+	}
+	else {
+		if (*warn_ptr == '\0') {
+			spwd->sp_warn = -1;
+		} else {
+			spwd->sp_warn = (gid_t) strtoul(warn_ptr, &endptr, 10);
+			if (*endptr != '\0')
+				return -1;
+		}
+
+		if (*inact_ptr == '\0') {
+			spwd->sp_inact = -1;
+		} else {
+			spwd->sp_inact = (gid_t) strtoul(inact_ptr, &endptr, 10);
+			if (*endptr != '\0')
+				return -1;
+		}
+
+		if (*expire_ptr == '\0') {
+			spwd->sp_expire = -1;
+		} else {
+			spwd->sp_expire = (gid_t) strtoul(expire_ptr, &endptr, 10);
+			if (*endptr != '\0')
+				return -1;
+		}
+
+		if (flag_ptr==NULL || *flag_ptr=='\0') {
+			spwd->sp_flag = ~0ul;
+		} else {
+			spwd->sp_flag = (gid_t) strtoul(flag_ptr, &endptr, 10);
+			if (*endptr != '\0')
+				return -1;
+		}
+	}
+
+	return 0;
+}

+ 45 - 0
libc/pwd_grp/fgetspent.c

@@ -0,0 +1,45 @@
+/*
+ * fgetspent.c - Based on fgetpwent.c
+ * 
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <shadow.h>
+
+#define PWD_BUFFER_SIZE 256
+
+int fgetspent_r (FILE *file, struct spwd *spwd,
+	char *buff, size_t buflen, struct spwd **crap)
+{
+	if (file == NULL) {
+		__set_errno(EINTR);
+		return -1;
+	}
+	return(__getspent_r(spwd, buff, buflen, fileno(file)));
+}
+
+struct spwd *fgetspent(FILE * file)
+{
+	static char line_buff[PWD_BUFFER_SIZE];
+	static struct spwd spwd;
+
+	if (fgetspent_r(file, &spwd, line_buff, PWD_BUFFER_SIZE, NULL) != -1) {
+		return &spwd;
+	}
+	return NULL;
+}

+ 2 - 1
libc/pwd_grp/getgrgid.c

@@ -22,6 +22,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <grp.h>
+#include <paths.h>
 #include "config.h"
 
 struct group *getgrgid(const gid_t gid)
@@ -29,7 +30,7 @@ struct group *getgrgid(const gid_t gid)
 	struct group *group;
 	int grp_fd;
 
-	if ((grp_fd = open("/etc/group", O_RDONLY)) < 0)
+	if ((grp_fd = open(_PATH_GROUP, O_RDONLY)) < 0)
 		return NULL;
 
 	while ((group = __getgrent(grp_fd)) != NULL)

+ 2 - 1
libc/pwd_grp/getgrnam.c

@@ -23,6 +23,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <grp.h>
+#include <paths.h>
 #include "config.h"
 
 struct group *getgrnam(const char *name)
@@ -35,7 +36,7 @@ struct group *getgrnam(const char *name)
 		return NULL;
 	}
 
-	if ((grp_fd = open("/etc/group", O_RDONLY)) < 0)
+	if ((grp_fd = open(_PATH_GROUP, O_RDONLY)) < 0)
 		return NULL;
 
 	while ((group = __getgrent(grp_fd)) != NULL)

+ 2 - 2
libc/pwd_grp/getpwnam.c

@@ -23,9 +23,9 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <pwd.h>
+#include <paths.h>
 #include "config.h"
 
-
 #define PWD_BUFFER_SIZE 256
 
 /* file descriptor for the password file currently open */
@@ -43,7 +43,7 @@ int getpwnam_r (const char *name, struct passwd *password,
 		return -1;
 	}
 
-	if ((passwd_fd = open("/etc/passwd", O_RDONLY)) < 0)
+	if ((passwd_fd = open(_PATH_PASSWD, O_RDONLY)) < 0)
 		return -1;
 
 	while (__getpwent_r(password, buff, buflen, passwd_fd) != -1)

+ 2 - 2
libc/pwd_grp/getpwuid.c

@@ -22,9 +22,9 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <pwd.h>
+#include <paths.h>
 #include "config.h"
 
-
 #define PWD_BUFFER_SIZE 256
 
 /* file descriptor for the password file currently open */
@@ -36,7 +36,7 @@ int getpwuid_r (uid_t uid, struct passwd *password,
 {
 	int passwd_fd;
 
-	if ((passwd_fd = open("/etc/passwd", O_RDONLY)) < 0)
+	if ((passwd_fd = open(_PATH_PASSWD, O_RDONLY)) < 0)
 		return -1;
 
 	while (__getpwent_r(password, buff, buflen, passwd_fd) != -1)

+ 61 - 0
libc/pwd_grp/getspnam.c

@@ -0,0 +1,61 @@
+/*
+ * getspnam.c - Based on getpwnam.c
+ * 
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <shadow.h>
+
+#define PWD_BUFFER_SIZE 256
+
+int getspnam_r (const char *name, struct spwd *spwd,
+	char *buff, size_t buflen, struct spwd **crap)
+{
+	int spwd_fd;
+
+	if (name == NULL) {
+		__set_errno(EINVAL);
+		return -1;
+	}
+
+	if ((spwd_fd = open(_PATH_SHADOW, O_RDONLY)) < 0)
+		return -1;
+
+	while (__getspent_r(spwd, buff, buflen, spwd_fd) != -1)
+		if (!strcmp(spwd->sp_namp, name)) {
+			close(spwd_fd);
+			return 0;
+		}
+
+	close(spwd_fd);
+	return -1;
+}
+
+struct spwd *getspnam(const char *name)
+{
+	static char line_buff[PWD_BUFFER_SIZE];
+	static struct spwd spwd;
+
+	if (getspnam_r(name, &spwd, line_buff, PWD_BUFFER_SIZE, NULL) != -1) {
+		return &spwd;
+	}
+	return NULL;
+}
+

+ 50 - 0
libc/pwd_grp/getspuid.c

@@ -0,0 +1,50 @@
+/*
+ * getspuid.c - Based on getpwuid.c
+ * 
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <shadow.h>
+
+#define PWD_BUFFER_SIZE 256
+
+int getspuid_r (uid_t uid, struct spwd *spwd,
+	char *buff, size_t buflen, struct spwd **crap)
+{
+	char pwd_buff[PWD_BUFFER_SIZE];
+	struct passwd password;
+
+	if (getpwuid_r(uid, &password, pwd_buff, PWD_BUFFER_SIZE, NULL) < 0)
+		return -1;
+
+	return getspnam_r(password.pw_name, spwd, buff, buflen, crap);
+}
+
+struct spwd *getspuid(uid_t uid)
+{
+	static char line_buff[PWD_BUFFER_SIZE];
+	static struct spwd spwd;
+
+	if (getspuid_r(uid, &spwd, line_buff, PWD_BUFFER_SIZE, NULL) != -1) {
+		return &spwd;
+	}
+	return NULL;
+}
+

+ 2 - 1
libc/pwd_grp/grent.c

@@ -27,6 +27,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <grp.h>
+#include <paths.h>
 #include "config.h"
 
 static int grp_fd = -1;
@@ -35,7 +36,7 @@ void setgrent(void)
 {
 	if (grp_fd != -1)
 		close(grp_fd);
-	grp_fd = open("/etc/group", O_RDONLY);
+	grp_fd = open(_PATH_GROUP, O_RDONLY);
 }
 
 void endgrent(void)

+ 2 - 1
libc/pwd_grp/initgroups.c

@@ -22,6 +22,7 @@
 #include <string.h>
 #include <fcntl.h>
 #include <grp.h>
+#include <paths.h>
 #include "config.h"
 
 int initgroups(__const char *user, gid_t gid)
@@ -38,7 +39,7 @@ int initgroups(__const char *user, gid_t gid)
 	int grp_fd;
 
 
-	if ((grp_fd = open("/etc/group", O_RDONLY)) < 0)
+	if ((grp_fd = open(_PATH_GROUP, O_RDONLY)) < 0)
 		return -1;
 
 	num_groups = 0;

+ 163 - 0
libc/pwd_grp/lckpwdf.c

@@ -0,0 +1,163 @@
+/* Handle locking of password file.
+   Copyright (C) 1996, 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <fcntl.h>
+#include <shadow.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/file.h>
+#include <paths.h>
+
+/* How long to wait for getting the lock before returning with an
+   error.  */
+#define TIMEOUT 15 /* sec */
+
+/* File descriptor for lock file.  */
+static int lock_fd = -1;
+
+/* Prototypes for local functions.  */
+static void noop_handler __P ((int __sig));
+
+
+int
+lckpwdf ()
+{
+	int flags;
+	sigset_t saved_set;         /* Saved set of caught signals.  */
+	struct sigaction saved_act; /* Saved signal action.  */
+	sigset_t new_set;           /* New set of caught signals.  */
+	struct sigaction new_act;   /* New signal action.  */
+	struct flock fl;            /* Information struct for locking.  */
+	int result;
+
+	if (lock_fd != -1)
+		/* Still locked by own process.  */
+		return -1;
+
+	lock_fd = open (_PATH_PASSWD, O_WRONLY);
+	if (lock_fd == -1)
+		/* Cannot create lock file.  */
+		return -1;
+
+	/* Make sure file gets correctly closed when process finished.  */
+	flags = fcntl (lock_fd, F_GETFD, 0);
+	if (flags == -1) {
+		/* Cannot get file flags.  */
+		close(lock_fd);
+		lock_fd = -1;
+		return -1;
+	}
+	flags |= FD_CLOEXEC;		/* Close on exit.  */
+	if (fcntl (lock_fd, F_SETFD, flags) < 0) {
+		/* Cannot set new flags.  */
+		close(lock_fd);
+		lock_fd = -1;
+		return -1;
+	}
+
+	/* Now we have to get exclusive write access.  Since multiple
+	   process could try this we won't stop when it first fails.
+	   Instead we set a timeout for the system call.  Once the timer
+	   expires it is likely that there are some problems which cannot be
+	   resolved by waiting.
+	   
+	   It is important that we don't change the signal state.  We must
+	   restore the old signal behaviour.  */
+	memset (&new_act, '\0', sizeof (struct sigaction));
+	new_act.sa_handler = noop_handler;
+	sigfillset (&new_act.sa_mask);
+	new_act.sa_flags = 0ul;
+
+	/* Install new action handler for alarm and save old.  */
+	if (sigaction (SIGALRM, &new_act, &saved_act) < 0) {
+		/* Cannot install signal handler.  */
+		close(lock_fd);
+		lock_fd = -1;
+		return -1;
+	}
+
+	/* Now make sure the alarm signal is not blocked.  */
+	sigemptyset (&new_set);
+	sigaddset (&new_set, SIGALRM);
+	if (sigprocmask (SIG_UNBLOCK, &new_set, &saved_set) < 0) {
+		sigaction (SIGALRM, &saved_act, NULL);
+		close(lock_fd);
+		lock_fd = -1;
+		return -1;
+	}
+
+	/* Start timer.  If we cannot get the lock in the specified time we
+	   get a signal.  */
+	alarm (TIMEOUT);
+
+	/* Try to get the lock.  */
+	memset (&fl, '\0', sizeof (struct flock));
+	fl.l_type = F_WRLCK;
+	fl.l_whence = SEEK_SET;
+	result = fcntl (lock_fd, F_SETLKW, &fl);
+
+	/* Clear alarm.  */
+	alarm (0);
+
+	/* Restore old set of handled signals.  We don't need to know
+	   about the current one.*/
+	sigprocmask (SIG_SETMASK, &saved_set, NULL);
+
+	/* Restore old action handler for alarm.  We don't need to know
+	   about the current one.  */
+	sigaction (SIGALRM, &saved_act, NULL);
+
+	if (result < 0) {
+		close(lock_fd);
+		lock_fd = -1;
+		return -1;
+	}
+
+	return 0;
+}
+
+
+int
+ulckpwdf ()
+{
+	int result;
+	
+	if (lock_fd == -1) {
+		/* There is no lock set.  */
+		result = -1;
+	}
+	else {
+		result = close (lock_fd);
+		
+		/* Mark descriptor as unused.  */
+		lock_fd = -1;
+	}
+
+	return result;
+}
+
+
+static void
+noop_handler (sig)
+	int sig;
+{
+	/* We simply return which makes the `fcntl' call return with an error.  */
+}

+ 79 - 0
libc/pwd_grp/putspent.c

@@ -0,0 +1,79 @@
+/* Copyright (C) 1991, 1992, 1996, 1997, 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <stdio.h>
+#include <shadow.h>
+
+#define _S(x)	x ? x : ""
+
+
+/* Write an entry to the given stream.
+   This must know the format of the password file.  */
+int
+putspent (const struct spwd *p, FILE *stream)
+{
+  int errors = 0;
+
+  if (fprintf (stream, "%s:%s:", p->sp_namp, _S (p->sp_pwdp)) < 0)
+    ++errors;
+
+  if ((p->sp_lstchg != (long int) -1
+       && fprintf (stream, "%ld:", p->sp_lstchg) < 0)
+      || (p->sp_lstchg == (long int) -1
+	  && putc (':', stream) == EOF))
+    ++errors;
+
+  if ((p->sp_min != (long int) -1
+       && fprintf (stream, "%ld:", p->sp_min) < 0)
+      || (p->sp_min == (long int) -1
+	  && putc (':', stream) == EOF))
+    ++errors;
+
+  if ((p->sp_max != (long int) -1
+       && fprintf (stream, "%ld:", p->sp_max) < 0)
+      || (p->sp_max == (long int) -1
+	  && putc (':', stream) == EOF))
+    ++errors;
+
+  if ((p->sp_warn != (long int) -1
+       && fprintf (stream, "%ld:", p->sp_warn) < 0)
+      || (p->sp_warn == (long int) -1
+	  && putc (':', stream) == EOF))
+    ++errors;
+
+  if ((p->sp_inact != (long int) -1
+       && fprintf (stream, "%ld:", p->sp_inact) < 0)
+      || (p->sp_inact == (long int) -1
+	  && putc (':', stream) == EOF))
+    ++errors;
+
+  if ((p->sp_expire != (long int) -1
+       && fprintf (stream, "%ld:", p->sp_expire) < 0)
+      || (p->sp_expire == (long int) -1
+	  && putc (':', stream) == EOF))
+    ++errors;
+
+  if (p->sp_flag != ~0ul
+      && fprintf (stream, "%ld", p->sp_flag) < 0)
+    ++errors;
+
+  if (putc ('\n', stream) == EOF)
+    ++errors;
+
+  return errors ? -1 : 0;
+}

+ 2 - 1
libc/pwd_grp/pwent.c

@@ -23,6 +23,7 @@
 #include <errno.h>
 #include <pwd.h>
 #include <fcntl.h>
+#include <paths.h>
 #include "config.h"
 
 /*
@@ -43,7 +44,7 @@ void setpwent(void)
 	if (pw_fd != -1)
 		close(pw_fd);
 
-	pw_fd = open("/etc/passwd", O_RDONLY);
+	pw_fd = open(_PATH_PASSWD, O_RDONLY);
 }
 
 void endpwent(void)

+ 41 - 0
libc/pwd_grp/sgetspent.c

@@ -0,0 +1,41 @@
+/*
+ * sgetspent.c
+ * 
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <shadow.h>
+
+#define PWD_BUFFER_SIZE 256
+
+int sgetspent_r (const char *string, struct spwd *spwd,
+	char *buff, size_t buflen, struct spwd **crap)
+{
+	return(__sgetspent_r(string, spwd, buff, buflen));
+}
+
+struct spwd *sgetspent(const char *string)
+{
+	static char line_buff[PWD_BUFFER_SIZE];
+	static struct spwd spwd;
+
+	if (sgetspent_r(string, &spwd, line_buff, PWD_BUFFER_SIZE, NULL) != -1) {
+		return &spwd;
+	}
+	return NULL;
+}

+ 71 - 0
libc/pwd_grp/spent.c

@@ -0,0 +1,71 @@
+/*
+ * spent.c - Based on pwent.c
+ * 
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <shadow.h>
+#include <fcntl.h>
+
+/*
+ * setspent(), endspent(), and getspent() are included in the same object
+ * file, since one cannot be used without the other two, so it makes sense to
+ * link them all in together.
+ */
+
+#define PWD_BUFFER_SIZE 256
+
+/* file descriptor for the password file currently open */
+static int spwd_fd = -1;
+
+void setspent(void)
+{
+	if (spwd_fd != -1)
+		close(spwd_fd);
+
+	spwd_fd = open(_PATH_SHADOW, O_RDONLY);
+}
+
+void endspent(void)
+{
+	if (spwd_fd != -1)
+		close(spwd_fd);
+	spwd_fd = -1;
+}
+
+int getspent_r (struct spwd *spwd, char *buff, 
+	size_t buflen, struct spwd **crap)
+{
+	if (spwd_fd != -1 && __getspent_r(spwd, buff, buflen, spwd_fd) != -1) {
+		return 0;
+	}
+	return -1;
+}
+
+struct spwd *getspent(void)
+{
+	static char line_buff[PWD_BUFFER_SIZE];
+	static struct spwd spwd;
+
+	if (getspent_r(&spwd, line_buff, PWD_BUFFER_SIZE, NULL) != -1) {
+		return &spwd;
+	}
+	return NULL;
+}
+