🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: es.comp.os.linux.programacion
Article #7625

Re: Código base en C de un servidor

#7625
From: J.A. Gutierrez
Date: Mon, 03 Feb 2003 12:29
538 lines
11225 bytes
Antonio Maestre Garc�a <anmaegar@quitararrakis.es> wrote:
: atenci�n. Lo que haga el servidor es ya cosa m�a... Seguro q debe haber por
: ah� un c�digo base. En principio quiero evitar programarlo yo o tener que

---------------------------------------------------------------------------
/*
 * <spd@daphne.cps.unizar.es>
 * Mon Apr 30 21:12:19 DST 2001
 *
 * :set tabstop=4
 *
 * Tested on:
 *
 *	FreeBSD 4.2    ix86		gcc 2.95.2
 *	SunOS 5.7      Sparc	gcc 2.95.2
 *	SunOS 5.8      Sparc	WorkShop Compilers 5.0
 *	IRIX 6.2       mips		MIPSpro Compilers: Version 7.2.1.2m
 *	Tru64 5.0      alpha	Compaq C V6.1-011
 *	Linux RH 7.0   alpha	gcc 2.96
 *	Linux RH 6.2   ix86		gcc 2.95.2
 *	HP-UX B.11.00  PA-RISC	HP C/ANSI C Compiler B.11.01.06
 */

static char __ident[] = "@(#)SPDsoft, Wed May  2 18:55:37 DST 2001";
#define VERS_STR        ((char*)&__ident[4])




#include <stdio.h>
#include <stdarg.h>  /* va_ */
#include <stdlib.h>  /* atoi */
#include <unistd.h>  /* getpid */
#include <fcntl.h>   /* getpid */
#include <string.h>

#include <sys/time.h>  
#include <sys/types.h>  
#include <sys/socket.h> 
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>  

#include <sys/ioctl.h> 

#include <signal.h>
#include <sys/wait.h>

#include <errno.h>  
#include <assert.h>  

#ifdef __sgi
#	define HAVE_DAEMONIZE
#endif

#ifndef HAVE_DAEMONIZE
/* _daemonize(3C) flags */
#define _DF_NOFORK      0x1     /* don't fork */
#define _DF_NOCHDIR     0x2     /* don't chdir to / */
#define _DF_NOCLOSE     0x4     /* close no files */

int my_daemonize(int flags, int fd1, int fd2, int fd3);
#define _daemonize my_daemonize
#endif

#define HAVE_SETSID 1 /* irix, linux, solaris */
#define HAVE_STRERROR 1

#ifndef  HAVE_STRERROR
#	define strerror(e) sys_errlist[(e)]
#endif

#ifndef _SYSV_SIGNALS
#	define _BSD_SIGNALS
#endif
#ifdef _BSD_SIGNALS
#	define sigset	signal
#endif

#define IPL	32
#define MAXS	100
#ifndef DEFAULT_TPORT
#define DEFAULT_TPORT 5004
#endif


/*
 * Globals
 */

int	done;

typedef	struct	{
	char	my_ip[IPL];
	int		port_d, port_s;
} server_data_struct;

server_data_struct	server_data[MAXS];

typedef	struct	{
	unsigned int		port;
	int		debug;
	char	*logfile;
	FILE	*f;
} prefs_struct;

prefs_struct	gprefs;


/*
 * Prototypes
 */

void clean( int i );
void usage(char *name);
void debug_msg(const char *fmt, ...);
int decode_reg(unsigned char *buf, long nbytes, uint32_t *sum);
int decode_unreg(unsigned char *buf, long nbytes, uint32_t *sum);
int decode_list(unsigned char *buf, long nbytes, uint32_t *sum);
int send_list(int s);

/*
 */

#define request_is(s1,s2) (	(s1[0]==s2[0])&&\
							(s1[1]==s2[1])&&\
							(s1[2]==s2[2])&&\
							(s1[3]==s2[3])	)

void usage(char *name)
{
	fprintf(stderr, "usage: %s [-p port] [-l logfile] [-d] [-v]\n",name);
	fprintf(stderr, "-d: debug\n");
	fprintf(stderr, "-v: version\n");
	exit(-1);
}

#define perror(e) debug_msg("%s (%s)\n", e, strerror(errno))
void debug_msg(const char *fmt, ...)
{
	va_list                 vl;

	if ( NULL != gprefs.f)
	{
		va_start(vl,fmt);
			vfprintf(gprefs.f,fmt,vl);
		va_end(vl);
		fflush(gprefs.f);
	}
}


int main(int argc, char *argv[])
{
#define BS 1000
	double					n=0;
	unsigned long			n_p=0;
	long					nbytes;
	int						s;
	int						sockfd=0;
	int						clientlen;
	struct sockaddr_in		server,
							client;
	int						fd;
	unsigned char			buf[BS];

	uint32_t				sum;
	unsigned char			*req;
	int						err;

	struct timeval			tv;
	fd_set					mask,
							rmask;
	int						nfound;
	int						maxfd;
	int						reuse=1;

	int						option;

	gprefs.port=DEFAULT_TPORT;
	gprefs.debug=0;
	gprefs.logfile=NULL;
	gprefs.f=stderr;


	while ( (option=getopt(argc,argv,"hdp:l:v")) != EOF )
	{
		switch(option)
		{
			case 'p':
				gprefs.port = (unsigned int) atoi(optarg);
				break;
			case 'l':
				gprefs.logfile = optarg;
				break;
			case 'd':
				gprefs.debug = 1;
				break;
			case 'v':
				fprintf(stdout, "%s\n",VERS_STR);
				exit(0);
				break;
			case 'h':
			default:
				usage(argv[0]);
				break;
		}
	}
				

	tv.tv_sec = 2;
	tv.tv_usec = 500000;

	memset(&server,0,sizeof(server));

	if ( !gprefs.debug )
	{
		if ( -1 == _daemonize(_DF_NOCHDIR,
				gprefs.f != NULL ? fileno(gprefs.f) : -1, -1,-1))
			perror("Can't daemonize");
	}


	server.sin_family =			AF_INET;
	server.sin_port =			htons(gprefs.port);
	server.sin_addr.s_addr =	htonl(INADDR_ANY);

	if (
		( SIG_ERR == sigset(SIGTERM, clean)) ||
		( SIG_ERR == sigset(SIGINT, clean)) )
		perror("signal");


	if ( (s=socket(AF_INET,SOCK_STREAM,0)) == -1 )
	{
		perror("Can't get socket");
		exit(1);
	}
/*	debug_msg("open socket %d\n", s);*/

	if (setsockopt(s, SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(int)) == -1)
	{
		perror("setsockopt");
	}

	if( bind( s, (struct sockaddr *)&server, sizeof(server)) != 0 )
	{	
		perror("bind failed");
		exit(1);
	}

/*	debug_msg("bind to %d\n", ntohs(server.sin_port));*/

	if ( listen( s, 5 ) != 0 )
	{
		perror("Can't listen");
		exit(1);
	}
	debug_msg("PID %d listening on %d\n", getpid(), ntohs(server.sin_port));
		
	if ( NULL != gprefs.logfile )
	{
		if ( NULL == ( gprefs.f = fopen(gprefs.logfile, "wb")))
		{
			perror(optarg);
			gprefs.logfile = NULL;
		}
	}
	done=0;
	FD_ZERO(&mask);
	FD_SET(s, &mask);
	maxfd=s;

	for(;!done;)
	{
		rmask=mask;

		nfound=select(maxfd+1, &rmask, NULL, NULL, &tv);

		if (nfound<0)
		{
			if ( EINTR == errno )
			{
				debug_msg("Interrupted system call\n");
				done=1;
				break;
			}
			/*
			 * An error occurred during the select, or
			 * the select timed out.
			 */
			if ( 0 != errno )
			{
				perror("select");
				done=1;
			}
		}
		if (nfound==0)
		{
			continue;
		}
		if (FD_ISSET(s, &rmask))
		{
			done=0;

			debug_msg("%d accepting\n", getpid());
			clientlen=sizeof(client);
			if (
				(sockfd = accept( s, (struct sockaddr *)&client,&clientlen))
				< 0 )
			{
				if ( errno != EINTR )
				{
					perror("accept");
					done=1;
				}
				else
				{
					debug_msg("accept interrupted\n");
					done=1;
				}
			}
			else
			{
				debug_msg("- %d: accepted from %s\n",
					sockfd, inet_ntoa(client.sin_addr));
				fflush(stderr);
				FD_SET(sockfd, &mask);
				if (sockfd > maxfd)
					maxfd = sockfd;
				FD_CLR(s, &rmask);
			}
		}
			
		for ( fd=0; fd<=maxfd; fd++)
		{
			if (FD_ISSET(fd, &rmask))
			{
				nbytes = recv(fd,buf,sizeof(buf)-1,0);
				if ( nbytes < 0 )
				{
					perror("read");
				}
				if ( nbytes <= 0 )
				{
					debug_msg("- %d: EOF\n", fd);

					FD_CLR(fd,&mask);

					if ( -1 == shutdown(fd,2))
						perror("shutdown");
					else
						debug_msg("- %d: shutdown\n",fd);

					if ( -1 == close(fd))
						perror("close");
					else
						debug_msg("- %d: closed\n", fd);

					done = 0;
					continue;
				}
				
				req = (unsigned char *) buf;
				debug_msg("- %d: received request (%.4s)\n", fd, buf);

				/* [...] */

				if (request_is(req,"QUIT"))
				{
					/* Quit */
						write(fd,"OK    ",6);

						FD_CLR(fd,&mask);

						if ( -1 == shutdown(fd,2))
							perror("shutdown");
						else
							debug_msg("- %d: shutdown\n",fd);

						if ( -1 == close(fd))
							perror("close");
						else
							debug_msg("- %d: shutdown\n",fd);

				}
				else
				{
					debug_msg("- %d: Unknown request (%.4s)\n", fd, buf);
					write(fd,"ERUNKN",6);
					break;
				}

				fflush(stdout);
				n +=	nbytes;
				n_p +=	1;
			}
		}
	}

	debug_msg("Rec: %.0f bytes, %lu packets\n",n,n_p);

	for ( fd=maxfd; fd>0; fd--)
	{
		if ( -1 == shutdown(fd,2))
			perror("shutdown");
		else
			debug_msg("fd %d shutdown\n",fd);

		if ( -1 == close(fd))
			perror("close");
		else
			debug_msg("fd %d closed\n",fd);
	}


	exit(errno);
	return(errno); /* Keep compiler happy */
}

/************************************************************************/

void clean( int sig )
{
	if ( sig != SIGSEGV)
	{
		if ( SIG_ERR == sigset(sig, clean))
			perror("clean:signal");

		debug_msg("%d a escaparrar (%d)\n", getpid(), sig);
		fflush(stderr);
		done=1;
	}
}


/************************************************************************/

#ifndef HAVE_DAEMONIZE
int my_daemonize(int flags, int fd1, int fd2, int fd3)
{
	int status=0;
	int fd;

	debug_msg("daemonizing\n");

	if (!( flags & _DF_NOFORK ))
	{
		/* Fork and exit in the parent to disassociate from the
		 * current process group and become the leader of a new
		 * process group.
		 */

		if ( -1 == (status = fork()))
		{
			perror("cant fork");
			exit(1);
		}
		else if ( status > 0 )
		{
			_exit(0);
		}

#if HAVE_SETSID
		setsid();
#endif


		if ( -1 == (status = fork()))
		{
			perror("cant fork again");
			exit(1);
		}
		else if ( status > 0 )
		{
			_exit(0);
		}
	}


#ifdef TIOCNOTTY
	if ( 0 < (fd = open("/dev/tty", O_RDWR)))
	{
		if (ioctl(fd, TIOCNOTTY, NULL) < 0)
		{
			perror("can't disassociate from the terminal");
			status=-1;
		}
		close(fd);
	}
#endif /* TIOCNOTTY */

	if (!(flags & _DF_NOCHDIR))
	{
		if (chdir("/.") < 0)
		{
			perror("can't chdir to /.");
			status=-1;
		}
	}

	if (!(flags & _DF_NOCLOSE))
	{
		long l;
		int	i;

		l=sysconf(_SC_OPEN_MAX);

		while(l-->0)
		{
			if ((l!=fd1)&&(l!=fd2)&&(l!=fd3))
				close(l);
		}

		if ( -1 == ( i = open( "/dev/null", O_RDWR)))
		{
			perror("/dev/null");
			status=-1;
		}
		else
		{
			if ((1!=fd1)&&(1!=fd2)&&(1!=fd3))
				dup(i);
			if ((2!=fd1)&&(2!=fd2)&&(2!=fd3))
				dup(i);
		}
	}
	return(status);
}
#endif
---------------------------------------------------------------------------


-- 
PGP and other useless info at      \
http://www.cps.unizar.es/~spd/      \
finger://daphne.cps.unizar.es/spd    \       Timeo Danaos et dona ferentes
ftp://ivo.cps.unizar.es/pub/          \                         (Virgilio)   
Technical Details
Message-ID: <b1lnbd$8o0$1@news.unizar.es>
Path: arc1-ca.pugleaf.net!archiver1.google.com!news1.google.com!newsfeed.stanford.edu!bloom-beacon.mit.edu!news.rediris.es!bashful.rediris.es!news.unizar.es!not-for-mail
References: <3e3bbbab_1@news.arrakis.es>

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII
X-Google-Thread: f86c8,79de37df9f28b12c
X-Google-Attributes: gidf86c8,public
X-Google-ArrivalTime: 2003-02-03 03:44:50 PST
Path: arc1-ca.pugleaf.net!archiver1.google.com!news1.google.com!newsfeed.stanford.edu!bloom-beacon.mit.edu!news.rediris.es!bashful.rediris.es!news.unizar.es!not-for-mail
From: "J.A. Gutierrez" <spd@daphne.cps.unizar.es>
Newsgroups: es.comp.os.linux.programacion
Subject: Re: Código base en C de un servidor
Date: 3 Feb 2003 12:29:33 GMT
Organization: Rank
Lines: 538
Message-ID: <b1lnbd$8o0$1@news.unizar.es>
References: <3e3bbbab_1@news.arrakis.es>
NNTP-Posting-Host: daphne.cps.unizar.es
Mime-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
X-Trace: news.unizar.es 1044275373 8960 155.210.152.20 (3 Feb 2003 12:29:33 GMT)
X-Complaints-To: usenet@news.unizar.es
NNTP-Posting-Date: 3 Feb 2003 12:29:33 GMT
User-Agent: tin/1.4.5-20010409 ("One More Nightmare") (UNIX) (IRIX/6.2 (IP22))