Xref: utzoo comp.bugs.4bsd:1669 comp.std.c:4186 comp.lang.c:35498 Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!wuarchive!psuvax1!hsdndev!cmcl2!kramden.acf.nyu.edu!brnstnd From: brnstnd@kramden.acf.nyu.edu (Dan Bernstein) Newsgroups: comp.bugs.4bsd,comp.std.c,comp.lang.c Subject: Re: Safe coding practices (was Re: Bug in users command) Message-ID: <22311:Jan2502:34:1191@kramden.acf.nyu.edu> Date: 25 Jan 91 02:34:11 GMT References: <1991Jan24.060707.22566@tkou02.enet.dec.com> <22870@well.sf.ca.us> Organization: IR Lines: 72 X-Tone: pissed Ah, yes, Jef takes his place next to Chris on my list of gurus I've caught in a mistake. Two mistakes, in fact. Read on... In article <22870@well.sf.ca.us> Jef Poskanzer writes: > I think this is an *excellent* example of appropriate programming > technology. Dan Bernstein's hack of reading utmp twice and allocating > 50 extra slots in case more users log in between the two is, when you > come down to it, *no better*. I address this below. You aren't thinking things through. My program would be objectively better than yours even if it allocated *zero* extra slots for users who log in after the first read. > Just more complicated. Worse, in fact, > since he *doesn't* check for overflow. I do check for overflow. See that test for i < lines + 50? Jef, I expect an apology. I appreciate criticism of my code, particularly when it gives me better insight into what people are looking for. But I don't appreciate someone trying to excuse his programming mistakes by saying ``Dan's code fucks up too'' when, in fact, my code works exactly as it's supposed to. Before this, I thought you were the type who would give constructive criticism---things like ``You should've cast back and forth to char * or void * at the qsort() interface.'' Not false accusations that show you hardly even pay attention to what you're talking about. > He complained about a hard > limit of 200 users and then Actually, my main project for last May was writing pty 3.0 from scratch, including the PD utilities (like u.c, who.c, etc.) that come with the package. So don't think I'm complaining about a problem without already having tried to fix it. > went and programmed a different hard limit > of 50 new users in an unknowable time period. You are wrong. You're correctly reporting the limit I coded, but you said above that this behavior is no better than your fixed limit. In that statement you are wrong. I won't go into a long treatise about the principles of taking snapshots of a dynamic system. But here are the two most important properties of ``foo'', a utmp scanner: 1. foo reports a user only if he is logged on at some point between when foo is invoked and when it finishes. 2. There is some time interval during which foo is running, such that foo reports any user who is logged on throughout that interval. (The reason readdir() isn't safe for some applications is that it doesn't obey #2 in most implementations.) Guess what? My version of users satisfies these properties. Your version fails #2. Now you can talk all you want about reallocating memory (btw, there's no safe way to use realloc(), but you knew that) to read in as many users as possible. I'll skip the comments about a quadratic time requirement, and about people who simply *talk* about code instead of *writing* code, and cut to the heart of the issue: You won't be able to identify a single functional requirement that your reallocating version satisfies and that my users program doesn't. You see, users has to exit at some point, and before that point there must be a window when users doesn't detect new logins. No external requirement can tell how big that window is. So there's no way to tell the difference between a program that cuts things off when people log on too fast and a program that is cut off by the scheduler. The best you can do is #2 above. (This explanation isn't particularly lucid, but if you try to say what advantage a reallocating version will have, you'll realize that there is none.) ---Dan