#ifdef RCS
static char rcsid[]="$Id: netstuff.c,v 1.1.1.1 2000/11/13 02:42:45 holsta Exp $";
#endif
/******************************************************************************
* Internetting Cooperating Programmers
* ----------------------------------------------------------------------------
*
* ____ PROJECT
* | _ \ __ _ _ __ ___ ___ _ __
* | | | |/ _` | '_ \ / __/ _ \ '__|
* | |_| | (_| | | | | (_| __/ |
* |____/ \__,_|_| |_|\___\___|_| the IRC bot
*
* All files in this archive are subject to the GNU General Public License.
*
* $Source: /cvsroot/dancer/dancer/src/netstuff.c,v $
* $Revision: 1.1.1.1 $
* $Date: 2000/11/13 02:42:45 $
* $Author: holsta $
* $State: Exp $
* $Locker: $
*
* ---------------------------------------------------------------------------
*****************************************************************************/
/*
* Lowlevel socket handling. Primarily based on IPC primer 4.2.
*/
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#if defined(AMIGA) && !defined(__GNUC__)
# include <sys/errno.h>
# include <sys/ioctl.h>
# include <sys/utsname.h>
#else
# ifdef HAVE_YP_MASTER
# include <rpcsvc/ypclnt.h>
# endif
#endif
#include "dancer.h"
#include "trio.h"
#include "strio.h"
#include "function.h"
#include "user.h"
#include "server.h"
#include "transfer.h"
#include "netstuff.h"
#include "link.h"
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
#ifndef INADDR_NONE
#define INADDR_NONE -1
#endif
/* --- Global ----------------------------------------------------- */
extern bool restart;
extern bool cleanup;
extern bool chat;
extern char nameserver[];
extern char dancer_myhost[];
extern time_t lastevent;
extern int serverSocket;
extern itemident *current;
extern itemclient *clientHead;
char myhost[MAXHOSTNAMELEN];
ulong myipaddrnum = 0;
time_t now = 0;
int linkSocket = -1;
fd_set rdset;
fd_set wrset;
struct sockaddr_in linkaddr;
struct sockaddr_in fromaddr;
itemclient *client = NULL;
/* --- GetHost ---------------------------------------------------- */
struct hostent *GetHost(char *hostname)
{
static struct hostent he;
static char name[MAXHOSTNAMELEN];
static char *aliaslist[1], *addrlist[2];
static struct in_addr addrentry;
struct hostent *hp;
ulong in;
snapshot;
in = inet_addr(hostname);
if (INADDR_NONE == in) {
hp = gethostbyname(hostname);
if (NULL == hp)
Debug("gethostbyname(2) failed for %s (%s)", hostname, StrError(errno));
}
else {
aliaslist[0] = NULL;
addrentry.s_addr = in;
addrlist[0] = (char *)&addrentry;
addrlist[1] = NULL;
he.h_name = StrCopyMax(name, sizeof(name), MakeIP(ntohl(in)));
he.h_aliases = aliaslist;
he.h_addrtype = AF_INET;
he.h_length = sizeof(struct in_addr);
he.h_addr_list = addrlist;
hp = &he;
}
return hp;
}
/* --- MakeIP ----------------------------------------------------- */
char *MakeIP(ulong num)
{
#ifdef HAVE_INET_NTOA
struct in_addr in;
snapshot;
in.s_addr = htonl(num);
return inet_ntoa(in);
#else
static char addr[MINIBUFFER];
unsigned char *paddr;
snapshot;
num = htonl(num); /* htonl() added to avoid endian probs */
paddr = (unsigned char *)#
StrFormatMax(addr, sizeof(addr), "%u.%u.%u.%u",
paddr[0], paddr[1], paddr[2], paddr[3]);
return addr;
#endif
}
/* --- CloseConnection -------------------------------------------- */
void CloseConnection(int s)
{
snapshot;
if (0 <= s) {
FD_CLR(s, &rdset);
FD_CLR(s, &wrset);
close(s);
}
}
/* --- SetSockOpt ------------------------------------------------- */
void SetSockOpt(int s)
{
struct linger l;
snapshot;
l.l_onoff = l.l_linger = 0;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 0, 0);
setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, 0, 0);
setsockopt(s, SOL_SOCKET, SO_LINGER, (char *)&l, sizeof(l));
}
/* --- Connect ---------------------------------------------------- */
void Blocking(int s)
{
#if !defined(AMIGA) || defined(__GNUC__)
int flags;
snapshot;
flags = fcntl(s, F_GETFL, 0);
#ifdef NBLOCK_BSD
fcntl(s, F_SETFL, flags & (~FNDELAY));
#else
fcntl(s, F_SETFL, flags & (~O_NONBLOCK));
#endif
#else
snapshot;
IoctlSocket(s, FIONBIO, 1L);
#endif
}
void NonBlocking(int s)
{
#if !defined(AMIGA) || defined(__GNUC__)
int flags;
snapshot;
flags = fcntl(s, F_GETFL, 0);
#ifdef NBLOCK_BSD
fcntl(s, F_SETFL, flags | FNDELAY);
#else
fcntl(s, F_SETFL, flags | O_NONBLOCK);
#endif
#else
snapshot;
IoctlSocket(s, FIONBIO, 0L);
#endif
}
void Connected(itemclient *c)
{
snapshot;
c->status = CL_CONNECTED;
SetSockOpt(c->socket);
FD_CLR(c->socket, &wrset);
FD_SET(c->socket, &rdset);
Blocking(c->socket);
Logf(LOGCLIENT, "Connection accepted at socket %d", c->socket);
}
int Connect(int s, void *psa)
{
struct sockaddr_in sa;
snapshot;
memset(&sa, 0, sizeof(sa));
sa.sin_family = ((struct sockaddr_in *)psa)->sin_family;
sa.sin_port = htons((unsigned short)0);
/* Bind to INADDR_ANY to allow connections to any local interface */
sa.sin_addr.s_addr = (0 == myipaddrnum) ? htonl(INADDR_ANY) :
htonl(myipaddrnum);
if (-1 == bind(s, (struct sockaddr *)&sa, sizeof(sa))) {
Debug("bind(2) failed on socket %d (%s), myhost = %s, myipaddrnum = %lu",
s, StrError(errno), myhost, myipaddrnum);
}
return connect(s, (struct sockaddr *)psa, sizeof(struct sockaddr_in));
}
/* Non-blocking connect */
bool ConnectNB(itemclient *c)
{
snapshot;
FD_SET(c->socket, &wrset);
NonBlocking(c->socket);
if (-1 == Connect(c->socket, &c->addr)) {
/* connect() failed */
c->status = CL_CONNECTING;
return ((EINPROGRESS == errno) || (EAGAIN == errno) || (EWOULDBLOCK == errno));
}
Connected(c);
return TRUE;
}
/* --- OpenConnection --------------------------------------------- */
int OpenServerConnection(char *hostname, int port)
{
snapshot;
return OpenConnection(hostname, port);
}
itemclient *OpenClientConnection(char *from, char *uhost, itemuser *user,
char *hostname, int port)
{
struct hostent *hp;
itemclient *c;
snapshot;
hp = GetHost(hostname);
if (hp) {
c = AddClient(from, uhost, user, -1);
if (c) {
memcpy((char *)&c->addr.sin_addr, hp->h_addr, hp->h_length);
c->addr.sin_family = hp->h_addrtype;
c->addr.sin_port = htons((unsigned short)port);
c->socket = socket(hp->h_addrtype, SOCK_STREAM, 0);
if (0 <= c->socket) {
if (ConnectNB(c)) {
c->linksort = OUT_CHAT; /* Mark this as chat */
return c;
}
}
RemoveClient(c);
}
}
return NULL;
}
int OpenConnection(char *hostname, int port)
{
struct hostent *hp;
struct sockaddr_in sa;
struct linger l;
int s;
snapshot;
hp = GetHost(hostname);
if (hp) {
memset((char *)&sa, 0, sizeof(sa));
memcpy((char *)&sa.sin_addr, hp->h_addr, hp->h_length);
sa.sin_family = hp->h_addrtype;
sa.sin_port = htons((unsigned short)port);
s = socket(hp->h_addrtype, SOCK_STREAM, 0);
if (0 <= s) {
if (0 <= Connect(s, &sa)) {
SetSockOpt(s);
FD_SET(s, &rdset);
return s;
}
else {
CloseConnection(s);
Debug("connect(2) failed on socket %d (%s)", s, StrError(errno));
}
}
else
Debug("socket(2) failed for %s (%s)", hostname, StrError(errno));
}
return -1;
}
/* --- OpenListener ----------------------------------------------- */
itemclient *OpenListener(char *from, char *userhost, itemuser *user)
{
struct sockaddr_in sa;
struct hostent *hp;
itemclient *c;
int size;
snapshot;
hp = GetHost(myhost);
if (hp) {
c = AddClient(from, userhost, user, -1);
if (c) {
c->socket = socket(hp->h_addrtype, SOCK_STREAM, 0);
if (0 <= c->socket) {
memset((char *)&sa, 0, sizeof(sa));
memcpy((char *)&sa.sin_addr, hp->h_addr, hp->h_length);
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = INADDR_ANY;
sa.sin_port = htons((unsigned short)0);
size = sizeof(sa);
if (0 <= bind(c->socket, (struct sockaddr *)&sa, size)) {
if (0 <= listen(c->socket, 1)) {
c->status = CL_LISTENING;
FD_SET(c->socket, &rdset);
/* Re-using sa */
size = sizeof(&c->addr);
getsockname(c->socket, (struct sockaddr *)&c->addr, &size);
return c;
}
else
Debug("listen(2) failed on socket %d (%s)", c->socket, StrError(errno));
}
else
Debug("bind(2) failed on socket %d (%s)", c->socket, StrError(errno));
}
else
Debug("socket(2) failed (%s)", StrError(errno));
RemoveClient(c);
}
}
return NULL;
}
/* ---OpenLink ---------------------------------------------------- */
int OpenLink(void)
{
int s, size;
snapshot;
s = socket(AF_INET, SOCK_DGRAM, 0);
if (0 <= s) {
size = sizeof(linkaddr);
memset((char *)&linkaddr, 0, size);
linkaddr.sin_family = AF_INET;
linkaddr.sin_addr.s_addr = htonl(INADDR_ANY);
linkaddr.sin_port = htons((unsigned short)0);
if (0 <= bind(s, (struct sockaddr *)&linkaddr, size)) {
FD_SET(s, &rdset);
getsockname(s, (struct sockaddr *)&linkaddr, &size);
return s;
}
/* close(s); ? */
}
return -1;
}
/* --- Outgoing --------------------------------------------------- */
void Outgoing(char *from, char linksort, char *opts)
{
char buffer[BIGBUFFER];
char buffer2[BIGBUFFER];
itemclient *c;
snapshot;
if (NULL == from)
from = current->nick;
if (OUT_LINK == linksort) {
SendCtcpf(from, "DCC LINK UDP %lu %u",
myipaddrnum, htons(linkaddr.sin_port));
}
else if (OUT_CHAT == linksort) {
c = OpenListener(from, current->host, current->user);
if (c) {
SendCtcpf(from, "DCC CHAT chat %lu %u",
myipaddrnum, htons(c->addr.sin_port));
c->linksort = linksort;
}
else
ReplyCtcp(from, "ERRMSG Unable to establish connection");
}
#ifdef BAGDER
else if (OUT_SEND == linksort) {
char *ptr;
bool uselocal = TRUE;
int file;
while ('/' == *opts)
opts++;
StrFormatMax(buffer, sizeof(buffer), "%s/%s", DCC_FILEPATH, opts);
StrFormatMax(buffer2, sizeof(buffer2), "%s/%s", DCC_FILECACHE, opts);
/* StrCopy(buffer2, buffer); */
ptr = buffer2 + StrLength(DCC_FILECACHE) + 1;
while (*ptr) {
if ('/' == *ptr)
*ptr = '_';
ptr++;
}
/* Things done here:
1) Check if the file is in the cache, and use that if it is
2) - fetch the file from the primary site and write it in the
cache dir, start DCCing as soon as the file grows
(timout the wait in X seconds, 20<X<60 seconds)
and continue until the fetch signals DONE (even if some
reads may not give new data due to slow ftp fetch)
- when the ftp is done (the Exec() job is complete), the
client should get noted
- file existance and size should be checked, 0 bytes means
failed ftp => abort DCC (retry next ftp site when multiple
ones are supported)
*/
/* First out, check for the file in the cache */
file = open(buffer2, O_RDONLY);
if (-1 == file) {
/* Not in the cache, we need to get it from the ftp site */
int s; /* to read the file from */
/* Get the file from the FTP server, we lock this synchronously at
least for a start, all the way until we start downloading the
file, which will be done as a receiving socket as on additional
socket client */
if (!ftpget(site, buffer, &s, &size)) {
/* we got a file size and a socket back, use them both */
itemclient *k = AddClient(from, NULL, NULL, s);
if (k) {
file = open(temporary, O_RDONLY);
}
}
}
if (0 <= file) {
/* Add this download to the cache */
CacheAdd(buffer2);
}
if (file > 0) {
char *filebuffer = malloc(CLF_FILEBUFFER);
if (buffer &&
(c = OpenListener(from, current->host, current->user))) {
char *filepart;
c->file = file;
c->linksort = linksort;
c->lasttime = time(NULL);
c->filebuffer = filebuffer;
if (uselocal)
/* if this is a local file, it is considered complete already */
c->fileflags |= CLF_FILECOMPLETE;
filepart = StrIndexLast(buffer, '/');
if (filepart)
filepart++;
else
filepart = buffer;
/* That silly AmIRC client requires a file length parameter! */
SendCtcpf(from, "DCC SEND %s %lu %u -1", filepart,
myipaddrnum, htons(c->addr.sin_port));
fprintf(stderr, "DCC SEND %s %lu %u -1\n", filepart,
myipaddrnum, htons(c->addr.sin_port));
}
else
ReplyCtcp(from, "ERRMSG Unable to establish connection");
}
else
ReplyCtcp(from, "ERRMSG Unable to get the specified file");
}
#endif
}
/* --- Alive ------------------------------------------------------ */
bool Alive(int s)
{
struct sockaddr name;
int namelen;
snapshot;
namelen = sizeof(name);
if (-1 == getpeername(s, &name, &namelen)) {
if (ENOTCONN == errno) {
errno = 0;
return FALSE;
}
}
return TRUE;
}
/* --- ReadSocket ------------------------------------------------- */
int ReadSocket(int s, char *buffer, size_t buffer_size)
{
char c;
int i = 0;
snapshot;
do {
if (1 > read(s, &c, 1))
return 0;
if (i < (buffer_size - 1))
buffer[i++] = c;
} while (c != '\n');
buffer[i] = (char)0;
#ifdef DBUG
fprintf(stderr, "%d < %s", s, buffer);
#endif
return i;
}
static int ReadFileSendSocket(int s, char *buffer)
{
char c;
int i = 0;
snapshot;
do {
if (read(s, &c, 1) < 1)
return 0;
buffer[i++] = c;
} while (i < 4); /* This *IS* always 4-bytes as "defined" in the crappy
DCC SEND standard */
return i;
}
static int WriteFileSendSocket(itemclient *c)
{
int n;
snapshot;
if (c->filesent == c->fileacked) {
n = read(c->file, c->filebuffer, CLF_FILEBUFFER);
if (n > 0) {
int err = write(c->socket, c->filebuffer, n);
c->filesent += n;
fprintf(stderr, "write() returned %d - sent %d bytes\n", err, c->filesent);
}
return n;
}
return 1; /* Don't terminate now */
}
/* --- WriteSocket ------------------------------------------------ */
inline void WriteSocket(int s, char *msg)
{
snapshot;
#ifdef DBUG
fprintf(stderr, "%d > %s\n", s, msg);
#endif
write(s, msg, StrLength(msg));
write(s, "\n", 1);
}
void WriteSocketf(int s, char *format, ...)
{
char buffer[MAXLINE-2]; /* CR-LF, max 510 chars / line */
va_list args;
snapshot;
va_start(args, format);
trio_vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);
WriteSocket(s, buffer);
}
/* --- WriteNick -------------------------------------------------- */
inline void WriteNick(char *nick, char *msg)
{
snapshot;
WriteSocketf(serverSocket, "NOTICE %s :%s", nick, msg);
}
/* --- WriteServer ------------------------------------------------ */
void WriteServer(char *format, ...)
{
static char buffer[MAXLINE-2];
va_list args;
snapshot;
va_start(args, format);
trio_vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);
WriteSocket(serverSocket, buffer);
}
/* --- HandleSockets ---------------------------------------------- */
void HandleSockets(fd_set *readset, fd_set *writeset)
{
extern itemexec *execHead;
char buffer[MAXLINE];
int s;
itemclient *c, *next;
itemexec *px, *pxx;
snapshot;
/* --- Server messages --- */
if (FD_ISSET(serverSocket, readset)) {
if (0 < ReadSocket(serverSocket, buffer, sizeof(buffer))) {
ParseServer(buffer);
}
else {
/* This is never reached? see ReadSocket() */
/* Error or EOF from server */
Debug("EOF from server (%s)", StrError(errno));
DisconnectServ("EOF from server (%s)", StrError(errno));
restart = cleanup = TRUE;
}
}
#ifdef BREESE
/* --- Link bots --- */
if (FD_ISSET(linkSocket, readset)) {
if (0 < ReadLink(buffer))
LinkParse(buffer);
}
#endif
/* --- Dcc clients --- */
for (c = First(clientHead); c; c = next) {
next = Next(c);
if (FD_ISSET(c->socket, readset)) {
/* To make sure we won't handle the same socket twice (CUT command) */
FD_CLR(c->socket, readset);
if (CL_LISTENING == c->status) {
int size = sizeof(struct sockaddr_in);
/* If we got something on a listen connection go ahead and accept it */
s = accept(c->socket, (struct sockaddr *)&c->addr, &size);
switch (s) {
case -1:
Debug("accept(2) failed on socket %d (%s)", c->socket, StrError(errno));
RemoveClient(c);
break;
default:
CloseConnection(c->socket);
c->socket = s;
c->status = CL_CONNECTED;
FD_SET(c->socket, &rdset);
if (OUT_SEND == c->linksort) {
FD_SET(c->socket, &wrset);
fprintf(stderr, "File sending initiated, here it should come...\n");
}
Logf(LOGCLIENT, "Connection accepted at socket %d", c->socket);
break;
}
continue; /* for */
}
else {
/* Message on a normal client connection */
client = c;
if (OUT_SEND == c->linksort) {
/* This is a file sending socket, we might/should receive ACKs on
this. */
unsigned int ack;
unsigned int networkack;
s = ReadFileSendSocket(c->socket, (char *)&networkack);
ack = ntohl(networkack);
c->fileacked = ack; /* this many bytes acknowledged from the peer */
fprintf(stderr, "=> GOT ACK %d\n", ack);
}
else {
s = ReadSocket(c->socket, buffer, sizeof(buffer));
}
switch (s) {
case -1: /* Read error on client */
/* This is never reached? see ReadSocket() & ReadFileSendSocket() */
Debug("Error on client (%s)", StrError(errno));
break;
case 0: /* EOF from client */
RemoveClient(c);
continue; /* for */
default:
if (OUT_CHAT == c->linksort) {
DccCommand(buffer);
/*
* This dirty hack is needed because some commands may remove
* ANY client. Get rid of the hack and the FD_CLRs.
*/
for (next = First(clientHead); next; next = Next(next)) {
if (FD_ISSET(next->socket, readset) ||
FD_ISSET(next->socket, writeset))
break;
}
continue; /* for */
}
/* else got file data */
break;
}
}
}
/*
* Write signal is only received when a non-blocking connection is
* established.
*/
if (FD_ISSET(c->socket, writeset)) {
/* To make sure we won't handle the same socket twice (CUT command) */
FD_CLR(c->socket, writeset);
if (CL_CONNECTING == c->status) {
/*
* Re-issue connect() to get the error.
* Better to use getsockopt(SOL_ERROR)?
*/
errno = 0;
connect(c->socket, (struct sockaddr *)&c->addr, sizeof(struct sockaddr_in));
switch (errno) {
case EXIT_SUCCESS:
case EISCONN:
Connected(c);
break;
default:
ReplyCtcpf(c->ident->nick, "ERRMSG Unable to establish connection (%s)",
StrError(errno));
Logf(LOGCLIENT, "Connection failed for %s on socket %d (%s)",
c->ident->nick, c->socket, StrError(errno));
RemoveClient(c);
break;
}
}
else if (OUT_SEND == c->linksort) {
/* fprintf(stderr, "sending file\n"); */
if ((0 >= WriteFileSendSocket(c)) &&
(c->fileflags & CLF_FILECOMPLETE)) {
/* We couldn't read and the file is considered complete */
fprintf(stderr, "sending file done, %d bytes written!\n",
c->filesent);
RemoveClient(c);
}
}
}
}
/* --- Shell commands --- */
for (px = First(execHead); px; px = pxx) {
pxx = Next(px);
if (FD_ISSET(px->socket, readset))
GotExec(px); /* May DeleteEntry(px) */
}
lastevent = time(NULL);
}
#ifndef HAVE_GETDTABLESIZE
/* This is typically done for HPUX systems */
#include <sys/resource.h>
#ifndef FD_SETSIZE
#define FD_SETSIZE 64
#endif
int getdtablesize(void)
{
struct rlimit rlp;
snapshot;
if (0 == getrlimit(RLIMIT_NOFILE, &rlp)) {
return rlp.rlim_cur;
}
return FD_SETSIZE;
}
#endif
/* --- EventLoop -------------------------------------------------- */
void EventLoop(void)
{
static struct timeval stamp;
struct timeval curtime, dt;
long diff;
int fdsize;
fd_set rtmpset, wtmpset;
snapshot;
gettimeofday(&stamp, NULL);
while (!cleanup) {
client = NULL;
chat = FALSE;
/* Calculate the timeout value */
gettimeofday(&curtime, NULL);
if (curtime.tv_usec > stamp.tv_usec)
curtime.tv_usec += MILLION;
diff = RTIMER - (MILLION * (curtime.tv_sec - stamp.tv_sec)) -
(curtime.tv_usec - stamp.tv_usec);
if (diff > 0) {
dt.tv_sec = diff / MILLION;
dt.tv_usec = diff % MILLION;
fdsize = getdtablesize();
if (fdsize > FD_SETSIZE)
fdsize = FD_SETSIZE;
rtmpset = rdset;
wtmpset = wrset;
errno = 0;
/*
* We are not expecting any out-of-band messages,
* so the exceptfds argument is set to NULL
*/
switch (select(fdsize, &rtmpset, &wtmpset, NULL, &dt)) {
case -1: /* Ignore errors and interrupts */
if (EINTR == errno)
continue;
Debug("select(2) failed (%s)", StrError(errno));
cleanup = TRUE;
restart = FALSE;
break;
case 0: /* select(2) timeout */
gettimeofday(&stamp, NULL);
now = stamp.tv_sec;
TimeEvents();
break;
default: /* Data on socket */
now = time(NULL);
HandleSockets(&rtmpset, &wtmpset);
break;
}
}
else { /* Timeout overdue, activate immediately */
gettimeofday(&stamp, NULL);
now = stamp.tv_sec;
TimeEvents();
}
}
}
/* --- NetInit ---------------------------------------------------- */
void NetInit(void)
{
char mydomain[MAXHOSTNAMELEN];
char *problemsolver;
struct hostent *hp;
snapshot;
FD_ZERO(&rdset);
FD_ZERO(&wrset);
/*
* Getting the actual name@host has proved troublesome on many
* machines, this ugly solution was added quickly to get Darxide
* up and running quickly, and therefore this "feature" remains
* undocumented until we have sorted out how to deal with it.
*/
problemsolver = getenv("DANCER_MYHOST");
if (NULL == problemsolver) {
/* If the environment variable isn't set, try the config value if set */
if (dancer_myhost[0])
problemsolver = dancer_myhost;
}
if (problemsolver) {
StrCopyMax(myhost, sizeof(myhost), problemsolver);
myipaddrnum = (ulong)ntohl(inet_addr(myhost));
if (0 == myipaddrnum)
Logf(LOGDEBUG, "Failed to inet_addr() the host '%s'", myhost);
}
else {
/*
* If no host was set in the environment (can also happen if
* started from cron) we'll try to get it ourselves. Changes
* are that we only get 'host' and not 'host.domain'.
*/
#if defined(AMIGA) && !defined(__GNUC__)
struct utsname utstmp;
uname(&utstmp);
StrCopyMax(myhost, sizeof(myhost), utstmp.nodename);
#else
gethostname(myhost, sizeof(myhost));
#endif
}
if ((0 == myipaddrnum) && (hp = GetHost(myhost))) {
/*
* The IP# is needed for outgoing dcc chats
*/
myipaddrnum = (ulong)ntohl(((struct in_addr *)hp->h_addr)->s_addr);
/*
* If our previous attempt to get the domain name along with
* the host name failed, let's try to find the domain now.
*/
if (NULL == StrIndex(myhost, '.')) {
/* First we try an inverse DNS lookup */
hp = GetHost(MakeIP(myipaddrnum));
if (hp) {
char *name;
int i;
for (i = 0, name = hp->h_name; name; name = hp->h_aliases[i++]) {
if (StrIndex(name, '.')) {
StrCopyMax(myhost, sizeof(myhost), name);
break;
}
}
}
#ifdef HAVE_GETDOMAINNAME
if (NULL == StrIndex(myhost, '.')) {
/*
* One last desperate attempt. The name received from
* getdomainname() isn't necessarily the full domain name.
*/
getdomainname(mydomain, sizeof(mydomain));
if (StrIndex(mydomain, '.')) {
StrFormatAppendMax(myhost, sizeof(myhost), ".%s", mydomain);
}
else {
/* The machine does not know and we have to ask the nameserver */
}
#endif
}
}
}
#if defined(HAVE_YP_GET_DEFAULT_DOMAIN) && defined(HAVE_YP_MASTER)
if ((char)0 == nameserver[0]) {
char *my_defaultdomain;
char *my_nameserver;
if (!yp_get_default_domain(&my_defaultdomain)) {
if (!yp_master(my_defaultdomain, "hosts.byname", &my_nameserver))
StrCopyMax(nameserver, MIDBUFFER, my_nameserver);
}
}
#endif
#ifdef BREESE
memset((char *)&fromaddr, 0, sizeof(fromaddr));
fromaddr.sin_family = AF_INET;
linkSocket = OpenLink();
#endif
}
/* --- NetCleanup ------------------------------------------------- */
void NetCleanup(void)
{
snapshot;
CloseConnection(linkSocket);
CloseConnection(serverSocket);
}
syntax highlighted by Code2HTML, v. 0.9.1