That means there was no wait() anywhere! Since the ttymsg() function used by wall, write, and talkd forks off a child whenever writing to a tty would block, it was creating a zombie process every time we typed in a line! These zombies built up to the point where nobody could fork off any new processes. Exiting nwall orphaned them, letting init do a collossal clean-up job.
Seth suggested that I use wait3 or wait4, but I wanted to be all warm and fuzzy and POSIX-compliant, so I suggested waitpid(). Seth came up with the call before I could, so the ttymsg code in nwall now contains while(waitpid(0, NULL, WNOHANG)) ; in the parent section.
Of course, the thing I don't understand is why this was never caught, since the write program could potentially suffer the same problem.