You don't actually need i here. i is the same as (q - password). It would be idiomatic C to simply rewrite the loop condition as: while (q < password+sizeof(password) && (*q = getchar()) != '\n'). To preserve your "goto error;" part, maybe you could do the overflow check when null terminating outside the loop.
Isn't sizeof only standardised in C89? Wouldn't shock me if this form needs to be an rvalue.
The author did try pointer arithmetic:
> I initially attempted a fix using pointer arithmetic, but the 1973 C compiler didn’t like it, while it didn’t refuse the syntax, the code had no effect.
The article specifically mentions this optimization as not working with the compiler at that time, hence the need for the separate index variable.
> We will edit su.c to prevent the overflow by maintaining a counter, i, and verifying it against the buffer size during the read loop. I initially attempted a fix using pointer arithmetic, but the 1973 C compiler didn’t like it, while it didn’t refuse the syntax, the code had no effect. I settled on a simpler index-based check instead.