        Allocate and bind a server socket

        From Douglas E. Comer and David L. Stevens: `Internetworking with
        TCP/IP Volume III'

<<*>>=
#include <config.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

static u_short portbase = 0;            /* Port base, for non-root servers */

EXPORT int passivesock(char *service, char *protocol, int qlen)
{
    struct servent *pse;        /* Pointer to service information entry */
    struct protoent *ppe;       /* Pointer to protocol information entry */
    struct sockaddr_in sin;     /* An Internet endpoint address */
    int s, type;                /* Socket descriptor and socket type */

    bzero((char *) &sin, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = INADDR_ANY;

    /* Map service name to port number */
    
    if ((pse = getservbyname(service, protocol)))
        sin.sin_port = htons(ntohs((u_short) pse->s_port) + portbase);
    else if ('0' <= *service && *service <= '9')
	sin.sin_port = htons((u_short) atoi(service));
    else 
        return -1;                              /* Can't get service entry */

    /* Map protocol name to protocol number */

    if ((ppe = getprotobyname(protocol)) == 0)
        return -1;                              /* Can't get protocol entry */

    /* Use protocol to choose a socket type */

    if (strcmp(protocol, "udp") == 0)
        type = SOCK_DGRAM;
    else
        type = SOCK_STREAM;

    /* Allocate a socket */

    if ((s = socket(PF_INET, type, ppe->p_proto)) < 0)
        return -1;                              /* Can't create socket */

    /* Bind the socket */

    if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0)
        return -1;                              /* Can't bind to port */
    if (type == SOCK_STREAM && listen(s, qlen) < 0)
        return -1;                              /* Can't listen on port */

    return s;
}

