Esempio n. 1
0
void env_universal_destroy()
{
	/*
	  Go into blocking mode and send all data before exiting
	*/
	if( env_universal_server.fd >= 0 )
	{
		if( fcntl( env_universal_server.fd, F_SETFL, 0 ) != 0 )
		{
			wperror( L"fcntl" );
		}
		try_send_all( &env_universal_server );		
	}

	connection_destroy( &env_universal_server );
	env_universal_server.fd =-1;
	env_universal_common_destroy();
	init = 0;
}
Esempio n. 2
0
/**
   Main function for fishd
*/
int main( int argc, char ** argv )
{
	int child_socket;
	struct sockaddr_un remote;
	socklen_t t;
	int max_fd;
	int update_count=0;
	
	fd_set read_fd, write_fd;

	set_main_thread();
    setup_fork_guards();
	
	program_name=L"fishd";
	wsetlocale( LC_ALL, L"" );	

	/*
	  Parse options
	*/
	while( 1 )
	{
		static struct option
			long_options[] =
			{
				{
					"help", no_argument, 0, 'h' 
				}
				,
				{
					"version", no_argument, 0, 'v' 
				}
				,
				{ 
					0, 0, 0, 0 
				}
			}
		;
		
		int opt_index = 0;
		
		int opt = getopt_long( argc,
							   argv, 
							   GETOPT_STRING,
							   long_options, 
							   &opt_index );
		
		if( opt == -1 )
			break;
		
		switch( opt )
		{
			case 0:
				break;				

			case 'h':
				print_help( argv[0], 1 );
				exit(0);				
								
			case 'v':
				debug( 0, L"%ls, version %s\n", program_name, PACKAGE_VERSION );
				exit( 0 );				
				
			case '?':
				return 1;
				
		}		
	}
	
	init();
	while(1) 
	{
		connection_t *c;
		int res;

		t = sizeof( remote );		
		
		FD_ZERO( &read_fd );
		FD_ZERO( &write_fd );
		FD_SET( sock, &read_fd );
		max_fd = sock+1;
		for( c=conn; c; c=c->next )
		{
			FD_SET( c->fd, &read_fd );
			max_fd = maxi( max_fd, c->fd+1);
			
			if( ! c->unsent->empty() )
			{
				FD_SET( c->fd, &write_fd );
			}
		}

		while( 1 )
		{
			res=select( max_fd, &read_fd, &write_fd, 0, 0 );

			if( quit )
			{
				save();
				exit(0);
			}
			
			if( res != -1 )
				break;
			
			if( errno != EINTR )
			{
				wperror( L"select" );
				exit(1);
			}
		}
				
		if( FD_ISSET( sock, &read_fd ) )
		{
			if( (child_socket = 
				 accept( sock, 
						 (struct sockaddr *)&remote, 
						 &t) ) == -1) {
				wperror( L"accept" );
				exit(1);
			}
			else
			{
				debug( 4, L"Connected with new child on fd %d", child_socket );

				if( fcntl( child_socket, F_SETFL, O_NONBLOCK ) != 0 )
				{
					wperror( L"fcntl" );
					close( child_socket );		
				}
				else
				{
					connection_t *newc = (connection_t *)malloc( sizeof(connection_t));
					connection_init( newc, child_socket );					
					newc->next = conn;
					send( newc->fd, GREETING, strlen(GREETING), MSG_DONTWAIT );
					enqueue_all( newc );				
					conn=newc;
				}
			}
		}
		
		for( c=conn; c; c=c->next )
		{
			if( FD_ISSET( c->fd, &write_fd ) )
			{
				try_send_all( c );
			}
		}
		
		for( c=conn; c; c=c->next )
		{
			if( FD_ISSET( c->fd, &read_fd ) )
			{
				read_message( c );

				/*
				  Occasionally we save during normal use, so that we
				  won't lose everything on a system crash
				*/
				update_count++;
				if( update_count >= 64 )
				{
					save();
					update_count = 0;
				}
			}
		}
		
		connection_t *prev=0;
		c=conn;
		
		while( c )
		{
			if( c->killme )
			{
				debug( 4, L"Close connection %d", c->fd );

				while( ! c->unsent->empty() )
				{
					message_t *msg = c->unsent->front();
                    c->unsent->pop();
					msg->count--;
					if( !msg->count )
						free( msg );
				}
				
				connection_destroy( c );
				if( prev )
				{
					prev->next=c->next;
				}
				else
				{
					conn=c->next;
				}
				
				free(c);
				
				c=(prev?prev->next:conn);
				
			}
			else
			{
				prev=c;
				c=c->next;
			}
		}

		if( !conn )
		{
			debug( 0, L"No more clients. Quitting" );
			save();			
			env_universal_common_destroy();
			break;
		}		

	}
}