get_line now uses a single buffer, strips leading space and skips comments. This reduces malloc usage slightly and gives a cleaner API at the expense of a slight bss increase.

This commit is contained in:
Roy Marples 2008-11-05 13:57:54 +00:00
parent 9783ceb17a
commit e1caa8dbad
5 changed files with 63 additions and 53 deletions

View File

@ -51,31 +51,64 @@
# define _PATH_DEVNULL "/dev/null"
#endif
int clock_monotonic = 0;
int clock_monotonic;
static char *lbuf;
static size_t lbuf_len;
#ifdef DEBUG_MEMORY
static void
free_lbuf(void)
{
free(lbuf);
}
#endif
/* Handy routine to read very long lines in text files.
* This means we read the whole line and avoid any nasty buffer overflows. */
ssize_t
get_line(char **line, size_t *len, FILE *fp)
* This means we read the whole line and avoid any nasty buffer overflows.
* We strip leading space and avoid comment lines, making the code that calls
* us smaller.
* As we don't use threads, this API is clean too. */
char *
get_line(FILE * restrict fp)
{
char *p;
size_t last = 0;
char *p, *e;
size_t last;
while(!feof(fp)) {
if (*line == NULL || last != 0) {
*len += BUFSIZ;
*line = xrealloc(*line, *len);
again:
if (feof(fp))
return NULL;
#ifdef DEBUG_MEMORY
if (!lbuf)
atexit(free_lbuf);
#endif
last = 0;
do {
if (!lbuf || last != 0) {
lbuf_len += BUFSIZ;
lbuf = xrealloc(lbuf, lbuf_len);
}
p = *line + last;
p = lbuf + last;
memset(p, 0, BUFSIZ);
fgets(p, BUFSIZ, fp);
last += strlen(p);
if (last && (*line)[last - 1] == '\n') {
(*line)[last - 1] = '\0';
if (last && lbuf[last - 1] == '\n') {
lbuf[last - 1] = '\0';
break;
}
} while(!feof(fp));
if (!last)
return NULL;
e = p + last - 1;
for (p = lbuf; p < e; p++) {
if (*p != ' ' && *p != '\t')
break;
}
return last;
if (p == e || *p == '#' || *p == ';')
goto again;
return p;
}
/* Simple hack to return a random number without arc4random */

View File

@ -86,7 +86,7 @@ int closefrom(int);
int set_cloexec(int);
int set_nonblock(int);
ssize_t get_line(char **, size_t *, FILE *);
char *get_line(FILE * restrict);
extern int clock_monotonic;
int get_monotonic(struct timeval *);
time_t uptime(void);

25
duid.c
View File

@ -47,30 +47,23 @@ get_duid(unsigned char *duid, const struct interface *iface)
time_t t;
int x = 0;
unsigned char *p = duid;
size_t len = 0, l = 0;
char *buffer = NULL, *line, *option;
size_t len = 0;
char *line;
/* If we already have a DUID then use it as it's never supposed
* to change once we have one even if the interfaces do */
if ((f = fopen(DUID, "r"))) {
while ((get_line(&buffer, &len, f))) {
line = buffer;
while ((option = strsep(&line, " \t")))
if (*option != '\0')
break;
if (!option || *option == '\0' || *option == '#')
continue;
l = hwaddr_aton(NULL, option);
if (l && l <= DUID_LEN) {
hwaddr_aton(duid, option);
while ((line = get_line(f))) {
len = hwaddr_aton(NULL, line);
if (len && len <= DUID_LEN) {
hwaddr_aton(duid, line);
break;
}
l = 0;
len = 0;
}
fclose(f);
free(buffer);
if (l)
return l;
if (len)
return len;
} else {
if (errno != ENOENT)
return 0;

View File

@ -431,18 +431,15 @@ struct interface *
discover_interfaces(int argc, char * const *argv)
{
FILE *f;
char *buffer = NULL, *p;
size_t len = 0, ln = 0, n;
char *p;
size_t ln = 0, n;
int i;
struct interface *ifs = NULL, *ifp, *ifl;
if ((f = fopen("/proc/net/dev", "r"))) {
while (get_line(&buffer, &len, f)) {
while (p = get_line(f)) {
if (++ln < 2)
continue;
p = buffer;
while (isspace((unsigned int)*p))
p++;
n = strcspn(p, ": \t");
p[n]= '\0';
ifl = NULL;
@ -479,7 +476,6 @@ discover_interfaces(int argc, char * const *argv)
}
}
fclose(f);
free(buffer);
}
return ifs;
}

View File

@ -586,8 +586,7 @@ read_config(const char *file, const char *ifname)
{
struct if_options *ifo;
FILE *f;
size_t len = 0;
char *line, *option, *p, *buffer = NULL;
char *line, *option, *p;
int skip = 0;
/* Seed our default options */
@ -612,18 +611,8 @@ read_config(const char *file, const char *ifname)
if (!f)
return ifo;
while ((get_line(&buffer, &len, f))) {
line = buffer;
while ((option = strsep(&line, " \t")))
if (*option != '\0')
break;
if (!option || *option == '\0' || *option == '#')
continue;
/* Trim leading whitespace */
if (line) {
while (*line != '\0' && (*line == ' ' || *line == '\t'))
line++;
}
while ((line = get_line(f))) {
option = strsep(&line, " \t");
/* Trim trailing whitespace */
if (line && *line) {
p = line + strlen(line) - 1;
@ -646,7 +635,6 @@ read_config(const char *file, const char *ifname)
break;
}
}
free(buffer);
fclose(f);
/* Terminate the encapsulated options */