Subject: Re: Better than..
To: Greg Scott <gscott@londononline.net>
From: Manuel Bouyer <bouyer@antioche.lip6.fr>
List: port-i386
Date: 01/04/2000 22:17:27
--UlVJffcvxoiEqYs2
Content-Type: text/plain; charset=us-ascii

[Cc:'d to netbsd-advocacy]

On Mon, Jan 03, 2000 at 06:31:38PM -0500, Greg Scott wrote:
> Anyone know of where I can find a list of things that make NetBSD better
> than say.. oh. Linux?

I can see two major advantages:
- reliability. Linux will do the job as well, as long as nothing hurt it.
  But in face of a unexpected event it'll behave very badly and may not
  recover (or be hard to recover). You can make 2 experiments really
  demonstrative of this:
  1) setup a linux mail server (a stock redhat install is enouth) and feed
  it with one or more client which sends mail as fast as they can (you can
  use the small program attached for this, it's best to change it to just
  print a sequence number). let it run this way for 10-20s and hit the reset
  button. The server will not come back up without a fsck -y and mail will
  be lost (just count how many were sent and how many are in the destination
  mailbox). Do the same with a NetBSD server: sure it seems slower but after
  the reset it comes back up without assistance and no mail are lost (at worse
  there are some duplicates).
  2) find a CD with bad blocks (or scratch one if you don't have a bad one :)
  and try to read it on a linux box with a IDE drive. The last time I did this
  on a stock redhat 6 I had to hit the reset button, I could'nt even reboot
  it.

- pkgsrc is a bit win over binary distributions (rpm or whatever) because it
  includes tools that can't be redistributed in binary or source form,
  or for which you have to fill in a form (e.g. the realaudio proxy).
  The last one which hit me today is xv: no xv rpm in the redhat distrib,
  you have to build one by hand (some numbers: we have about more than 1000
  packages in pkgsrc, the redhat CD comes with only 700 rpms, and the base
  system is inclued !). Sure there are redhat-contribs ... all of them don't
  work out of the box :)

I happen to give courses in a high school which uses linux for his NFS servers.
3 hours were needed to get them back up after a power outage, and it's common
to have a server unaviable because noone is here to hit the reset button.
Maybe the environnement is not ideal but the previous servers were
Sun/SunOS4 or Solaris2.5 and had much less problems. I'm pretty sure NetBSD
would have been a better choise for this (but they use a SCSI board for wich
only a linux kernel module in binary form is available - did you say GPL ? :)

> 
> I need to convince a client that hype doesn't mean quality.
> 

I had to do this only a few weeks ago. I think I was successfull as I've got
the authorisation to "upgrade" our mail server from solaris to NetBSD :)

--
Manuel Bouyer <bouyer@antioche.eu.org>
--

--UlVJffcvxoiEqYs2
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="smtptorture.c"

#include <ctype.h>
#include <fcntl.h>
#include <memory.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>

#include <netinet/in.h>

#include <sys/socket.h>

char *ehlo = "ehlo rochebonne.lip6.fr\n";
char *from = "mail from: bouyer\n";
char *to = "rcpt to: root\n";
char *data = "data\n";
char *rset = "rset\n";
char *dot = ".\n";

char *body = "Subject: test\n\n"
"# tcsh\n"
"/cordouan:/home/bouyer# /usr/sbin/sendmail -bd -q10m\n"
"cordouan:/home/bouyer# w\n"
" 2:39PM  up 2 mins, 4 users, load averages: 0.93, 0.50, 0.21\n"
" USER    TTY FROM              LOGIN@  IDLE WHAT\n"
" w: proc size mismatch (26544 total, 688 chunks)\n"
" cordouan:/home/bouyer# \n";

void smtp_send(int, char*, int);
int smtp_receive(int);

int
main(int argc, char **argv)
{
	char *server ;
	u_short port ;
	int client_socket , sendmail_err;
	struct hostent *host ;
	struct sockaddr_in server_sockaddr ;

	if ( argc != 3 )
	{
		fprintf ( stderr , "usage: client host port\n" ) ;
		exit ( EXIT_FAILURE ) ;
	}

	server = argv [ 1 ] ;
	port = atoi ( argv [ 2 ] ) ;

	client_socket = socket ( PF_INET , SOCK_STREAM , 0 ) ;
	if ( client_socket == -1 ) {
		perror ( "socket" ) ;
		exit ( EXIT_FAILURE ) ;
	}

	host = gethostbyname ( server ) ;
	if ( host == NULL ) {
		perror ( "gethostbyname" ) ;
		exit ( EXIT_FAILURE ) ;
	}

	memset ( &server_sockaddr , 0 , sizeof ( server_sockaddr ) ) ;
	server_sockaddr . sin_family = AF_INET ;
	server_sockaddr . sin_port = htons ( port ) ;
	server_sockaddr . sin_addr. s_addr = ** ( u_long ** ) host -> h_addr_list ;

	if ( connect ( client_socket , ( struct sockaddr * ) &server_sockaddr ,
		 sizeof ( server_sockaddr ) ) == -1 ) {
		perror ( "connect" ) ;
		exit ( EXIT_FAILURE ) ;
	}


	sendmail_err = smtp_receive(client_socket);
	if (sendmail_err != 2) {
		close(client_socket);
		exit(1);
	}
	smtp_send(client_socket, ehlo, 1);
	sendmail_err = smtp_receive(client_socket);
	if (sendmail_err != 2) {
		close(client_socket);
		exit(1);
	}
#define CHECK_ERR  do {\
	sendmail_err = smtp_receive(client_socket);\
	if(sendmail_err == 5) {\
		close(sendmail_err);\
		exit(1);\
	}\
	if(sendmail_err == 4) {\
		sleep(60);\
		goto reset;\
	}\
	} while (0)
	
	for (;;) {
		smtp_send(client_socket, from, 1);
		CHECK_ERR;
		smtp_send(client_socket, to, 1);
		CHECK_ERR;
		smtp_send(client_socket, data, 1);
		CHECK_ERR;
		smtp_send(client_socket, body, 0);
		smtp_send(client_socket, dot, 1);
		CHECK_ERR;
reset:	smtp_send(client_socket, rset, 1);
		CHECK_ERR;
	}
	exit(EXIT_SUCCESS);
}


void smtp_send(int fd, char* str, int flags)
{
	int bytes;
again:
	bytes = write(fd, str, strlen(str));
	if (bytes == 0) {
		close(fd);
		exit(0);
	}
	if (bytes == -1) {
		perror("write");
		sleep(2);
		goto again;
	}
	if (flags & 1)	
		write(2, str, strlen(str));
}

int smtp_receive(int fd)
{
	char readval = 0;
	char ret;
	int bytes, again, nbc;

again:
	bytes = read(fd, &ret, 1);
	if (bytes == 0) {
		close(fd);
		exit(0);
	}
	if (bytes == -1) {
		perror("read");
		sleep(2);
		goto again;
	}
	write(2, &ret, 1);
	ret = ret - 48;
	nbc = 1;
	again=0;
	while (1) {
again2:
		bytes = read(fd, &readval, 1);
		if (bytes == 0) {
			close(fd);
			exit(0);
		}
		if (bytes == -1) {
			perror("read");
			sleep(2);
			goto again2;
		}
		nbc++;
		if (nbc == 4 && readval=='-')
			again=1;
		write(2, &readval, 1);
		if (readval == '\n') {
			if(again == 1)
				goto again;
			return(ret);
		}
	}
}

--UlVJffcvxoiEqYs2--