
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include "gai.h"

/*
 * This function handles the service string.
 */

/* include ga_serv */
int ga_serv(struct addrinfo *aihead, const struct addrinfo *hintsp, const char *serv)
{
    int port, rc, nfound;
    struct servent *sptr;

    nfound = 0;
    if (isdigit(serv[0])) {	/* check for port number string first */
	port = htons(atoi(serv));
	if (hintsp->ai_socktype) {
	    /* caller specifies socket type */
	    if ((rc = ga_port(aihead, port, hintsp->ai_socktype)) < 0)
		return (EAI_MEMORY);
	    nfound += rc;
	} else {
	    /* caller does not specify socket type */
	    if ((rc = ga_port(aihead, port, SOCK_STREAM)) < 0)
		return (EAI_MEMORY);
	    nfound += rc;
	    if ((rc = ga_port(aihead, port, SOCK_DGRAM)) < 0)
		return (EAI_MEMORY);
	    nfound += rc;
	}
    } else {
	/* try service name, TCP then UDP */
	if (hintsp->ai_socktype == 0 || hintsp->ai_socktype == SOCK_STREAM) {
	    if ((sptr = getservbyname(serv, "tcp")) != NULL) {
		if ((rc = ga_port(aihead, sptr->s_port, SOCK_STREAM)) < 0)
		    return (EAI_MEMORY);
		nfound += rc;
	    }
	}
	if (hintsp->ai_socktype == 0 || hintsp->ai_socktype == SOCK_DGRAM) {
	    if ((sptr = getservbyname(serv, "udp")) != NULL) {
		if ((rc = ga_port(aihead, sptr->s_port, SOCK_DGRAM)) < 0)
		    return (EAI_MEMORY);
		nfound += rc;
	    }
	}
    }

    if (nfound == 0) {
	if (hintsp->ai_socktype == 0)
	    return (EAI_NONAME);	/* all calls to getservbyname() failed */
	else
	    return (EAI_SERVICE);	/* service not supported for socket type */
    }
    return (0);
}
