[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