/*************************************************************************/
/*                  VChat interactive IP-level chat system               */
/*-----------------------------------------------------------------------*/
/*  (c) '93/'94 by Andreas S. Wetzel (mickey@deadline.bln.sub.org)       */
/*                 All rights reserverd.                                 */ 
/*-----------------------------------------------------------------------*/
/* See the file COPYRIGHT in the top level directory of VChat for        */
/* copyright notices and further disclaimers.                            */ 
/*************************************************************************/

/****** includes ******/

#include "../config.h"
#include "../global.h"
#include <stdio.h>
#include <errno.h>
#include <syslog.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "proto.h"
#include "../version.h"

#define	CPRY	"* (c) '93/'94 by mickey@deadline -- All rights reserved."

/********************************************/
/* Hier kommen nun die Routinen fuer die    */
/* behandlung der einzelnen Server commands */
/********************************************/

void signon(struct client_data *ptr)
{
	struct client_data *cl;
	extern char our_host[];
	extern struct in_addr our_ipaddr;
	extern int clients;
	int i;

	snd_svmsg(ptr->fd, "* Connected to VChat server at %c%s%c [%c%s%c]",
		RED, our_host, XXX, YEL, inet_ntoa(our_ipaddr), XXX);
	snd_svmsg(ptr->fd, "* VChat TCP/IP chat server %s\n", VERSION);

	for(i=0; i<clients; i++)
	{
		cl = cl_addr(i);

		if(strcmp(ptr->user, ptr->nick) == 0)
			snd_svmsg(cl->fd, "* Signon user %c%s%c from %c%s%c [%c%s%c]",
			BLU, ptr->user, XXX, RED, ptr->host, XXX, YEL,
			inet_ntoa(ptr->ip_addr), XXX);
		else
			snd_svmsg(cl->fd, "* Signon user %c%s%c (%s) from %c%s%c [%c%s%c]",
			BLU, ptr->user, XXX, ptr->nick, RED, ptr->host, XXX, YEL,
			inet_ntoa(ptr->ip_addr), XXX);
	}
	log(LOG_INFO, "Signon user %s (%s) from %s [%s]",
		ptr->user, ptr->nick, ptr->host,
		inet_ntoa(ptr->ip_addr));
}

void signoff(struct client_data *ptr)
{
	struct client_data *cl;
	extern int clients;
	int i;

	log(LOG_INFO, "Signoff user %s (%s) from %s [%s].",ptr->user,
		ptr->nick, ptr->host, inet_ntoa(ptr->ip_addr));

	for(i=0; i<clients; i++)
	{
		cl = cl_addr(i);

		if(strcmp(ptr->user, ptr->nick) == 0)
		{
			snd_svmsg(cl->fd, "* Signoff user %c%s%c from %c%s%c [%c%s%c]",
				BLU, ptr->user, XXX, RED, ptr->host, XXX, YEL,
				inet_ntoa(ptr->ip_addr), XXX);
		}
		else
		{
			snd_svmsg(cl->fd, "* Signoff user %c%s%c (%s) from %c%s%c [%c%s%c]",
				BLU, ptr->user, XXX, ptr->nick, RED, ptr->host,
				XXX, YEL, inet_ntoa(ptr->ip_addr), XXX);
		}
	}

	delete_client(ptr->fd);
}

void err_signoff(struct client_data *ptr)
{
	struct client_data *cl;
	extern int clients;

	int i;

	log(LOG_INFO, "Signoff user %s (%s) from %s [%s].", ptr->user,
		ptr->nick, ptr->host, inet_ntoa(ptr->ip_addr));

	for(i=0; i<clients; i++)
	{
		cl = cl_addr(i);

		if(cl != ptr)
		{
			if(strcmp(ptr->user, ptr->nick) == 0)
			{
				snd_svmsg(cl->fd, "* Signoff user %c%s%c from %c%s%c [%c%s%c]",
					BLU, ptr->user, XXX, RED, ptr->host,
					XXX, YEL, inet_ntoa(ptr->ip_addr), XXX);
			}
			else
			{
				snd_svmsg(cl->fd, "* Signoff user %c%s%c (%s) from %c%s%c [%c%s%c]",
					BLU, ptr->user, XXX, ptr->nick,
					RED, ptr->host, XXX, YEL, 
					inet_ntoa(ptr->ip_addr), XXX);
			}
		}
	}

	delete_client(ptr->fd);
}

void chnick(struct client_data *ptr, char *dat)
{
	struct nickname *nk = (struct nickname *) dat;
	struct client_data *pt;
	extern int clients;
	int i;

	if(nick_ok(ptr, nk->nick))
	{
		for(i=0; i<clients; i++)
		{
			pt = cl_addr(i);

			if(pt->channel == ptr->channel)
			{
				snd_svmsg(pt->fd, "* %c%s%c is now known as %c%s%c.",
					RED, ptr->nick, XXX, YEL, nk->nick, XXX);
			}
		}
		log(LOG_INFO, "%s is now know as %s.", ptr->nick, nk->nick);
		strcpy(ptr->nick, nk->nick);
	}
	else
	{
		snd_svmsg(ptr->fd, "* Nickname '%c%s%c' is already in use.", 
			RED, nk->nick, XXX);
		log(LOG_INFO, "[%s]: Nickname '%s' is already in use.", ptr->nick, nk->nick);
	}
}

void chchan(struct client_data *ptr, char *dat)
{
	struct channel *ch = (struct channel *) dat;
	struct client_data *pt;
	extern int clients;
	int i;

	for(i=0; i<clients; i++)
	{
		pt = cl_addr(i);

		if(pt->fd == ptr->fd)
		{
			snd_svmsg(pt->fd, "* You are now on channel %c%d%c.",
			RED, ch->chan, XXX);
		}
		else if(pt->channel == ptr->channel)
		{
			snd_svmsg(pt->fd, "* %c%s%c left this channel.",
			RED, ptr->nick, XXX);
		}
		else if(pt->channel == ch->chan)
		{
			snd_svmsg(pt->fd, "* %c%s%c joined this channel.",
			RED, ptr->nick, XXX);
		}
	}
	
	bcopy(&ch->chan, &ptr->channel, sizeof(struct channel));
	log(LOG_INFO, "%s (%s) joined channel %d", ptr->user, ptr->nick, ptr->channel);
}

void prvmsg(struct client_data *ptr, char *dat)
{
	struct prv_message *prv = (struct prv_message *) dat;
	struct client_data *cl;
	extern int clients;
	int i;
	int n = 0;
	
	for(i=0; i<clients; i++)
	{
		cl = cl_addr(i);

		if(strcmp(cl->nick, prv->receiver) == 0)
		{
			snd_svmsg(cl->fd, "(*%c%s%c*) %s",
			RED, ptr->nick, XXX, prv->msg);
			log(LOG_INFO, "(%s) -> (*%s*) %s", ptr->nick, cl->nick, prv->msg);
			n++;
		}
	}
	if(!n)
		snd_svmsg(cl->fd, "* Nickname '%c%s%c' not found",
		RED, prv->receiver, XXX);
}

void pubmsg(struct client_data *ptr, char *dat)
{
	extern int clients;
	struct client_data *pt;
	int i;

	if(chatters(ptr->channel) > 1)
	{
		for(i=0; i<clients; i++)
		{
			pt = cl_addr(i);

			if(pt->channel == ptr->channel)
			{
				if(pt->fd != ptr->fd)
					snd_svmsg(pt->fd, "(%s) %s", ptr->nick, dat);
				else
					snd_svmsg(pt->fd, "%s",dat);
			}
		}
		log(LOG_INFO, "(%s) %s", ptr->nick, dat);
	}
	else
	{
		snd_svmsg(ptr->fd, "* You are alone in this conference -- nobody can hear you.");
	}
}

void invite(struct client_data *ptr, char *dat)
{
	struct client_data *cl;
	struct nickname *nam = (struct nickname *) dat;
	extern int clients;
	int i;
	int n = 0;

	for(i=0; i<clients; i++)
	{
		cl = cl_addr(i);

		if(strcmp(cl->nick, nam->nick) == 0)
		{
			snd_svmsg(cl->fd, "* %c%s%c (%s) invites you to join channel %c%d%c",
			BLU, ptr->user, XXX, ptr->nick, RED, ptr->channel, XXX);
			log(LOG_INFO, "%s invites %s to join channel %d", ptr->nick, cl->nick, ptr->channel);
			n++;
		}
	}

	if(n)
		snd_svmsg(ptr->fd, "* User has been invited");
	else
		snd_svmsg(ptr->fd, "* No such user");
}

void snd_id(struct client_data *ptr)
{
	snd_svmsg(ptr->fd, "* VChat TCP/IP server %c%s%c.",
	YEL, VERSION, XXX);
	snd_svmsg(ptr->fd, "%s", CPRY);
	log(LOG_INFO, "%s requested server info.", ptr->nick);
}

void ulist(struct client_data *ptr, char *dat)
{
	struct client_data *cl;
	struct list *lt = (struct list *) dat;
	extern int clients;

	int i;
	int n = 0;

	if((lt->cmd == CHAN && lt->chan < 0) && privileged(ptr) == 0)
	{
		snd_svmsg(ptr->fd, "* No informations on negative channels available");
		log(LOG_INFO, "%s requested channel list for channel %d -- denied.",
			ptr->nick, lt->chan);
	}
	else
	{
		for(i=0; i<clients; i++)
		{
			cl = cl_addr(i);

			if((lt->cmd == ALL_CHAN)
			||(ptr->channel == cl->channel && lt->cmd == MY_CHAN)
			||(cl->channel == lt->chan && lt->cmd == CHAN))
			{
				if(!n)
				{
					snd_svmsg(ptr->fd, "");
					if(clients>1)
						snd_svmsg(ptr->fd, "*  %c%d%c Users online.",
						RED, clients, XXX);
					else
						snd_svmsg(ptr->fd, "*  %c%d%c User online.",
						RED, clients, XXX);
					snd_svmsg(ptr->fd, "*");
					snd_svmsg(ptr->fd, "* %c%c Username         Nickname            Channel From       IP-Adress       %c", WHT, BG | BLU, XXX);
				}

				if(cl->channel < 0 && !privileged(ptr))
				{
					snd_svmsg(ptr->fd, "*  %-16s %-16s ?????????? %-10s %s",
						cl->user, cl->nick, cl->host,
						inet_ntoa(cl->ip_addr));
				}
				else
				{
					snd_svmsg(ptr->fd, "*  %-16s %-16s %10d %-10s %s",
						cl->user, cl->nick, cl->channel, cl->host,
					inet_ntoa(cl->ip_addr));
				}
				n++;
			}
		}
		if(n)
			snd_svmsg(ptr->fd,"");
		else
			snd_svmsg(ptr->fd, "* No users on channel %c%d%c",
			RED, lt->chan, XXX);
	}
}

void page(struct client_data *ptr, char *dat)
{
	FILE *pipe;
	char comline[255];
	extern int errno;
	extern char our_host[];

	sprintf(comline, "mail -s \"%s@%s (%s) would like to chat.\" %s 1>&2 2>/dev/null",
		ptr->user, ptr->host, ptr->nick, dat);

	if(pipe = popen(comline, "w"))
	{
		fprintf(pipe, "=> User %s@%s [%s] would like to chat to you.\n",
			ptr->user, ptr->host, inet_ntoa(ptr->ip_addr));
		fprintf(pipe, "=> Use 'vchat -s %s' at shell command level to get into the dialgoue.\n",
			our_host);

		if(pclose(pipe) && errno != EINTR)
		{
			snd_svmsg(ptr->fd, "* Mail failed.");
			log(LOG_NOTICE, "Page request of %s (%s) for %s failed.",
				ptr->user, ptr->nick, dat);
		}
		else
		{
			snd_svmsg(ptr->fd, "* Page sent.");
			log(LOG_INFO, "%s (%s) sent page request via mail to %s",
				ptr->user, ptr->nick, dat);
		}
	}
	else
	{
		snd_svmsg(ptr->fd, "* Sorry, mail is out of order.");
		log(LOG_NOTICE, "Failed opening pipe to mail process.");
	}
}

void ring(struct client_data *ptr, char *dat)
{
	extern char our_host[];
	extern struct in_addr our_ipaddr;
	struct sockaddr_in sock_in;
	struct hostent *ht;
	struct servent *sv;
	struct ping_cmd pcmd;
	struct vresp vr;
	char *user;
	char *host;
	int s;
#ifdef SLIP_FIX
	struct timeval to;
#endif
	if((char *)strchr(dat, '@') == NULL)    /* Local Adress */
	{
		user = dat;
		host = ptr->host;
		bcopy(&ptr->ip_addr, &sock_in.sin_addr, sizeof(struct in_addr));
	}
	else				/* Remote Adress */
	{
		user = (char *)strtok(dat,"@");
		host = (char *)strtok(NULL,"@");

		if((ht = gethostbyname(host)) == NULL)
		{
			snd_svmsg(ptr->fd, "* No IP adress of host %c%s%c",
			RED, host, XXX);
			log(LOG_INFO, "Could not find IP adress of host %s", host);
			return;
		}

		bcopy(ht->h_addr, &sock_in.sin_addr, sizeof(ht->h_addr));
	}

	if(ucheck(user, &sock_in.sin_addr))
	{
		snd_svmsg(ptr->fd, "* No need to ring %c%s%c -- (s)he's already chatting",
		RED, user, XXX);
		return;
	}
#ifdef VPING_INETD
	if(!(sv = getservbyname("vping", "tcp")))
	{
		snd_svmsg(ptr->fd, "* Unable to connect to vping server.");
		snd_svmsg(ptr->fd, "* Reason: %cvping/tcp unknown service%c.", RED, XXX);
		return;
	}

	sock_in.sin_port = sv->s_port;	
#else
	sock_in.sin_port = htons(PING_PORT);
#endif
	sock_in.sin_family = AF_INET;

	if((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		snd_svmsg(ptr->fd, "* Server failed to open socket");
		snd_svmsg(ptr->fd, "* Reason: %c%s%c.", RED, strerror(errno), XXX);
		log(LOG_ERR, "Failed to open socket for ping request");
		log(LOG_ERR, "Reason: %m");
		return;
	}
#ifdef SLIP_FIX
	to.tv_sec = RCVTMOUT_SEC;
	to.tv_usec = RCVTMOUT_USEC;

	if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *) &to, sizeof(to)) == -1)
	{
		snd_svmsg(ptr->fd, "* Server failed to set socket options.");
		snd_svmsg(ptr->fd, "* Reason: %c%s%c.", RED, strerror(errno), XXX);
		log(LOG_ERR, "Failed to set socket options");
		log(LOG_ERR, "Reason: %m");
		return;
	}
#endif
	if(connect(s, (struct sockaddr *)&sock_in, sizeof(struct sockaddr_in)) != 0)
	{
		snd_svmsg(ptr->fd, "* Failed to connect VPing server at %c%s%c [%c%s%c]",
			RED, host, XXX, YEL, inet_ntoa(sock_in.sin_addr), XXX);
		snd_svmsg(ptr->fd, "* Reason: %c%s%c.", RED, strerror(errno), XXX);
		log(LOG_NOTICE, "Failed to connect ping server at %s [%s]",
			host, inet_ntoa(sock_in.sin_addr));
		log(LOG_NOTICE, "Reason: %m");
		close(s);
		return;
	}

	pcmd.cmd = P_PING;
	pcmd.len = strlen(user);
	strncpy(pcmd.user, ptr->user, 16);
	strncpy(pcmd.nick, ptr->nick, 16);
	strncpy(pcmd.host, ptr->host, 16);
	strncpy(pcmd.sv_host, our_host, 16);
	bcopy(&ptr->ip_addr, &pcmd.ip_addr, sizeof(ptr->ip_addr));
	bcopy(&our_ipaddr, &pcmd.sv_ipaddr, sizeof(our_ipaddr));

	write(s, &pcmd, sizeof(struct ping_cmd));
	write(s, user, strlen(user));

	if(read(s, &vr, sizeof(struct vresp)) == sizeof(struct vresp))
	{
		switch(vr.stat)
		{
			case OK:		snd_svmsg(ptr->fd, "* Rang %c%s@%s%c", RED, user, host, XXX);
						log(LOG_INFO, "%s (%s) rang %s@%s", ptr->user, ptr->nick, user, host);
						break;
			case TTY_OFAIL:		snd_svmsg(ptr->fd, "* Failed to open terminal on %c%s%c [%c%s%c] for output",
							RED, host, XXX, YEL, inet_ntoa(sock_in.sin_addr), XXX);
						break;
			case UTMP_OFAIL:	snd_svmsg(ptr->fd, "* Failed to open utmp file on %c%s%c [%c%s%c]",
							RED, host, XXX, YEL, inet_ntoa(sock_in.sin_addr), XXX);
						break;
			case NO_ACCESS:		snd_svmsg(ptr->fd, "* %c%s@%s%c is refusing messages",
							RED, user, host, XXX);
						break;
			case NO_LOGIN:		snd_svmsg(ptr->fd, "* %c%s@%s%c not logged in.",
							RED, user, host, XXX);
						break;
			case BAD_CMD:		snd_svmsg(ptr->fd, "* VPing server at %c%s%c [%c%s%c] received garbled command packet",
							RED, host, XXX, YEL, inet_ntoa(sock_in.sin_addr), XXX);
						break;
			case BAD_DATA:		snd_svmsg(ptr->fd, "* VPing server at %c%s%c [%c%s%c] received garbled data packet",
							RED, host, XXX, YEL, inet_ntoa(sock_in.sin_addr), XXX);
						break;
			default:		snd_svmsg(ptr->fd, "* VPing server at %c%s%c [%c%s%c] returned unknown status $%x",
							RED, host, XXX, YEL, inet_ntoa(sock_in.sin_addr), XXX, vr.stat);
						break;
		}
	}
	else
	{
		snd_svmsg(ptr->fd, "* No acknowledge from VPing server at %c%s%c", RED, host, XXX);
	}
	close(s);
}

void who(struct client_data *ptr, char *dat)
{
	extern char our_host[];
	extern struct in_addr our_ipaddr;
	struct sockaddr_in sock_in;
	struct hostent *ht;
	struct servent *sv;
	struct ping_cmd pcmd;
	struct sysinfo sys;
	struct u_info ut[MAXUSERS];
	char *host;
	int s, i;
	int onl_d, onl_h, onl_m;
	int idl_d, idl_h, idl_m;
	char c;
#ifdef SLIP_FIX
	struct timeval to;
#endif
	if(strlen(dat) == 0)
	{
		host = ptr->host;
		bcopy(&ptr->ip_addr, &sock_in.sin_addr, sizeof(ptr->ip_addr));
	}
	else
	{
		host = dat;

		if((ht = gethostbyname(host)) == NULL)
		{
			snd_svmsg(ptr->fd, "* No IP adress of host %c%s%c", RED, host, XXX);
			log(LOG_NOTICE, "Could not find IP adress of host %s", host);
			return;
		}

		bcopy(ht->h_addr, &sock_in.sin_addr, sizeof(ht->h_addr));
	}

#ifdef VPING_INETD
	if(!(sv = getservbyname("vping", "tcp")))
	{
		snd_svmsg(ptr->fd, "* Unable to connect to vping server.");
		snd_svmsg(ptr->fd, "* Reason: %cvping/tcp unknown service%c.", RED, XXX);
		return;
	}

	sock_in.sin_port = sv->s_port;
#else
	sock_in.sin_port = htons(PING_PORT);
#endif
	sock_in.sin_family = AF_INET;

	if((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		snd_svmsg(ptr->fd, "* Server failed to open socket");
		snd_svmsg(ptr->fd, "* Reason: %c%s%c.", RED, strerror(errno), XXX);
		log(LOG_ERR, "Failed to open socket");
		log(LOG_ERR, "Reason: %m");
		return;
	}
#ifdef SLIP_FIX
	to.tv_sec = RCVTMOUT_SEC;
	to.tv_usec = RCVTMOUT_USEC;

	if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *) &to, sizeof(to)) == -1)
	{
		snd_svmsg(ptr->fd, "* Server failed to set scoket options.");
		snd_svmsg(ptr->fd, "* Reason: %c%s%c", RED, strerror(errno), XXX);
		log(LOG_ERR, "Failed to set socket options.");
		log(LOG_ERR, "Reason: %m");
	}
#endif
	if(connect(s, (struct sockaddr *)&sock_in, sizeof(struct sockaddr_in)) != 0)
	{
		snd_svmsg(ptr->fd, "* Failed to connect VPing server at %c%s%c [%c%s%c]",
			RED, host, XXX, YEL, inet_ntoa(sock_in.sin_addr), XXX);
		snd_svmsg(ptr->fd, "* Reason: %c%s%c", RED, strerror(errno), XXX);
		close(s);
		log(LOG_NOTICE, "Failed to connect VPing Server at %s [%s]", host, inet_ntoa(sock_in.sin_addr));
		log(LOG_NOTICE, "Reason: %m");
		return;
	}

	pcmd.cmd = P_WHO;
	pcmd.len = 0;
	strncpy(pcmd.user, ptr->user, 16);
	strncpy(pcmd.nick, ptr->nick, 16);
	strncpy(pcmd.host, ptr->host, 16);
	strncpy(pcmd.sv_host, our_host, 16);
	bcopy(&ptr->ip_addr, &pcmd.ip_addr, sizeof(ptr->ip_addr));
	bcopy(&our_ipaddr, &pcmd.sv_ipaddr, sizeof(our_ipaddr));

	write(s, &pcmd, sizeof(struct ping_cmd));

	if(read(s, &sys, sizeof(sys)) == sizeof(sys))
	{
		snd_svmsg(ptr->fd, "\n* Sysinfo for host %c%s%c [%c%s%c]",
			RED, host, XXX, YEL, inet_ntoa(ptr->ip_addr), XXX);
		snd_svmsg(ptr->fd, "*");

		if(sys.nusers == 1)
		{
			snd_svmsg(ptr->fd, "* %c1%c user online -- load average: %c%2.3f%c %2.3f%c %2.3f",
				RED, sys.loadavg[2], BLU, sys.loadavg[1], YEL, sys.loadavg[0]);
		}
		else
		{
			snd_svmsg(ptr->fd, "* %c%d%c users online -- load average: %c%2.3f%c %2.3f%c %2.3f",
				RED, sys.nusers, XXX, RED, sys.loadavg[2], BLU, sys.loadavg[1],
				YEL, sys.loadavg[0]);
		}

		snd_svmsg(ptr->fd, "*");

		if(sys.nusers)
			snd_svmsg(ptr->fd, "* %c%cUSER       TTY      HOST       LOGIN             ONLINE     IDLE        %c",
				WHT, BG | BLU, XXX);

		for(i=0; i<sys.nusers; i++)
		{
			if(read(s, &ut[i], sizeof(struct u_info)) == sizeof(struct u_info))
			{
				onl_d = ((int)ut[i].u_online / 0x15180);
				onl_h = ((int)(ut[i].u_online % 0x15180) / 0xe10);
				onl_m = ((int)(ut[i].u_online % 0xe10) / 0x3c);

				idl_d = ((int)ut[i].u_idle / 0x15180);
				idl_h = ((int)(ut[i].u_idle % 0x15180) / 0xe10);
				idl_m = ((int)(ut[i].u_idle % 0xe10) / 0x3c);

				if(onl_d && idl_d)
				{
					snd_svmsg(ptr->fd, "* %-10s %-8s %-10s %-16s %2dd+ %02d:%02d %2dd+ %02d:%02d",
						ut[i].u_name,
						ut[i].u_line,
						ut[i].u_host,
						pr_time(ut[i].u_time, 16),
						onl_d, onl_h, onl_m,
						idl_d, idl_h, idl_m);
				}
				else if(onl_d)
				{
					snd_svmsg(ptr->fd, "* %-10s %-8s %-10s %-16s %2dd+ %02d:%02d      %02d:%02d",
						ut[i].u_name,
						ut[i].u_line,
						ut[i].u_host,
						pr_time(ut[i].u_time, 16),
						onl_d, onl_h, onl_m,
						idl_h, idl_m);
				}
				else
				{
					snd_svmsg(ptr->fd, "* %-10s %-8s %-10s %-16s      %02d:%02d      %02d:%02d",
						ut[i].u_name,
						ut[i].u_line,
						ut[i].u_host,
						pr_time(ut[i].u_time, 16),
						onl_h, onl_m,
						idl_h, idl_m);
				}
			}
			else
			{
				break;
			}
		}
	}
	else
	{
		snd_svmsg(ptr->fd, "* Vping server does not respond.");
	}
	close(s);
}
