int main( int argc, char **argv )
{
    if (boost::ends_with(argv[0], "syncevo-local-sync")) {
        return LocalTransportMain(argc, argv);
    }

    // Intercept stderr and route it through our logging.
    // stdout is printed normally. Deconstructing it when
    // leaving main() does one final processing of pending
    // output.
    LogRedirect redirect(false);
    setvbuf(stderr, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);

    SyncContext::initMain("syncevolution");

    // Expand PATH to cover the directory we were started from?
    // This might be needed to find normalize_vcard.
    char *exe = strdup(argv[0]);
    if (strchr(exe, '/') ) {
        char *dir = dirname(exe);
        string path;
        char *oldpath = getenv("PATH");
        if (oldpath) {
            path += oldpath;
            path += ":";
        }
        path += dir;
        setenv("PATH", path.c_str(), 1);
    }
    free(exe);

    try {
        if (getenv("SYNCEVOLUTION_DEBUG")) {
            LoggerBase::instance().setLevel(Logger::DEBUG);
        }

        SyncEvo::KeyringSyncCmdline cmdline(argc, argv);
        vector<string> parsedArgs;
        if(!cmdline.parse(parsedArgs)) {
            return 1;
        }

        if (cmdline.dontRun()) {
            return 0;
        }

        Bool useDaemon = cmdline.useDaemon();

        if(cmdline.monitor()) {

#ifdef DBUS_SERVICE
            // monitor a session
            RemoteDBusServer server;
            if(server.checkStarted() && server.monitor(cmdline.getConfigName())) {
                return 0;
            }
            return 1;
#else
            SE_LOG_ERROR(NULL, NULL, "this syncevolution binary was compiled without support for monitoring a background sync");
            return 1;
#endif
        } else if(cmdline.status() && 
                  cmdline.getConfigName().empty()) {

#ifdef DBUS_SERVICE
            // '--status' and no server name, try to get running sessions 
            RemoteDBusServer server;
            if(server.checkStarted()) {
                server.runningSessions();
                return 0;
            }
            return 1;
#else
            SE_LOG_SHOW(NULL, NULL, "this syncevolution binary was compiled without support for monitoring a background sync");
            return 1;
#endif
        } else if (useDaemon ||
                   !useDaemon.wasSet()) {
#ifdef DBUS_SERVICE
            RemoteDBusServer server;

            // Running execute() without the server available will print errors.
            // Avoid that unless the user explicitly asked for the daemon.
            bool result = server.checkStarted(false);
            if (useDaemon.wasSet() || result) {
                return !server.execute(parsedArgs, cmdline.getConfigName(), cmdline.isSync());
            } else {
                // User didn't select --use-daemon and thus doesn't need to know about it
                // not being available.
                // SE_LOG_SHOW(NULL, NULL, "WARNING: cannot run syncevolution as daemon. "
                //             "Trying to run it without daemon.");
            }
#else
            if (useDaemon.wasSet()) {
                SE_LOG_SHOW(NULL, NULL, "ERROR: this syncevolution binary was compiled without support of daemon. "
                            "Either run syncevolution with '--use-daemon=no' or without that option."); 
                return 1;
            }
#endif
        } 

        // if forcing not using daemon or trying to use daemon with failures,
        // run arguments in the process
        if (!useDaemon.wasSet() ||
            !useDaemon) {
            EDSAbiWrapperInit();

            /*
             * don't log errors to cerr: LogRedirect cannot distinguish
             * between our valid error messages and noise from other
             * libs, therefore it would get suppressed (logged at
             * level DEVELOPER, while output is at most INFO)
             */
            if (cmdline.run()) {
                return 0;
            } else {
                return 1;
            }
        }
    } catch ( const std::exception &ex ) {
        SE_LOG_ERROR(NULL, NULL, "%s", ex.what());
    } catch (...) {
        SE_LOG_ERROR(NULL, NULL, "unknown error");
    }

    return 1;
}