Module Name:    src
Committed By:   kefren
Date:           Fri Oct 18 14:14:14 UTC 2013

Modified Files:
        src/usr.sbin/ldpd: conffile.c

Log Message:
sync behaviour with man page: accept spaces, empty lines and comments


To generate a diff of this commit:
cvs rdiff -u -r1.7 -r1.8 src/usr.sbin/ldpd/conffile.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.sbin/ldpd/conffile.c
diff -u src/usr.sbin/ldpd/conffile.c:1.7 src/usr.sbin/ldpd/conffile.c:1.8
--- src/usr.sbin/ldpd/conffile.c:1.7	Thu Oct 17 18:10:23 2013
+++ src/usr.sbin/ldpd/conffile.c	Fri Oct 18 14:14:14 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: conffile.c,v 1.7 2013/10/17 18:10:23 kefren Exp $ */
+/* $NetBSD: conffile.c,v 1.8 2013/10/18 14:14:14 kefren Exp $ */
 
 /*
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <arpa/inet.h>
 #include <netinet/in.h>
-
+#include <sys/mman.h>
 #include <ctype.h>
 #include <fcntl.h>
 #include <stdlib.h>
@@ -44,13 +44,15 @@
 #define NextCommand(x) strsep(&x, " ")
 #define LINEMAXSIZE 1024
 
+char *mapped, *nextline;
+size_t mapsize;
+
 extern int ldp_hello_time, ldp_keepalive_time, ldp_holddown_time, command_port,
 	min_label, max_label, no_default_route, loop_detection;
-int confh;
 struct in_addr conf_ldp_id;
 
 static int conf_dispatch(char*);
-static int conf_readline(char*, size_t);
+static char * conf_getlinelimit(void);
 static int checkeol(char*);
 static int Fhellotime(char*);
 static int Fport(char*);
@@ -108,52 +110,59 @@ static int parseline;
 int
 conf_parsefile(const char *fname)
 {
-	char buf[LINEMAXSIZE + 1];
+	char line[LINEMAXSIZE+1];
+	struct stat fs;
 
 	SLIST_INIT(&conei_head);
 	SLIST_INIT(&coifs_head);
 	conf_ldp_id.s_addr = 0;
 
-	confh = open(fname, O_RDONLY, 0);
+	int confh = open(fname, O_RDONLY, 0);
 
-	if (confh == -1)
+	if (confh == -1 || fstat(confh, &fs) == -1 ||
+	    (mapped = mmap(NULL, fs.st_size, PROT_READ, MAP_SHARED, confh, 0))
+	    == MAP_FAILED)
 		return E_CONF_IO;
 
-	for (parseline = 1; conf_readline(buf, sizeof(buf)) >= 0; parseline++)
-		if (conf_dispatch(buf) != 0) {
-			close(confh);
-			return parseline;
-		}
-
+	mapsize = fs.st_size;
+	nextline = mapped;
+	for (parseline = 1; ; parseline++) {
+		char *prev = nextline;
+		if ((nextline = conf_getlinelimit()) == NULL)
+			break;
+		while (isspace((int)*prev) != 0 && prev < nextline)
+			prev++;
+		if (nextline - prev < 2)
+			continue;
+		else if (nextline - prev > LINEMAXSIZE)
+			goto parerr;
+		memcpy(line, prev, nextline - prev);
+		if (line[0] == '#')
+			continue;
+		else
+			line[nextline - prev] = '\0';
+		if (conf_dispatch(line) != 0)
+			goto parerr;
+	}
+	munmap(mapped, mapsize);
 	close(confh);
 	return 0;
+parerr:
+	munmap(mapped, mapsize);
+	close(confh);
+	return parseline;
 }
 
-/*
- * Reads a line from config file
- */
-int
-conf_readline(char *buf, size_t bufsize)
+char *
+conf_getlinelimit(void)
 {
-	size_t i;
+	char *p = nextline;
 
-	for (i = 0; i < bufsize; i++) {
-		if (read(confh, &buf[i], 1) != 1) {
-			if (i == 0)
-				return E_CONF_IO;
-			break;
-		}
-		if (buf[i] == '\n')
-			break;
-		if (i == 0 && isspace((unsigned char)buf[i]) != 0) {
-			i--;
-			continue;
-		}
-	}
-	if (i == bufsize)
-		return E_CONF_MEM;
-	buf[i] = '\0';
-	return i;
+	if (nextline < mapped || (size_t)(nextline - mapped) >= mapsize)
+		return NULL;
+
+	for (p = nextline; *p != '\n' && (size_t)(p - mapped) < mapsize; p++);
+	return p + 1;
 }
 
 /*
@@ -179,7 +188,7 @@ conf_dispatch(char *line)
 	else if (matched > 1)
 		return E_CONF_AMBIGUOUS;
 
-	if (checkeol(nline) != 0)
+	if (nline == NULL || checkeol(nline) != 0)
 		return E_CONF_PARAM;
 	return main_commands[last_match].func(nline);
 }
@@ -193,6 +202,10 @@ int
 checkeol(char *line)
 {
 	size_t len = strlen(line);
+	if (len > 0 && line[len - 1] == '\n') {
+		line[len - 1] = '\0';
+		len--;
+	}
 	if (len > 0 && line[len - 1] == ';') {
 		line[len - 1] = '\0';
 		return 0;
@@ -289,7 +302,7 @@ Fneighbour(char *line)
 	char *peer;
 	struct conf_neighbour *nei;
 	struct in_addr ad;
-	char buf[1024];
+	char buf[LINEMAXSIZE];
 
 	peer = NextCommand(line);
 	if (inet_pton(AF_INET, peer, &ad) != 1)
@@ -301,10 +314,21 @@ Fneighbour(char *line)
 	nei->address.s_addr = ad.s_addr;
 	SLIST_INSERT_HEAD(&conei_head, nei, neilist);
 
-	while (conf_readline(buf, sizeof(buf)) >= 0) {
+	for ( ; ; ) {
+		char *prev = nextline;
 		parseline++;
-		if (buf[0] == '}')
-			return 0;
+		nextline = conf_getlinelimit();
+		if (nextline == NULL || (size_t)(nextline - prev) > LINEMAXSIZE)
+			return -1;
+		while (isspace((int)*prev) != 0 && prev < nextline)
+			prev++;
+		memcpy(buf, prev, nextline - prev);
+		if (nextline - prev < 2 || buf[0] == '#')
+			continue;
+		else if (buf[0] == '}')
+			break;
+		else
+			buf[nextline - prev] = '\0';
 		if (Gneighbour(nei, buf) == -1)
 			return -1;
 	}
@@ -352,7 +376,7 @@ Finterface(char *line)
 {
 	char *ifname;
 	struct conf_interface *conf_if = calloc(1, sizeof(*conf_if));
-	char buf[1024];
+	char buf[LINEMAXSIZE];
 
 	ifname = NextCommand(line);
 	if (conf_if == NULL || ifname == NULL)
@@ -360,14 +384,25 @@ Finterface(char *line)
 	strlcpy(conf_if->if_name, ifname, IF_NAMESIZE);
 	SLIST_INSERT_HEAD(&coifs_head, conf_if, iflist);
 
-	while (conf_readline(buf, sizeof(buf)) >= 0) {
+	for ( ; ; ) {
+		char *prev = nextline;
 		parseline++;
-		if (buf[0] == '}')
-			return 0;
+		nextline = conf_getlinelimit();
+		if (nextline == NULL || (size_t)(nextline - prev) > LINEMAXSIZE)
+			return -1;
+		while (isspace((int)*prev) != 0 && prev < nextline)
+			prev++;
+		memcpy(buf, prev, nextline - prev);
+		if (nextline - prev < 2 || buf[0] == '#')
+			continue;
+		else if (buf[0] == '}')
+			break;
+		else
+			buf[nextline - prev] = '\0';
 		if (Ginterface(conf_if, buf) == -1)
 			return -1;
 	}
-	return -1;
+	return 0;
 }
 
 int

Reply via email to