# 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;
+
+again:
+ if (feof(fp))
+ return NULL;
+
+#ifdef DEBUG_MEMORY
+ if (!lbuf)
+ atexit(free_lbuf);
+#endif
- while(!feof(fp)) {
- if (*line == NULL || last != 0) {
- *len += BUFSIZ;
- *line = xrealloc(*line, *len);
+ 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 */
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);
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;
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;
}
}
fclose(f);
- free(buffer);
}
return ifs;
}
{
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 */
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;
break;
}
}
- free(buffer);
fclose(f);
/* Terminate the encapsulated options */