#include <netinet/in.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
const char id[] = "$Id: filtserver.html,v 1.1 2001/05/22 07:58:08 paudley Exp $";
#define VERSION "1.0"
#define MAXLINE 512
#define PASSWORD "zookes"
#define SA struct sockaddr
//#define debug(x)
#define debug(x) x
#undef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b))
/* include readline */
static ssize_t my_read(int fd, char *ptr)
{
static int read_cnt = 0;
static char *read_ptr;
static char read_buf[MAXLINE];
if (read_cnt <= 0) {
again:
if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) {
if (errno == EINTR)
goto again;
return(-1);
} else if (read_cnt == 0)
return(0);
read_ptr = read_buf;
}
read_cnt--;
*ptr = *read_ptr++;
return(1);
}
ssize_t readline(int fd, void *vptr, size_t maxlen)
{
int n, rc;
char c, *ptr;
ptr = vptr;
for (n = 1; n < maxlen; n++) {
if ( (rc = my_read(fd, &c)) == 1) {
*ptr++ = c;
if (c == '\n')
break; /* newline is stored, like fgets() */
} else if (rc == 0) {
if (n == 1)
return(0); /* EOF, no data read */
else
break; /* EOF, some data was read */
} else
return(-1); /* error, errno set by read() */
}
*ptr = 0; /* null terminate like fgets() */
return(n);
}
/* end readline */
/* include writen */
// Write "n" bytes to a descriptor.
ssize_t writen(int fd, const void *vptr, size_t n)
{
size_t nleft;
ssize_t nwritten;
const char *ptr;
// ignore SIGPIPE
signal( SIGPIPE, SIG_IGN );
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
if (errno == EINTR)
nwritten = 0; /* and call write() again */
else
return(-1); /* error */
}
nleft -= nwritten;
ptr += nwritten;
}
return(n);
}
/* end writen */
int main(int argc, char **argv)
{
int i, maxi, maxfd, listenfd, connfd, sockfd;
int nready, clients[FD_SETSIZE], x, port;
char auth[FD_SETSIZE];
ssize_t n, clilen;
fd_set rset, allset;
char line[MAXLINE], passwd[64], version[128];
char* tmp;
struct sockaddr_in cliaddr, servaddr;
sprintf(version,"v%s (%s)",VERSION,id);
if( argc < 2 ) {
fprintf(stderr,"FiltServer %s\n",version);
fprintf(stderr," syntax: filtserver <port> [ <password> ]\n");
fprintf(stderr," (default passwd is \"%s\"\n", PASSWORD );
exit(1);
}
if( ( port=strtol( argv[1], NULL, 10 ) ) < 1 || port > 65535 ) {
fprintf(stderr,"Invalid port specification.\n");
exit(1);
}
debug( printf("port: %d\n", port ) );
if( argc < 3 )
sprintf( passwd, PASSWORD );
else
sprintf( passwd, argv[2] );
debug( printf("passwd: %s\n", passwd ) );
for( i=0; i< FD_SETSIZE; i++ ) { clients[i] = -1; auth[i] = 0; }
maxi = -1;
listenfd = socket( AF_INET, SOCK_STREAM, 0 );
bzero( &servaddr, sizeof(servaddr) );
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
servaddr.sin_port = htons( port );
if( bind(listenfd, (SA *) &servaddr, sizeof(servaddr)) == -1 ) {
fprintf(stderr,"bind() error: %s\n", strerror(errno));
exit(2);
}
listen(listenfd, 5);
maxfd = MAX( listenfd, STDIN_FILENO ); /* initialize */
FD_ZERO(&allset);
FD_SET( listenfd, &allset );
FD_SET( STDIN_FILENO, &allset );
for ( ; ; ) {
rset = allset;
nready = select(maxfd+1, &rset, NULL, NULL, NULL);
if( FD_ISSET( listenfd, &rset ) ) {
// New Client connection
clilen = sizeof(cliaddr);
connfd = accept(listenfd,(SA*)&cliaddr,&clilen);
debug( printf("new client: %s, port %d\n",
inet_ntop(AF_INET,&cliaddr.sin_addr,4,NULL),
ntohs(cliaddr.sin_port)) );
for( i=0; i<FD_SETSIZE; i++ )
if( clients[i] < 0 ) {
clients[i] = connfd;
break;
}
debug( printf( "connect(%d)...\n", i ) );
// Print the banner...
sprintf( line, "FiltServer v%s\n - Copyright Patrick Audley (1997)\n\nPlease enter password:\n", version );
if( writen( connfd, line, strlen(line) ) < 0 ) {
// Error writing to client..
debug( printf( "Dropping client for write error.\n" ) );
close( connfd );
FD_CLR( connfd, &allset );
clients[i] = -1;
auth[i] = 0;
for( i=0; i<FD_SETSIZE; i++ )
if( clients[i] > -1 ) maxi = i;
}
if( i == FD_SETSIZE ) {
debug( printf( "Too many clients!\n" ) );
close( connfd );
}
FD_SET( connfd, &allset );
if( connfd > maxfd )
maxfd = connfd; /* for select */
if( i > maxi )
maxi = i; /* max index in client[] array */
if( --nready <= 0 )
continue;
}
for( i=0; i<=maxi; i++ ) {
// check all clients for data/disconnects.
if( ( sockfd = clients[i] ) < 0 )
continue;
if( FD_ISSET( sockfd, &rset ) ) {
// This client has something.
if( ( n=readline( sockfd, line, MAXLINE ) ) == 0 ) {
// connection closed by client.
debug( printf( "dropping(%d)...\n", i ) );
close( sockfd );
FD_CLR( sockfd, &allset );
clients[i] = -1;
auth[i] = 0;
for( i=0; i<FD_SETSIZE; i++ )
if( clients[i] > -1 ) maxi = i;
} else {
debug( printf( "client_read(%d): %s", i, line ) );
// process input... look for passwd.
if( auth[i] > 0 ) {
// Already authenticated... ignore..
} else if( strncmp( passwd, line, strlen(passwd) ) == 0 ) {
// Otherwise, compare input to passwd.
debug( printf( "auth(%d)...\n",i ) );
auth[i] = 1;
debug( printf( "write(%d)...\n", i ) );
sprintf( line, "Access Granted: Streaming active.\n------------------------------------------\n" );
if( writen( sockfd, line, strlen(line) ) < 0 ) {
// Error writing to client..
debug( printf( "Dropping client for write error.\n" ) );
close( sockfd );
FD_CLR( sockfd, &allset );
clients[i] = -1;
auth[i] = 0;
for( i=0; i<FD_SETSIZE; i++ )
if( clients[i] > -1 ) maxi = i;
}
} else {
sprintf( line, "Access Denied.\n" );
writen( sockfd, line, strlen(line) );
// drop the client.
debug( printf( "Dropping client for passwd error.\n" ) );
close( sockfd );
FD_CLR( sockfd, &allset );
clients[i] = -1;
auth[i] = 0;
for( i=0; i<FD_SETSIZE; i++ )
if( clients[i] > -1 ) maxi = i;
}
}
if( --nready <= 0 )
break; // no more readable descriptors.
}
}
if( FD_ISSET( STDIN_FILENO, &rset ) ) {
// Something on stdin for us.
if( ( n=readline( STDIN_FILENO, line, MAXLINE ) ) == 0 ) {
// oops... problem...
debug( printf( "nothing to read from stdin...\n" ) );
} else {
debug( printf( "read: %s", line ) );
// write out line to each client..
for( i=0; i<=maxi; i++ ) {
if( ( sockfd = clients[i] ) < 0 || auth[i] < 1 )
continue;
debug( printf( "write(%d)...\n", i ) );
if( writen( sockfd, line, n ) < 0 ) {
// Error writing to client..
debug( printf( "Dropping client for write error.\n" ) );
close( sockfd );
FD_CLR( sockfd, &allset );
clients[i] = -1;
auth[i] = 0;
for( i=0; i<FD_SETSIZE; i++ )
if( clients[i] > -1 ) maxi = i;
}
}
}
}
}
}
// $Log: filtserver.c,v $
// Revision 1.1 1997/10/22 06:26:12 paudley
// - Changed banner to not scroll off screen.
//
// Revision 1.0.0.1 1997/10/22 06:22:07 paudley
// Inital write
//
syntax highlighted by Code2HTML, v. 0.9