8
Log service : server
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <string.h>
- #include <signal.h>
- #include <unistd.h>
- #include <time.h>
- #include "debug.h"
- #if defined( DEBUG )
- int debug = 0;
- #endif
- #define LOGFILE "log.txt"
- #define PORTNUM 10123
- #define MAXCONN 32
- #define LINESIZE 1024
- struct {
- char *log_file;
- int port_num;
- int socket;
- struct {
- int sock;
- FILE *fin;
- char *ip;
- } in_sockets[MAXCONN];
- FILE *flog;
- } app;
- static char *timestamp() {
- time_t now = time( 0 );
- struct tm *tm = localtime( &now );
- static char s[18]; /* dd/mm/yy hh:mm:ss */
- sprintf( s, "%02d/%02d/%02d %02d:%02d:%02d", tm->tm_mday, tm->tm_mon, tm->tm_year - 100,
- tm->tm_hour, tm->tm_min, tm->tm_sec );
- return s;
- }
- void open_log() {
- FILE *fp;
- ONDEBUG9( fputs( "\n[open_socket]\n", stdout ); );
- if ( app.flog == 0 ) {
- if ( (fp = fopen( app.log_file, "a" )) == 0 )
- goto error;
- app.flog = fp;
- if ( fprintf( app.flog, "%s START\n", timestamp() ) == EOF )
- goto error;
- }
- return;
- error:
- perror( 0 );
- exit( 1 );
- }
- void close_log() {
- ONDEBUG9( fputs( "\n[close_log]\n", stdout ); );
- if ( app.flog != 0 ) {
- if ( fprintf( app.flog, "%s STOP\n", timestamp() ) == EOF )
- goto error;
- fclose( app.flog );
- app.flog = 0;
- }
- return;
- error:
- perror( 0 );
- exit( 1 );
- }
- void open_socket() {
- int sd = -1;
- struct sockaddr_in sd_address;
- socklen_t addrlen = sizeof( struct sockaddr_in );
- int sockoptval, sockoptlen;
- ONDEBUG9( fputs( "\n[open_socket]\n", stdout ); );
- if ( (sd = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP )) == -1 )
- goto error;
- sockoptval = 1; /* on */
- sockoptlen = sizeof ( sockoptval );
- if ( setsockopt( sd, SOL_SOCKET, SO_REUSEADDR, &sockoptval, sockoptlen ) < 0 )
- goto error;
- sd_address.sin_family = AF_INET;
- sd_address.sin_addr.s_addr = htonl( INADDR_ANY );
- sd_address.sin_port = htons( app.port_num );
- if ( bind( sd, (struct sockaddr *)&sd_address, addrlen ) != 0 )
- goto error;
- if ( listen( sd, 5 ) != 0)
- goto error;
- app.socket = sd;
- return;
- error:
- perror( 0 );
- if ( sd != -1 )
- close( sd );
- exit( 1 );
- }
- void close_socket( void ) {
- ONDEBUG9( fputs( "\n[close_socket]\n", stdout ); );
- if ( app.socket != -1 ) {
- close( app.socket );
- app.socket = -1;
- }
- }
- void drop_conn( int socket ) {
- int i;
- ONDEBUG9( fputs( "\n[drop_conn]\n", stdout ); );
- ONDEBUG2 ( fprintf( stdout, "-%d-\n", socket ); );
- for ( i = 0; i < MAXCONN; ++i ) {
- if ( app.in_sockets[ i ].sock == socket ) {
- fclose( app.in_sockets[ i ].fin );
- app.in_sockets[ i ].sock = -1;
- app.in_sockets[ i ].fin = 0;
- free( app.in_sockets[ i ].ip );
- return;
- }
- }
- }
- void accept_conn( int socket ) {
- int sd = -1;
- struct sockaddr_in sd_address;
- unsigned addrlen = sizeof( struct sockaddr_in );
- int i;
- ONDEBUG9( fputs( "\n[accept_conn]\n", stdout ); );
- sd = accept( socket, (struct sockaddr *)&sd_address, &addrlen );
- if ( sd == -1 )
- goto error;
- for ( i = 0; i < MAXCONN; ++i ) {
- if ( app.in_sockets[ i ].sock == -1 ) {
- FILE *fin = fdopen( sd, "r" );
- if ( fin == 0 )
- goto error;
- app.in_sockets[ i ].sock = sd;
- app.in_sockets[ i ].fin = fin;
- app.in_sockets[ i ].ip = strdup( inet_ntoa( sd_address.sin_addr ));
- return;
- }
- }
- close( sd );
- return;
- error:
- perror( 0 );
- if ( sd != -1 )
- close( sd );
- }
- void close_all_conns( void ) {
- int i;
- ONDEBUG9( fputs( "\n[close_all_conns]\n",stdout ); );
- for ( i = 0; i < MAXCONN; ++i ) {
- if ( app.in_sockets[ i ].sock != -1 ) {
- fclose( app.in_sockets[ i ].fin );
- app.in_sockets[ i ].sock = -1;
- app.in_sockets[ i ].fin = 0;
- free( app.in_sockets[ i ].ip );
- }
- }
- }
- void log_stream( int socket, FILE *fin, char *ip ) {
- char sline[ LINESIZE ];
- ONDEBUG9( fputs( "\n[log_stream]\n", stdout ); );
- if ( fgets( sline, sizeof( sline ), fin ) == 0 ) {
- drop_conn( socket );
- return;
- }
- ONDEBUG2 ( fprintf( stdout, "<%d>%d (%d)\n", socket, strlen( sline ), sline[ strlen( sline )-1 ] ); );
- if ( sline[ 0 ] != 'L' || sline[ 1 ] != 'O' || sline[ 2 ] != 'G' || sline[ 3 ] != ' ' || sline[ strlen( sline )-1 ] != '\n' ) {
- if ( fprintf( app.flog, "BADMSG %s %s\n", timestamp(), ip ) == EOF )
- goto error;
- drop_conn( socket );
- }
- else {
- if ( fprintf( app.flog, "LOG %s %s", timestamp(), ip ) == EOF )
- goto error;
- if ( fputs( sline+3, app.flog ) == EOF )
- goto error;
- }
- fflush( app.flog );
- return;
- error:
- perror( 0 );
- exit( 1 );
- }
- void quit( int status ) {
- ONDEBUG9( fputs( "\n[quit]\n", stdout ); );
- close_log();
- close_socket();
- close_all_conns();
- exit( status );
- }
- void intr( int sig ) {
- ONDEBUG9( fputs( "\n[intr]\n", stdout ); );
- ONDEBUG8( fprintf( stdout, "<sig=%d>\n", sig); );
- if ( sig == SIGTERM )
- quit( 0 );
- signal( sig, intr ); /* catch again */
- }
- void init( void ) {
- int i;
- ONDEBUG9( fputs( "\n[init]\n", stdout ); );
- app.log_file = LOGFILE;
- app.port_num = PORTNUM;
- app.socket = -1;
- for ( i = 0; i < MAXCONN; ++i )
- app.in_sockets[ i ].sock = -1;
- }
- void startup( ) {
- ONDEBUG9( fputs( "\n[startup]\n", stdout ); );
- open_log();
- open_socket();
- signal( SIGHUP, intr );
- #if !defined( DEBUG )
- signal( SIGINT, intr );
- #endif
- signal( SIGTERM, intr );
- }
- void main_loop( ) {
- fd_set read_fds;
- int n_fds = FD_SETSIZE;
- int sd, i;
- ONDEBUG9( fputs( "\n[main_loop]\n", stdout ); );
- for (;; ) { /* forever */
- FD_ZERO( &read_fds );
- if ( app.socket != -1 )
- FD_SET( app.socket, &read_fds );
- for ( i = 0; i < MAXCONN; ++i ) {
- sd = app.in_sockets[ i ].sock;
- if ( sd != -1 )
- FD_SET( sd, &read_fds );
- }
- switch ( select( n_fds, &read_fds, 0, 0, 0 )) {
- case -1: /* trouble */
- ONDEBUG8( fprintf( stdout, "<errno=%d>\n", errno) );
- if ( errno != EINTR ) {
- perror( 0 );
- quit( 1 );
- }
- break;
- case 0: /* time out */
- break;
- default: /* event */
- /* connect? */
- if ( app.socket != -1 && FD_ISSET( app.socket, &read_fds ))
- accept_conn( app.socket );
- /* data? */
- for ( i = 0; i < MAXCONN; ++i ) {
- sd = app.in_sockets[ i ].sock;
- if ( sd != -1 && FD_ISSET( sd, &read_fds ))
- log_stream( sd, app.in_sockets[ i ].fin, app.in_sockets[ i ].ip );
- }
- break;
- }
- }
- }
- int main( int argc, char **argv ) {
- extern int opterr;
- int c;
- init();
- opterr = 0;
- #if defined( DEBUG )
- while ( (c = getopt( argc, argv, "D:p:" )) != -1 )
- #else
- while ( (c = getopt( argc, argv, "p:" )) != -1 )
- #endif
- switch ( c ) {
- #if defined( DEBUG )
- case 'D':
- debug = atoi( optarg );
- break;
- #endif
- case 'p':
- if ((app.port_num = atoi( optarg )) == 0) {
- fputs( "portnum?\n", stderr );
- exit( 1 );
- }
- break;
- default:
- usage:
- #if defined( DEBUG )
- fprintf( stderr, "%s [-D level] [-p port_num] [log_file]\n", argv[ 0 ] );
- #else
- fprintf( stderr, "%s [-p port_num] [log_file]\n", argv[ 0 ] );
- #endif
- exit( 1 );
- }
- switch ( argc - optind ) {
- case 0:
- break;
- case 1:
- app.log_file = argv[ optind ];
- break;
- default:
- goto usage;
- }
- setbuf( stdout, 0 );
- startup();
- main_loop();
- }
Comments