Re: 2.1.120 - too many errors on the network interfaces

Andi Kleen (ak@muc.de)
20 Sep 1998 16:50:57 +0200


allbery@kf8nh.apk.net (Brandon S. Allbery KF8NH) writes:
>
> Dunno about ioctl (I've seen lots of schemes proposed and used, and all of
> them fall short), but it does seem silly that proc doesn't include version
> numbers. Would it really be that painful to have the first line of a /proc
> file be an interface version number? Old utilities that don't know about it
> would have to be replaced, but right now that ends up being true anyway and
> with no warning other than a paragraph buried in some text file. Worse, if
> you have to dual-boot between kernels with incompatible /proc file formats,
> you can't easily deal with both from a single utility: but with version
> numbers, a utility could invoke code conditionally on the version number or
> even run a backend selected by version number (/usr/lib/backend.d/ifconfig/X.
> Y, anyone?).
>
> I'm not talking about anything really complicated here, just having
> /proc/foo/bar start with e.g. "!@ 1.1\n".

This is totally unnecessary if you write robust /proc parsers.

The most important principle is to use the power of scanf, but work with lines.
This means never do:

fscanf(procfh, format, &field, &field);

but always do

getline(procfh, line);
sscanf(line, format, &field, &field);

This makes sure that the parser can always recover from added fields at the end.

The second principle is to parse the field titles instead of implicitely knowing
them. proc_gen_fmt() [from nettools] implements this.

Assuming you have a /proc file in the format (like most files in /proc/net):

Bla Blub Bli
1 2 3
3 4 5
6 7 8
...

then simply use

fmt = proc_gen_fmt("/proc/myfile", procfh,
"Bla", "%d", "Blub", "%d", "Bli", "%d");
if (!fmt) error();

while ((line = getline(procfh)) != NULL) {
sscanf(line, fmt, &blavar, &blubvar, &blivar);
}

proc_gen_fmt does not handle the case when fields are permutted, but I have
never seen this in a /proc interface change, and it would be trivial to add.
I admit the static buffer sizes are ugly, but could be easily replaced.

Extensions to other proc file formats like:

A: 1 4 6
B: 2 6
C: 3

etc. are trivial. And it needs no kernel changes, just the application of a
principle that should be taught at the first day of every programming course @)

-Andi

/* Tolerant /proc file parser. Copyright 1998 Andi Kleen. Subject to the GPL*/

#include <string.h>
#include <stdarg.h>
#include <stdio.h>

/* Caller must free return string. */
char *
proc_gen_fmt(char *name, FILE *fh, ...)
{
char buf[1024], format[1024] = "";
char *title, *head;
va_list ap;

if (!fgets(buf, sizeof buf, fh))
return NULL;

va_start(ap,fh);
head = strtok(buf, " \t");
title = va_arg(ap, char *);
while (title && head) {
if (!strcmp(title, head)) {
strcat(format, va_arg(ap, char *));
title = va_arg(ap, char *);
} else {
strcat(format, "%*[^ \t]");
}
strcat(format, " ");
head = strtok(NULL, " \t");
}
va_end(ap);

if (title) {
fprintf(stderr, "warning: %s does not contain required field %s\n",
name, title);
return NULL;
}
return strdup(format);
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/