Re: [dev] [lnanosmtp]

From: Markus Wichmann <nullplan_AT_gmx.net>
Date: Thu, 9 Jun 2016 19:18:21 +0200

On Thu, Jun 09, 2016 at 10:50:56PM +1100, Sylvain BERTRAND wrote:
> Hi,
>
> Introducing a new minimal and naive smtp server à la suckless: lnanosmtp
>
> https://github.com/sylware/lnanosmtp
> https://repo.or.cz/lnanosmtp.git
>
> cheers,
>
> --
> Sylvain
>

Dear Lord, it's been a while since I've seen such nice code make so
bafflingly bad design choices. Where to start?

1. The whole ulinux thing smacks a bit of NIH syndrome to me. And of
course, it kisses portability goodbye, but then that wasn't your goal at
all. With only i386 and AMD64 supported, I wonder why this isn't in
assembler.

2. You immediately block all signals on entry. That means:
    - SIGINT, SIGQUIT, SIGTSTP, SIGTTOU, SIGTTIN: There is no way to
      control the process from a terminal. You have to get another
      terminal out to kill it.
    - SIGSEGV, SIGILL, SIGBUS: Undefined behaviour if your code does
      anything to warrant the sending of those signals.
    - SIGCHLD: Zombies and no way of knowing about them. Why don't you
      just ignore it?
    - SIGXCPU, SIGXFSZ: No way to gracefully close on reaching ulimits.

And so on, and so forth. And for what? So you can handle signals using
signalfd. That would be good if you actually did that. However, that
only happens if the client never stalls out on you.

3. smtp_line_send() can't handle short writes, because the pointer that
is handed in as second argument to write() is never advanced, nor is the
unwritten part memmove()d to the front, as ridiculous as that would be.

4. Synchronous communication, no forking, no threading --> One client at
a time. So you're using epoll on the same two sockets all the time,
which means you might as well not have bothered.

Still, it could easily be salvaged: Drop all the setup code for the
server socket and make the code read from stdin and write to stdout.
Then this server can be run from inetd, or through any ucspi
implementation. That will also remove the glaring issue that the program
must be run as root and doesn't drop privileges even when it's done
doing privileged things.

5. Exiting at the drop of a hat: Your only error handling is to exit,
unless it was an expected error (usually EINTR). That's the opposite of
PHP, I guess, but that doesn't make it better.

6. You do know that if you used a C library, you'd have access to
strchr(), strcpy(), and the like, right? Because you seem to be having a
jolly good time rewriting those over and over again.

7. What's with the S_IFMT constants? You're binding hard to the syscall
interface, you can use 0666, it's not getting any less portable now.

8. You do know that C has more loop contructs than just the endless one,
right? Because I'm seeing a lot of endless loops that are basically
do-while loops, or counting loops... C has structured programming. Use
it! Please...

9. Oh wait, I see that you have strcpy(), you just don't use it.
Alrighty then.

And that was just what I saw in lnanosmtp.c. And I didn't check the
protocol.

Ciao,
Markus
Received on Thu Jun 09 2016 - 19:18:21 CEST

This archive was generated by hypermail 2.3.0 : Thu Jun 09 2016 - 19:24:11 CEST