/* This file is part of Pies
Copyright (C) 2009 Sergey Poznyakoff
Pies is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
Pies is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Pies. If not, see . */
#ifdef HAVE_CONFIG_H
# include
#endif
#include "pies.h"
#include
#include
#include
#include
#include
#include
#include
int
str2port (char *str)
{
struct servent *serv;
char *p;
int port;
/* First try to read it from /etc/services */
serv = getservbyname (str, "tcp");
if (serv != NULL)
port = ntohs(serv->s_port);
else
{
unsigned long l;
/* Not in services, maybe a number? */
l = strtoul (str, &p, 0);
if (*p || l < 0 || l > USHRT_MAX)
return -1;
port = l;
}
return port;
}
static size_t
_my_stpcpy (char **pbuf, size_t *psize, const char *src)
{
size_t slen = strlen (src);
if (pbuf == NULL || *pbuf == NULL)
return slen;
else
{
char *buf = *pbuf;
size_t size = *psize;
if (size > slen)
size = slen;
memcpy (buf, src, size);
*psize -= size;
*pbuf += size;
if (*psize)
**pbuf = 0;
else
(*pbuf)[-1] = 0;
return size;
}
}
#define S_UN_NAME(sa, salen) \
((salen < offsetof (struct sockaddr_un,sun_path)) ? "" : (sa)->sun_path)
void
sockaddr_to_str (const struct sockaddr *sa, int salen,
char *bufptr, size_t buflen,
size_t *plen)
{
char buf[INT_BUFSIZE_BOUND (uintmax_t)]; /* FIXME: too much */
size_t len = 0;
switch (sa->sa_family)
{
case AF_INET:
{
struct sockaddr_in s_in = *(struct sockaddr_in *)sa;
len += _my_stpcpy (&bufptr, &buflen, inet_ntoa(s_in.sin_addr));
len += _my_stpcpy (&bufptr, &buflen, ":");
len += _my_stpcpy (&bufptr, &buflen,
umaxtostr(ntohs (s_in.sin_port), buf));
break;
}
case AF_UNIX:
{
struct sockaddr_un *s_un = (struct sockaddr_un *)sa;
if (S_UN_NAME(s_un, salen)[0] == 0)
len += _my_stpcpy (&bufptr, &buflen, "anonymous socket");
else
{
len += _my_stpcpy (&bufptr, &buflen, "socket ");
len += _my_stpcpy (&bufptr, &buflen, s_un->sun_path);
}
break;
}
default:
len += _my_stpcpy (&bufptr, &buflen, "{Unsupported family: ");
len += _my_stpcpy (&bufptr, &buflen, umaxtostr (sa->sa_family, buf));
len += _my_stpcpy (&bufptr, &buflen, "}");
}
if (plen)
*plen = len + 1;
}
char *
sockaddr_to_astr (const struct sockaddr *sa, int salen)
{
size_t size;
char *p;
sockaddr_to_str(sa, salen, NULL, 0, &size);
p = xmalloc (size);
sockaddr_to_str(sa, salen, p, size, NULL);
return p;
}