X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;ds=sidebyside;f=utils%2FTerraSync%2Fterrasync.cxx;h=121a2347bb7c8ef2af973942eda68afd2ad7cfd5;hb=18beaecbcda10167c11bf9474fa3d007d28d1fe7;hp=f6c33c9b64c3e393ae6f2749c127dc22d88a43e8;hpb=397363760612c3b987125a2d1c6be083a8d306b3;p=flightgear.git diff --git a/utils/TerraSync/terrasync.cxx b/utils/TerraSync/terrasync.cxx index f6c33c9b6..121a2347b 100644 --- a/utils/TerraSync/terrasync.cxx +++ b/utils/TerraSync/terrasync.cxx @@ -4,6 +4,7 @@ // // Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt // Copyright (C) 2008 Alexander R. Perry +// Copyright (C) 2011 Thorsten Brehm // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -25,15 +26,20 @@ #include #endif +#include + #ifdef HAVE_WINDOWS_H #include #endif +#ifdef HAVE_UNISTD_H +#include "unistd.h" +#endif + #ifdef __MINGW32__ -#include -#include +# include #elif defined(_MSC_VER) -#include +# include #endif #include // atoi() atof() abs() system() @@ -44,278 +50,145 @@ #include #include #include -#include -#include - -#include -#include - -#include -#include - -#ifdef HAVE_SVN_CLIENT_H -# ifdef HAVE_LIBSVN_CLIENT_1 -# include -# include -# include -# include -# else -# undef HAVE_SVN_CLIENT_H -# endif -#endif - -using namespace std; -const char* source_base = NULL; -const char* svn_base = - "http://terrascenery.googlecode.com/svn/trunk/data/Scenery"; -const char* rsync_base = "scenery.flightgear.org::Scenery"; -const char* dest_base = "terrasyncdir"; -const char* rsync_cmd = - "rsync --verbose --archive --delete --perms --owner --group"; +#include +#include -#ifdef HAVE_SVN_CLIENT_H -bool use_svn = true; -#else -bool use_svn = false; -const char* svn_cmd = "svn checkout"; -#endif - -// display usage -static void usage( const string& prog ) { - cout << -"Usage: terrasync [options]\n" -"Options: \n" -" -d destination directory [required]\n" -" -R transport using pipe to rsync\n" -" -S transport using built-in svn\n" -" -p listen on UDP port [default: 5501]\n" -" -s source base [default: '']\n" -" -pid write PID to file\n" -" -v be more verbose\n" -; - -#ifdef HAVE_SVN_CLIENT_H - cout << " (defaults to the built in subversion)" << endl; -#else - cout << " (defaults to rsync, using external commands)" << endl; +#if defined(_MSC_VER) || defined(__MINGW32__) + typedef void (__cdecl * sighandler_t)(int); +#elif defined( __APPLE__ ) || defined (__FreeBSD__) + typedef sig_t sighandler_t; #endif - cout << "\nExample:\n" -"pid=$(cat $pidfile 2>/dev/null)\n" -"if test -n \"$pid\" && kill -0 $pid ; then\n" -" echo \"terrasync already running: $pid\"\n" -"else\n" -" nice /games/sport/fgs/utils/TerraSync/terrasync \\\n" -" -v -pid $pidfile -S -p 5500 -d /games/orig/terrasync &\n" -"fi" << endl; - -} - -deque waitingTiles; -typedef map CompletedTiles; -CompletedTiles completedTiles; -netSocket theSocket; - -#ifdef HAVE_SVN_CLIENT_H - -// Things we need for doing subversion checkout - often -apr_pool_t *mysvn_pool = NULL; -svn_client_ctx_t *mysvn_ctx = NULL; -svn_opt_revision_t *mysvn_rev = NULL; -svn_opt_revision_t *mysvn_rev_peg = NULL; - -static const svn_version_checklist_t mysvn_checklist[] = { - { "svn_subr", svn_subr_version }, - { "svn_client", svn_client_version }, - { "svn_wc", svn_wc_version }, - { "svn_ra", svn_ra_version }, - { "svn_delta", svn_delta_version }, - { "svn_diff", svn_diff_version }, - { NULL, NULL } -}; - -// Configure our subversion session -int mysvn_setup(void) { - // Are we already prepared? - if (mysvn_pool) return EXIT_SUCCESS; - // No, so initialize svn internals generally -#ifdef _MSC_VER - // there is a segfault when providing an error stream. - // Apparently, calling setvbuf with a nul buffer is - // not supported under msvc 7.1 ( code inside svn_cmdline_init ) - if (svn_cmdline_init("terrasync", 0) != EXIT_SUCCESS) - return EXIT_FAILURE; +int termination_triggering_signals[] = { +#if defined(_MSC_VER) || defined(__MINGW32__) + SIGINT, SIGILL, SIGFPE, SIGSEGV, SIGTERM, SIGBREAK, SIGABRT, #else - if (svn_cmdline_init("terrasync", stderr) != EXIT_SUCCESS) - return EXIT_FAILURE; -#endif - apr_pool_t *pool; - apr_pool_create(&pool, NULL); - svn_error_t *err = NULL; - SVN_VERSION_DEFINE(mysvn_version); - err = svn_ver_check_list(&mysvn_version, mysvn_checklist); - if (err) - return svn_cmdline_handle_exit_error(err, pool, "terrasync: "); - err = svn_ra_initialize(pool); - if (err) - return svn_cmdline_handle_exit_error(err, pool, "terrasync: "); - char *config_dir = NULL; - err = svn_config_ensure(config_dir, pool); - if (err) - return svn_cmdline_handle_exit_error(err, pool, "terrasync: "); - err = svn_client_create_context(&mysvn_ctx, pool); - if (err) - return svn_cmdline_handle_exit_error(err, pool, "terrasync: "); - err = svn_config_get_config(&(mysvn_ctx->config), - config_dir, pool); - if (err) - return svn_cmdline_handle_exit_error(err, pool, "terrasync: "); - svn_config_t *cfg; - cfg = ( svn_config_t*) apr_hash_get( - mysvn_ctx->config, - SVN_CONFIG_CATEGORY_CONFIG, - APR_HASH_KEY_STRING); - if (err) - return svn_cmdline_handle_exit_error(err, pool, "terrasync: "); - svn_auth_baton_t *ab; - err = svn_cmdline_setup_auth_baton(&ab, - TRUE, NULL, NULL, config_dir, TRUE, cfg, - mysvn_ctx->cancel_func, mysvn_ctx->cancel_baton, pool); - if (err) - return svn_cmdline_handle_exit_error(err, pool, "terrasync: "); - mysvn_ctx->auth_baton = ab; - mysvn_ctx->conflict_func = NULL; - mysvn_ctx->conflict_baton = NULL; - // Now our magic revisions - mysvn_rev = (svn_opt_revision_t*) apr_palloc(pool, - sizeof(svn_opt_revision_t)); - if (!mysvn_rev) - return EXIT_FAILURE; - mysvn_rev_peg = (svn_opt_revision_t*) apr_palloc(pool, - sizeof(svn_opt_revision_t)); - if (!mysvn_rev_peg) - return EXIT_FAILURE; - mysvn_rev->kind = svn_opt_revision_head; - mysvn_rev_peg->kind = svn_opt_revision_unspecified; - // Success if we got this far - mysvn_pool = pool; - return EXIT_SUCCESS; -} - + SIGHUP, SIGINT, SIGQUIT, SIGKILL, SIGTERM, #endif + 0}; // zero terminated -// sync one directory tree -void sync_tree(const char* dir) { - int rc; - char command[512]; - SGPath path( dest_base ); - - path.append( dir ); - rc = path.create_dir( 0755 ); - if (rc) { - cout << "Return code = " << rc << endl; - exit(1); - } +using namespace std; - if (use_svn) { -#ifdef HAVE_SVN_CLIENT_H - cout << dir << " ... "; - cout.flush(); - char dest_base_dir[512]; - snprintf( command, 512, - "%s/%s", source_base, dir); - snprintf( dest_base_dir, 512, - "%s/%s", dest_base, dir); - svn_error_t *err = NULL; - if (mysvn_setup() != EXIT_SUCCESS) - exit(1); - apr_pool_t *subpool = svn_pool_create(mysvn_pool); - err = svn_client_checkout3(NULL, - command, - dest_base_dir, - mysvn_rev_peg, - mysvn_rev, - svn_depth_infinity, - 0, - 0, - mysvn_ctx, - subpool); - if (err) { - // Report errors from the checkout attempt - cout << "failed: " << endl - << err->message << endl; - svn_error_clear(err); - return; - } else { - cout << "done" << endl; - } - svn_pool_destroy(subpool); - return; -#else +const char* svn_base = "http://terrascenery.googlecode.com/svn/trunk/data/Scenery"; +const char* rsync_base = "flightgear.mxchange.org::Scenery"; - snprintf( command, 512, - "%s %s/%s %s/%s", svn_cmd, - source_base, dir, - dest_base, dir ); -#endif - } else { - snprintf( command, 512, - "%s %s/%s/ %s/%s/", rsync_cmd, - source_base, dir, - dest_base, dir ); - } - cout << command << endl; - rc = system( command ); - if (rc) { - cout << "Return code = " << rc << endl; - if (rc == 5120) exit(1); - } -} +bool terminating = false; +sighandler_t prior_signal_handlers[32]; -#ifdef _MSC_VER -typedef void (__cdecl * sighandler_t)(int); -#elif defined( __APPLE__ ) -typedef sig_t sighandler_t; +simgear::Socket theSocket; +simgear::SGTerraSync* pTerraSync = NULL; + +/** display usage information */ +static void +usage( const string& prog ) { + cout << "Usage: terrasync [options]\n" + "Options:\n" + " -d destination directory [required]\n" + " -R transport using pipe to rsync\n" + " -S transport using built-in svn\n" + " -e transport using external svn client\n" + " -p listen on UDP port [default: 5501]\n" + " -s source base [default: '']\n" +#ifndef _MSC_VER + " -pid write PID to file\n" #endif + " -v be more verbose\n"; -bool terminating = false; -sighandler_t prior_signal_handlers[32]; -int termination_triggering_signals[] = { #ifndef _MSC_VER - SIGHUP, SIGINT, SIGQUIT, SIGKILL, -#else - SIGINT, SIGILL, SIGFPE, SIGSEGV, SIGTERM, SIGBREAK, SIGABRT, + cout << "\n" + "Example:\n" + " pid=$(cat $pidfile 2>/dev/null)\n" + " if test -n \"$pid\" && kill -0 $pid ; then\n" + " echo \"terrasync already running: $pid\"\n" + " else\n" + " nice /games/sport/fgs/utils/TerraSync/terrasync \\\n" + " -v -pid $pidfile -S -p 5500 -d /games/orig/terrasync &\n" + " fi\n"; #endif - 0}; // zero terminated +} -void terminate_request_handler(int param) { +/** Signal handler for termination requests (Ctrl-C) */ +void +terminate_request_handler(int param) +{ char msg[] = "\nReceived signal XX, intend to exit soon.\n" - "repeat the signal to force immediate termination.\n"; + "Repeat the signal to force immediate termination.\n"; msg[17] = '0' + param / 10; msg[18] = '0' + param % 10; - write(1, msg, sizeof(msg) - 1); + if (write(1, msg, sizeof(msg) - 1) == -1) + { + // need to act write's return value to avoid GCC compiler warning + // "'write' declared with attribute warn_unused_result" + terminating = true; // dummy operation + } terminating = true; signal(param, prior_signal_handlers[param]); theSocket.close(); + if (pTerraSync) + pTerraSync->unbind(); } +/** Parse command-line options. */ +void +parseOptions(int argc, char** argv, SGPropertyNode_ptr config, + bool& testing, int& verbose, int& port, const char* &pidfn) +{ + // parse arguments + for (int i=1; i < argc; ++i ) + { + string arg = argv[i]; + if ( arg == "-p" ) { + ++i; + port = atoi( argv[i] ); + } else if ( arg.find("-pid") == 0 ) { + ++i; + pidfn = argv[i]; + cout << "pidfn: " << pidfn << endl; + } else if ( arg == "-s" ) { + ++i; + config->setStringValue("svn-server", argv[i]); + } else if ( arg == "-d" ) { + ++i; + config->setStringValue("scenery-dir", argv[i]); + } else if ( arg == "-R" ) { + config->setBoolValue("use-svn", false); + } else if ( arg == "-S" ) { + config->setBoolValue("use-built-in-svn", true); + } else if ( arg == "-e" ) { + config->setBoolValue("use-built-in-svn", false); + } else if ( arg == "-v" ) { + verbose++; + } else if ( arg == "-T" ) { + testing = true; + } else if ( arg == "-h" ) { + usage( argv[0] ); + exit(0); + } else { + cerr << "Unrecognized command-line option '" << arg << "'" << endl; + usage( argv[0] ); + exit(-1); + } + } +} -const int nowhere = -9999; - - -// parse message -static void parse_message( const string &msg, int *lat, int *lon ) { +/** parse a single NMEA-0183 position message */ +static void +parse_message( int verbose, const string &msg, int *lat, int *lon ) +{ double dlat, dlon; string text = msg; - // find GGA string and advance to start of lat + if (verbose>=3) + cout << "message: '" << text << "'" << endl; + + // find GGA string and advance to start of lat (see NMEA-0183 for protocol specs) string::size_type pos = text.find( "$GPGGA" ); if ( pos == string::npos ) { - *lat = nowhere; - *lon = nowhere; - return; + *lat = simgear::NOWHERE; + *lon = simgear::NOWHERE; + return; } string tmp = text.substr( pos + 7 ); pos = tmp.find( "," ); @@ -359,14 +232,14 @@ static void parse_message( const string &msg, int *lat, int *lon ) { } if ((dlon == 0) && (dlat == 0)) { - *lon = nowhere; - *lat = nowhere; + *lon = simgear::NOWHERE; + *lat = simgear::NOWHERE; } } - -// sync area -static void sync_area( int lat, int lon ) { +void +syncArea( int lat, int lon ) +{ if ( lat < -90 || lat > 90 || lon < -180 || lon > 180 ) return; char NS, EW; @@ -397,239 +270,245 @@ static void sync_area( int lat, int lon ) { EW = 'e'; } - const char* terrainobjects[3] = { "Terrain", "Objects", 0 }; + ostringstream dir; + dir << setfill('0') + << EW << setw(3) << abs(baselon) << NS << setw(2) << abs(baselat) << "/" + << EW << setw(3) << abs(lon) << NS << setw(2) << abs(lat); - for (const char** tree = &terrainobjects[0]; *tree; tree++) { - char dir[512]; - snprintf( dir, 512, "%s/%c%03d%c%02d/%c%03d%c%02d", - *tree, - EW, abs(baselon), NS, abs(baselat), - EW, abs(lon), NS, abs(lat) ); - waitingTiles.push_back( dir ); - } + pTerraSync->syncAreaByPath(dir.str()); } - -// sync areas -static void sync_areas( int lat, int lon, int lat_dir, int lon_dir ) { - // do current 1x1 degree area first - sync_area( lat, lon ); - +void +syncAreas( int lat, int lon, int lat_dir, int lon_dir ) +{ if ( lat_dir == 0 && lon_dir == 0 ) { - // now do surrounding 8 1x1 degree areas. + + // do surrounding 8 1x1 degree areas. for ( int i = lat - 1; i <= lat + 1; ++i ) { for ( int j = lon - 1; j <= lon + 1; ++j ) { if ( i != lat || j != lon ) { - sync_area( i, j ); + syncArea( i, j ); } } } } else { if ( lat_dir != 0 ) { - sync_area( lat + lat_dir, lon ); - sync_area( lat + lat_dir, lon - 1 ); - sync_area( lat + lat_dir, lon + 1 ); + syncArea( lat + lat_dir, lon - 1 ); + syncArea( lat + lat_dir, lon + 1 ); + syncArea( lat + lat_dir, lon ); } if ( lon_dir != 0 ) { - sync_area( lat, lon + lon_dir ); - sync_area( lat - 1, lon + lon_dir ); - sync_area( lat + 1, lon + lon_dir ); + syncArea( lat - 1, lon + lon_dir ); + syncArea( lat + 1, lon + lon_dir ); + syncArea( lat, lon + lon_dir ); } } -} -void getWaitingTile() { - while ( !waitingTiles.empty() ) { - CompletedTiles::iterator ii = - completedTiles.find( waitingTiles.front() ); - time_t now = time(0); - if ( ii == completedTiles.end() || ii->second + 600 < now ) { - sync_tree(waitingTiles.front().c_str()); - completedTiles[ waitingTiles.front() ] = now; - waitingTiles.pop_front(); - break; - } - waitingTiles.pop_front(); - } + // do current 1x1 degree area first + syncArea( lat, lon ); } -int main( int argc, char **argv ) { - int port = 5501; - char host[256] = "localhost"; - bool testing = false; - bool do_checkout(true); - int verbose(0); - const char* pidfn = ""; +bool +schedulePosition(int lat, int lon) +{ + bool Ok = false; + if ((lat == simgear::NOWHERE) || (lon == simgear::NOWHERE)) { + return Ok; + } + + static int last_lat = simgear::NOWHERE; + static int last_lon = simgear::NOWHERE; + if ((lat == last_lat) && (lon == last_lon)) { + Ok = true; + return Ok; + } - // parse arguments - int i = 1; - while ( i < argc ) { - if ( (string)argv[i] == "-p" ) { - ++i; - port = atoi( argv[i] ); - } else if ( string(argv[i]).find("-pid") == 0 ) { - ++i; - pidfn = argv[i]; - cout << "pidfn: " << pidfn << endl; - } else if ( (string)argv[i] == "-s" ) { - ++i; - source_base = argv[i]; - } else if ( (string)argv[i] == "-d" ) { - ++i; - dest_base = argv[i]; - } else if ( (string)argv[i] == "-R" ) { - use_svn = false; - } else if ( (string)argv[i] == "-S" ) { - use_svn = true; - } else if ( (string)argv[i] == "-v" ) { - verbose++; - } else if ( (string)argv[i] == "-T" ) { - testing = true; - } else if ( (string)argv[i] == "-h" ) { - usage( argv[0] ); - exit(0); - } else { - cerr << "Unrecognized verbiage '" << argv[i] << "'" << endl; - usage( argv[0] ); - exit(-1); + int lat_dir=0; + int lon_dir=0; + + if ( last_lat != simgear::NOWHERE && last_lon != simgear::NOWHERE ) + { + int dist = lat - last_lat; + if ( dist != 0 ) + { + lat_dir = dist / abs(dist); + } + else + { + lat_dir = 0; + } + dist = lon - last_lon; + if ( dist != 0 ) + { + lon_dir = dist / abs(dist); + } else + { + lon_dir = 0; } - ++i; } - if (*pidfn) { - ofstream pidstream; - pidstream.open(pidfn); - if (!pidstream.good()) { - cerr << "Cannot open pid file '" << pidfn << "': "; - perror(0); - exit(2); - } - pidstream << getpid() << endl; - pidstream.close(); - } + cout << "Scenery update for " << + "lat = " << lat << ", lon = " << lon << + ", lat_dir = " << lat_dir << ", " << + "lon_dir = " << lon_dir << endl; - // Use the appropriate default for the "-s" flag - if (source_base == NULL) { - if (use_svn) - source_base = svn_base; - else - source_base = rsync_base; - } + syncAreas( lat, lon, lat_dir, lon_dir ); + Ok = true; + + last_lat = lat; + last_lon = lon; + + return Ok; +} +/** Monitor UDP socket and process NMEA position updates. */ +int +processRequests(SGPropertyNode_ptr config, bool testing, int verbose, int port) +{ + const char* host = "localhost"; + char msg[256]; + int len; + int lat, lon; + bool connected = false; + // Must call this before any other net stuff - netInit( &argc,argv ); + simgear::Socket::initSockets(); - if ( ! theSocket.open( false ) ) { // open a UDP socket - printf("error opening socket\n"); + // open UDP socket + if ( !theSocket.open( false ) ) + { + cerr << "error opening socket" << endl; return -1; } - if ( theSocket.bind( host, port ) == -1 ) { - printf("error binding to port %d\n", port); + if ( theSocket.bind( host, port ) == -1 ) + { + cerr << "error binding to port " << port << endl; return -1; } - char msg[256]; - int maxlen = 256; - int len; - int lat, lon; - int last_lat = nowhere; - int last_lon = nowhere; - bool recv_msg = false; - - char synced_other; - if (do_checkout) { - for ( synced_other = 'K'; synced_other <= 'Z'; synced_other++ ) { - char dir[512]; - snprintf( dir, 512, "Airports/%c", synced_other ); - waitingTiles.push_back( dir ); - } - for ( synced_other = 'A'; synced_other <= 'J'; synced_other++ ) { - char dir[512]; - snprintf( dir, 512, "Airports/%c", synced_other ); - waitingTiles.push_back( dir ); - } - if ( use_svn ) { - waitingTiles.push_back( "Models" ); - } - } - - - for (int* sigp=termination_triggering_signals; *sigp; sigp++) { - prior_signal_handlers[*sigp] = - signal(*sigp, *terminate_request_handler); - if (verbose) cout << "Intercepted signal " << *sigp << endl; - } + theSocket.setBlocking(true); - while ( !terminating ) { + while ( (!terminating)&& + (!config->getBoolValue("stalled", false)) ) + { + if (verbose >= 4) + cout << "main loop" << endl; // main loop - recv_msg = false; - if ( testing ) { - // No FGFS communications + bool recv_msg = false; + if ( testing ) + { + // Testing without FGFS communication lat = 37; lon = -123; - recv_msg = (lat != last_lat) || (lon != last_lon); - } else { - if (verbose && waitingTiles.empty()) { - cout << "Idle; waiting for FlightGear position\n"; + recv_msg = true; + } else + { + if (verbose && pTerraSync->isIdle()) + { + cout << "Idle; waiting for FlightGear position data" << endl; } - theSocket.setBlocking(waitingTiles.empty()); - len = theSocket.recv(msg, maxlen, 0); - if (len >= 0) { + len = theSocket.recv(msg, sizeof(msg)-1, 0); + if (len >= 0) + { msg[len] = '\0'; recv_msg = true; - if (verbose) cout << "recv length: " << len << endl; - parse_message( msg, &lat, &lon ); - } - } - - if ( recv_msg ) { - // Ignore messages where the location does not change - if ( lat != last_lat || lon != last_lon ) { - cout << "pos in msg = " << lat << "," << lon << endl; - deque oldRequests; - oldRequests.swap( waitingTiles ); - int lat_dir, lon_dir, dist; - if ( last_lat == nowhere || last_lon == nowhere ) { - lat_dir = lon_dir = 0; - } else { - dist = lat - last_lat; - if ( dist != 0 ) { - lat_dir = dist / abs(dist); - } else { - lat_dir = 0; - } - dist = lon - last_lon; - if ( dist != 0 ) { - lon_dir = dist / abs(dist); - } else { - lon_dir = 0; - } + if (verbose>=2) + cout << "recv length: " << len << endl; + parse_message( verbose, msg, &lat, &lon ); + if ((!connected)&& + (lat != simgear::NOWHERE)&& + (lon != simgear::NOWHERE)) + { + cout << "Valid position data received. Connected successfully." << endl; + connected = true; } - cout << "lat = " << lat << " lon = " << lon << endl; - cout << "lat_dir = " << lat_dir << " " - << "lon_dir = " << lon_dir << endl; - sync_areas( lat, lon, lat_dir, lon_dir ); - while ( !oldRequests.empty() ) { - waitingTiles.push_back( oldRequests.front() ); - oldRequests.pop_front(); - } - last_lat = lat; - last_lon = lon; } - } - - // No messages inbound, so process some pending work - else if ( !waitingTiles.empty() ) { - getWaitingTile(); } - else if ( testing ) { - terminating = true; - } else + if ( recv_msg ) + { + schedulePosition(lat, lon); + } - ulSleep( 1 ); + if ( testing ) + { + if (pTerraSync->isIdle()) + terminating = true; + else + SGTimeStamp::sleepForMSec(1000); + } } // while !terminating - + return 0; } + + +int main( int argc, char **argv ) +{ + int port = 5501; + int verbose = 0; + int exit_code = 0; + bool testing = false; + const char* pidfn = ""; + + // default configuration + sglog().setLogLevels( SG_ALL, SG_ALERT); + SGPropertyNode_ptr root = new SGPropertyNode(); + SGPropertyNode_ptr config = root->getNode("/sim/terrasync", true); + config->setStringValue("scenery-dir", "terrasyncdir"); + config->setStringValue("svn-server", svn_base); + config->setStringValue("rsync-server", rsync_base); + config->setBoolValue("use-built-in-svn", true); + config->setBoolValue("use-svn", true); + config->setBoolValue("enabled", true); + config->setIntValue("max-errors", -1); // -1 = infinite + + // parse command-line arguments + parseOptions(argc, argv, config, testing, verbose, port, pidfn); + + if (verbose) + sglog().setLogLevels( SG_ALL, SG_INFO); + +#ifndef _MSC_VER + // create PID file + if (*pidfn) + { + ofstream pidstream; + pidstream.open(pidfn); + if (!pidstream.good()) + { + cerr << "Cannot open pid file '" << pidfn << "': "; + perror(0); + exit(2); + } + pidstream << getpid() << endl; + pidstream.close(); + } +#endif + + // install signal handlers + for (int* sigp=termination_triggering_signals; *sigp; sigp++) + { + prior_signal_handlers[*sigp] = + signal(*sigp, *terminate_request_handler); + if (verbose>=2) + cout << "Intercepting signal " << *sigp << endl; + } + + { + pTerraSync = new simgear::SGTerraSync; + pTerraSync->setRoot(root); + pTerraSync->bind(); + pTerraSync->init(); + + // now monitor and process position updates + exit_code = processRequests(config, testing, verbose, port); + + pTerraSync->unbind(); + delete pTerraSync; + pTerraSync = NULL; + } + + return exit_code; +}