/*
 * Copyright (c) 1983 Regents of the University of California.
 * All rights reserved.  The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 */

#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getservbyname.c	5.3 (Berkeley) 5/19/86";
#endif LIBC_SCCS and not lint

#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <ctype.h>
#include <pwd.h>
#ifdef POSIX
#include <stdlib.h>
#else
extern char *malloc();
#endif
#include "hesiod.h"

extern int Hes_Errno;

struct servent *
hes_getservbyname(name, proto)
	char *name, *proto;
{
	static struct servent result;
	static char buffer[2048];
	int status;

	status = hes_getservbyname_r(name, proto, &result, buffer, 2048);
	if (status == HES_ER_OK) {
	    return(&result);
	} else {
	    Hes_Errno = status;
	    return(NULL);
	}
}

int
hes_getservbyname_r(name, proto, result, buffer, buflen)
	char *name, *proto, *buffer;
	struct servent *result;
	int buflen;
{
	register char **cp, **aliases = (char **) buffer;
	char *buf[100], *line;
	register int i = 0;
	int status;

	status = hes_resolve_r(name, "service", buf, 100);
	if (status != HES_ER_OK) return(status);
	status = HES_ER_NOTFOUND;
	for (cp = buf; *cp; cp++) {
		register char *servicename, *protoname, *port, *l = *cp;
		register int len = strlen(l);

		/* Find the service name. */
		while(*l && (*l == ' ' || *l == '\t'))
			l++;
		servicename = l;
		while(*l && *l != ' ' && *l != '\t' && *l != ';')
			l++;
		if (*l == '\0') /* malformed entry */
			continue;
		*l++ = '\0';

		/* Find the protocol name and check it. */
		while(*l && (*l == ' ' || *l == '\t'))
			l++;
		protoname = l;
		while(*l && *l != ' ' && *l != ';')
			l++;
		if (*l == '\0') /* malformed entry */
			continue;
		*l++ = '\0';
		if (cistrcmp(proto, protoname)) /* wrong protocol */
			continue;

		/* Find the port number. */
		while(*l && (*l == ' ' || *l == '\t' || *l == ';'))
			l++;
		if (*l == '\0') /* malformed entry */
			continue;
		port = l;

		while(*l && *l != ' ' && *l != '\t' && *l != ';')
			l++;
		if (*l)
			*l++ = '\0';
		while (*l) {
			if ((i + 2) * sizeof(char *) + len >= buflen)
				break;
			aliases[i++] = l;
			while(*l && !isspace(*l))
				l++;
			if (*l)
				*l++ = 0;
		}
		if ((i + 1) * sizeof(char *) + len >= buflen) {
			status = HES_ER_RANGE;
			break;
		}
		aliases[i++] = 0;
		line = (char *)(aliases + i);
		memcpy(line, *cp, len + 1);
		result->s_name = line;
		result->s_port = htons((unsigned short) atoi(port));
		result->s_proto = line + (protoname - *cp);
		result->s_aliases = aliases;
		for (; *aliases; aliases++)
			*aliases = line + (*aliases - *cp);
		status = HES_ER_OK;
		break;
	}
	for (cp = buf; *cp; cp++)
		free(*cp);
	return(status);
}
