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; }
/** 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; } } }