[syslinux] [PATCH] getpwnam() implementation in tftpd.c

Jules Colding JuBColding at yorkref.com
Mon May 19 03:26:22 PDT 2003


Hi,

This patch implements a minimal getpwnam() function in tftpd.c.

The reason for the patch is that I needed tftpd to work in my embedded
system, which are without libnss*. The patch has been tested, and works
for me. Please consider it.

Best regards,
  jules


-- 
Jules Colding <JuBColding at yorkref.com>
York Refrigeration


diff -urN tftp-hpa-0.34.orig/tftpd/Makefile tftp-hpa-0.34/tftpd/Makefile
--- tftp-hpa-0.34.orig/tftpd/Makefile	2001-11-27 11:18:11.000000000 +0100
+++ tftp-hpa-0.34/tftpd/Makefile	2003-05-17 21:18:08.000000000 +0200
@@ -4,6 +4,20 @@
 -include ../MCONFIG
 include ../MRULES
 
+# Setting this to something else that `true' will cause tftpd to directly 
+# use the system's password and group functions. Assuming you use GNU libc, 
+# when this is not `true', you will need to install the /etc/nsswitch.conf
+# configuration file and the required libnss_* libraries. This generally 
+# makes your embedded system quite a bit larger... If you leave this on, 
+# tftpd will directly use the /etc/password, /etc/group files (and your 
+# system will be smaller as well).
+USE_PRIVATE_PWD_GRP = false
+
+ifeq ($(strip $(USE_PRIVATE_PWD_GRP)),true)
+    CFLAGS += -DUSE_PRIVATE_PWD_GRP
+endif
+
+
 OBJS = tftpd.$(O) tftpsubs.$(O) recvfrom.$(O) misc.$(O) $(TFTPDOBJS)
 
 all: tftpd$(X) tftpd.8
diff -urN tftp-hpa-0.34.orig/tftpd/tftpd.c tftp-hpa-0.34/tftpd/tftpd.c
--- tftp-hpa-0.34.orig/tftpd/tftpd.c	2003-04-12 08:54:58.000000000 +0200
+++ tftp-hpa-0.34/tftpd/tftpd.c	2003-05-17 21:17:41.000000000 +0200
@@ -35,6 +35,25 @@
  * SUCH DAMAGE.
  */
 
+/*  __getpwent() - This function has originally been copied from the 
+ *  file __getpwent.c which is part of the libc-8086/pwd package for ELKS,
+ *  Copyright (C) 1995, 1996 Nat Friedman <ndf at linux.mit.edu>. 
+ * 
+ *  The present code has been copied from busybox-0.60.5.
+ *
+ *  The code was added to this file by Jules Colding <JuBColding at yorkref.com>.
+ */
+
+/*  getpwnam() - This function has originally been copied from the 
+ *  file getpwnam.c which is part of the libc-8086/pwd package for ELKS,
+ *  Copyright (C) 1995, 1996 Nat Friedman <ndf at linux.mit.edu>. 
+ * 
+ *  The present code has been copied from busybox-0.60.5.
+ * 
+ *  The code was added to this file by Jules Colding <JuBColding at yorkref.com>.
+ */
+
+
 #include "config.h"		/* Must be included first */
 #include "tftpd.h"
 
@@ -58,7 +77,6 @@
 #include <signal.h>
 #include <netdb.h>
 #include <ctype.h>
-#include <pwd.h>
 #include <limits.h>
 #include <syslog.h>
 
@@ -137,6 +155,135 @@
   { NULL,         NULL }
 };
 
+#ifndef USE_PRIVATE_PWD_GRP
+#include <pwd.h>
+#else
+#include <sys/types.h>
+#include <features.h>
+#include <stdio.h>
+
+/* The passwd structure.  */
+struct passwd
+{
+  char *pw_name;   /* Username.  */
+  char *pw_passwd; /* Password.  */
+  uid_t pw_uid;    /* User ID.  */
+  gid_t pw_gid;    /* Group ID.  */
+  char *pw_gecos;  /* Real name.  */
+  char *pw_dir;    /* Home directory.  */
+  char *pw_shell;  /* Shell program.  */
+};
+
+/* to prevent a compiler warning */
+struct passwd *__getpwent(int pwd_fd);
+struct passwd *getpwnam(const char *name);
+
+#define PWD_BUFFER_SIZE 256
+struct passwd *__getpwent(int pwd_fd)
+{
+	static char line_buff[PWD_BUFFER_SIZE];
+	static struct passwd passwd;
+	char *field_begin;
+	char *endptr;
+	char *gid_ptr=NULL;
+	char *uid_ptr=NULL;
+	int line_len;
+	int i;
+
+	/* We use the restart label to handle malformatted lines */
+  restart:
+	/* Read the passwd line into the static buffer using a minimal of
+	   syscalls. */
+	if ((line_len = read(pwd_fd, line_buff, PWD_BUFFER_SIZE)) <= 0)
+		return NULL;
+	field_begin = strchr(line_buff, '\n');
+	if (field_begin != NULL)
+		lseek(pwd_fd, (long) (1 + field_begin - (line_buff + line_len)),
+			  SEEK_CUR);
+	else {						/* The line is too long - skip it. :-\ */
+
+		do {
+			if ((line_len = read(pwd_fd, line_buff, PWD_BUFFER_SIZE)) <= 0)
+				return NULL;
+		} while (!(field_begin = strchr(line_buff, '\n')));
+		lseek(pwd_fd, (long) (field_begin - line_buff) - line_len + 1,
+			  SEEK_CUR);
+		goto restart;
+	}
+	if (*line_buff == '#' || *line_buff == ' ' || *line_buff == '\n' ||
+		*line_buff == '\t')
+		goto restart;
+	*field_begin = '\0';
+
+	/* We've read the line; now parse it. */
+	field_begin = line_buff;
+	for (i = 0; i < 7; i++) {
+		switch (i) {
+		case 0:
+			passwd.pw_name = field_begin;
+			break;
+		case 1:
+			passwd.pw_passwd = field_begin;
+			break;
+		case 2:
+			uid_ptr = field_begin;
+			break;
+		case 3:
+			gid_ptr = field_begin;
+			break;
+		case 4:
+			passwd.pw_gecos = field_begin;
+			break;
+		case 5:
+			passwd.pw_dir = field_begin;
+			break;
+		case 6:
+			passwd.pw_shell = field_begin;
+			break;
+		}
+		if (i < 6) {
+			field_begin = strchr(field_begin, ':');
+			if (field_begin == NULL)
+				goto restart;
+			*field_begin++ = '\0';
+		}
+	}
+	passwd.pw_gid = (gid_t) strtoul(gid_ptr, &endptr, 10);
+	if (*endptr != '\0')
+		goto restart;
+
+	passwd.pw_uid = (uid_t) strtoul(uid_ptr, &endptr, 10);
+	if (*endptr != '\0')
+		goto restart;
+
+	return &passwd;
+}
+
+struct passwd *getpwnam(const char *name)
+{
+	int passwd_fd;
+	struct passwd *passwd;
+
+	if (name == NULL) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	if ((passwd_fd = open("/etc/passwd", O_RDONLY)) < 0)
+		return NULL;
+
+	while ((passwd = __getpwent(passwd_fd)) != NULL)
+		if (!strcmp(passwd->pw_name, name)) {
+			close(passwd_fd);
+			return passwd;
+		}
+
+	close(passwd_fd);
+	return NULL;
+}
+#endif /* USE_PRIVATE_PWD_GRP */
+
+
 /* Simple handler for SIGHUP */
 static volatile sig_atomic_t caught_sighup = 0;
 static void handle_sighup(int sig)
@@ -247,6 +394,7 @@
   }
 }
 
+
 int
 main(int argc, char **argv)
 {





More information about the Syslinux mailing list