Code as Exemplar
Reasons
- Understand how it works
- Create compatible software
Strategy
- Try multiple approaches
- Search
- Browse
- Read documentation
- Run
- Run under a debugger
- Trace
- Ignore irrelevant details
Example: tail -f (NetBSD)
while ((ch = getopt(argc, argv, "b:c:fn:r")) != -1)
switch(ch) {
[...]
case 'f':
fflag = 1;
break;
}
[...]
for (;;) {
while ((ch = getc(fp)) != EOF)
if (putchar(ch) == EOF)
oerr();
[...]
if (!fflag)
break;
/*
* We pause for one second after displaying any data that has
* accumulated since we read the file. Since sleep(3) takes
* eight system calls, use select() instead.
*/
second.tv_sec = 1;
second.tv_usec = 0;
if (select(0, NULL, NULL, NULL, &second) == -1)
err(1, "select: %s", strerror(errno));
clearerr(fp);
}
Example: tail -f (FreeBSD)
if (fflag) {
kq = kqueue();
if (kq < 0)
err(1, "kqueue");
action = ADD_EVENTS;
}
for (;;) {
while ((ch = getc(fp)) != EOF)
if (putchar(ch) == EOF)
oerr();
[...]
if (! fflag)
break;
clearerr(fp);
switch (action) {
case ADD_EVENTS:
n = 0;
ts.tv_sec = 0;
ts.tv_nsec = 0;
if (Fflag && fileno(fp) != STDIN_FILENO) {
EV_SET(&ev[n], fileno(fp), EVFILT_VNODE,
EV_ADD | EV_ENABLE | EV_CLEAR,
NOTE_DELETE | NOTE_RENAME, 0, 0);
n++;
}
EV_SET(&ev[n], fileno(fp), EVFILT_READ,
EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, 0);
n++;
if (kevent(kq, ev, n, NULL, 0, &ts) < 0) {
action = USE_SLEEP;
} else {
action = USE_KQUEUE;
}
break;
kqueue, kevent - kernel event notification mechanism