예제 #1
0
파일: xrdp.c 프로젝트: dlinz/xrdp-ng
void xrdp_shutdown(int sig)
{
	LONG_PTR threadid;

	threadid = tc_get_threadid();
	g_writeln("shutting down");
	g_writeln("signal %d threadid %p", sig, threadid);

	if (WaitForSingleObject(g_TermEvent, 0) != WAIT_OBJECT_0)
		SetEvent(g_TermEvent);
}
예제 #2
0
파일: xrdpwin.c 프로젝트: AsherBond/xrdp
void DEFAULT_CC
xrdp_shutdown(int sig)
{
    tbus threadid;

    threadid = tc_get_threadid();
    g_writeln("shutting down");
    g_writeln("signal %d threadid %p", sig, threadid);

    if (!g_is_wait_obj_set(g_term_event))
    {
        g_set_wait_obj(g_term_event);
    }
}
예제 #3
0
파일: xrdp.c 프로젝트: dlinz/xrdp-ng
/* This function is used to run a function from the main thread.
 Sync_func is the function pointer that will run from main thread
 The function can have two long in parameters and must return long */
long g_xrdp_sync(long(*sync_func)(long param1, long param2), long sync_param1, long sync_param2)
{
	long sync_result;
	int sync_command;

	/* If the function is called from the main thread, the function can
	 * be called directly. g_threadid= main thread ID*/
	if (tc_threadid_equal(tc_get_threadid(), g_threadid))
	{
		/* this is the main thread, call the function directly */
		/* in fork mode, this always happens too */
		sync_result = sync_func(sync_param1, sync_param2);
		/*g_writeln("g_xrdp_sync processed IN main thread -> continue");*/
	}
	else
	{
		/* All threads have to wait here until the main thread
		 * process the function. g_process_waiting_function() is called
		 * from the listening thread. g_process_waiting_function() process the function*/
		tc_mutex_lock(g_sync1_mutex);
		tc_mutex_lock(g_sync_mutex);
		g_sync_param1 = sync_param1;
		g_sync_param2 = sync_param2;
		g_sync_func = sync_func;
		/* set a value THREAD_WAITING so the g_process_waiting_function function
		 * know if any function must be processed */
		g_sync_command = THREAD_WAITING;
		tc_mutex_unlock(g_sync_mutex);
		/* set this event so that the main thread know if
		 * g_process_waiting_function() must be called */
		SetEvent(g_SyncEvent);

		do
		{
			g_sleep(100);
			tc_mutex_lock(g_sync_mutex);
			/* load new value from global to see if the g_process_waiting_function()
			 * function has processed the function */
			sync_command = g_sync_command;
			sync_result = g_sync_result;
			tc_mutex_unlock(g_sync_mutex);
		} while (sync_command != 0); /* loop until g_process_waiting_function()

		 * has processed the request */
		tc_mutex_unlock(g_sync1_mutex);
		/*g_writeln("g_xrdp_sync processed BY main thread -> continue");*/
	}

	return sync_result;
}
예제 #4
0
파일: xrdpwin.c 프로젝트: AsherBond/xrdp
long APP_CC
g_xrdp_sync(long (*sync_func)(long param1, long param2), long sync_param1,
            long sync_param2)
{
    long sync_result;
    int sync_command;

    if (tc_threadid_equal(tc_get_threadid(), g_threadid))
    {
        /* this is the main thread, call the function directly */
        sync_result = sync_func(sync_param1, sync_param2);
    }
    else
    {
        tc_mutex_lock(g_sync1_mutex);
        tc_mutex_lock(g_sync_mutex);
        g_sync_param1 = sync_param1;
        g_sync_param2 = sync_param2;
        g_sync_func = sync_func;
        g_sync_command = 100;
        tc_mutex_unlock(g_sync_mutex);
        g_set_wait_obj(g_sync_event);

        do
        {
            g_sleep(100);
            tc_mutex_lock(g_sync_mutex);
            sync_command = g_sync_command;
            sync_result = g_sync_result;
            tc_mutex_unlock(g_sync_mutex);
        }
        while (sync_command != 0);

        tc_mutex_unlock(g_sync1_mutex);
    }

    return sync_result;
}
예제 #5
0
파일: xrdpwin.c 프로젝트: AsherBond/xrdp
int DEFAULT_CC
main(int argc, char **argv)
{
    int test;
    int host_be;
#if defined(_WIN32)
    WSADATA w;
    SC_HANDLE sc_man;
    SC_HANDLE sc_ser;
    int run_as_service;
    SERVICE_TABLE_ENTRY te[2];
#else
    int pid;
    int fd;
    int no_daemon;
    char text[256];
    char pid_file[256];
#endif

    g_init();
    ssl_init();
    /* check compiled endian with actual endian */
    test = 1;
    host_be = !((int)(*(unsigned char *)(&test)));
#if defined(B_ENDIAN)

    if (!host_be)
#endif
#if defined(L_ENDIAN)
        if (host_be)
#endif
        {
            g_writeln("endian wrong, edit arch.h");
            return 0;
        }

    /* check long, int and void* sizes */
    if (sizeof(int) != 4)
    {
        g_writeln("unusable int size, must be 4");
        return 0;
    }

    if (sizeof(long) != sizeof(void *))
    {
        g_writeln("long size must match void* size");
        return 0;
    }

    if (sizeof(long) != 4 && sizeof(long) != 8)
    {
        g_writeln("unusable long size, must be 4 or 8");
        return 0;
    }

    if (sizeof(tui64) != 8)
    {
        g_writeln("unusable tui64 size, must be 8");
        return 0;
    }

#if defined(_WIN32)
    run_as_service = 1;

    if (argc == 2)
    {
        if (g_strncasecmp(argv[1], "-help", 255) == 0 ||
                g_strncasecmp(argv[1], "--help", 255) == 0 ||
                g_strncasecmp(argv[1], "-h", 255) == 0)
        {
            g_writeln("");
            g_writeln("xrdp: A Remote Desktop Protocol server.");
            g_writeln("Copyright (C) Jay Sorg 2004-2011");
            g_writeln("See http://xrdp.sourceforge.net for more information.");
            g_writeln("");
            g_writeln("Usage: xrdp [options]");
            g_writeln("   -h: show help");
            g_writeln("   -install: install service");
            g_writeln("   -remove: remove service");
            g_writeln("");
            g_exit(0);
        }
        else if (g_strncasecmp(argv[1], "-install", 255) == 0 ||
                 g_strncasecmp(argv[1], "--install", 255) == 0 ||
                 g_strncasecmp(argv[1], "-i", 255) == 0)
        {
            /* open service manager */
            sc_man = OpenSCManager(0, 0, GENERIC_WRITE);

            if (sc_man == 0)
            {
                g_writeln("error OpenSCManager, do you have rights?");
                g_exit(0);
            }

            /* check if service is allready installed */
            sc_ser = OpenService(sc_man, "xrdp", SERVICE_ALL_ACCESS);

            if (sc_ser == 0)
            {
                /* install service */
                CreateService(sc_man, "xrdp", "xrdp", SERVICE_ALL_ACCESS,
                              SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START,
                              SERVICE_ERROR_IGNORE, "c:\\temp\\xrdp\\xrdp.exe",
                              0, 0, 0, 0, 0);

            }
            else
            {
                g_writeln("error service is allready installed");
                CloseServiceHandle(sc_ser);
                CloseServiceHandle(sc_man);
                g_exit(0);
            }

            CloseServiceHandle(sc_man);
            g_exit(0);
        }
        else if (g_strncasecmp(argv[1], "-remove", 255) == 0 ||
                 g_strncasecmp(argv[1], "--remove", 255) == 0 ||
                 g_strncasecmp(argv[1], "-r", 255) == 0)
        {
            /* open service manager */
            sc_man = OpenSCManager(0, 0, GENERIC_WRITE);

            if (sc_man == 0)
            {
                g_writeln("error OpenSCManager, do you have rights?");
                g_exit(0);
            }

            /* check if service is allready installed */
            sc_ser = OpenService(sc_man, "xrdp", SERVICE_ALL_ACCESS);

            if (sc_ser == 0)
            {
                g_writeln("error service is not installed");
                CloseServiceHandle(sc_man);
                g_exit(0);
            }

            DeleteService(sc_ser);
            CloseServiceHandle(sc_man);
            g_exit(0);
        }
        else
        {
            g_writeln("Unknown Parameter");
            g_writeln("xrdp -h for help");
            g_writeln("");
            g_exit(0);
        }
    }
    else if (argc > 1)
    {
        g_writeln("Unknown Parameter");
        g_writeln("xrdp -h for help");
        g_writeln("");
        g_exit(0);
    }

    if (run_as_service)
    {
        g_memset(&te, 0, sizeof(te));
        te[0].lpServiceName = "xrdp";
        te[0].lpServiceProc = MyServiceMain;
        StartServiceCtrlDispatcher(&te);
        g_exit(0);
    }

    WSAStartup(2, &w);
#else /* _WIN32 */
    g_snprintf(pid_file, 255, "%s/xrdp.pid", XRDP_PID_PATH);
    no_daemon = 0;

    if (argc == 2)
    {
        if ((g_strncasecmp(argv[1], "-kill", 255) == 0) ||
                (g_strncasecmp(argv[1], "--kill", 255) == 0) ||
                (g_strncasecmp(argv[1], "-k", 255) == 0))
        {
            g_writeln("stopping xrdp");
            /* read the xrdp.pid file */
            fd = -1;

            if (g_file_exist(pid_file)) /* xrdp.pid */
            {
                fd = g_file_open(pid_file); /* xrdp.pid */
            }

            if (fd == -1)
            {
                g_writeln("problem opening to xrdp.pid");
                g_writeln("maybe its not running");
            }
            else
            {
                g_memset(text, 0, 32);
                g_file_read(fd, text, 31);
                pid = g_atoi(text);
                g_writeln("stopping process id %d", pid);

                if (pid > 0)
                {
                    g_sigterm(pid);
                }

                g_file_close(fd);
            }

            g_exit(0);
        }
        else if (g_strncasecmp(argv[1], "-nodaemon", 255) == 0 ||
                 g_strncasecmp(argv[1], "--nodaemon", 255) == 0 ||
                 g_strncasecmp(argv[1], "-nd", 255) == 0 ||
                 g_strncasecmp(argv[1], "--nd", 255) == 0 ||
                 g_strncasecmp(argv[1], "-ns", 255) == 0 ||
                 g_strncasecmp(argv[1], "--ns", 255) == 0)
        {
            no_daemon = 1;
        }
        else if (g_strncasecmp(argv[1], "-help", 255) == 0 ||
                 g_strncasecmp(argv[1], "--help", 255) == 0 ||
                 g_strncasecmp(argv[1], "-h", 255) == 0)
        {
            g_writeln("");
            g_writeln("xrdp: A Remote Desktop Protocol server.");
            g_writeln("Copyright (C) Jay Sorg 2004-2011");
            g_writeln("See http://xrdp.sourceforge.net for more information.");
            g_writeln("");
            g_writeln("Usage: xrdp [options]");
            g_writeln("   -h: show help");
            g_writeln("   -nodaemon: don't fork into background");
            g_writeln("   -kill: shut down xrdp");
            g_writeln("");
            g_exit(0);
        }
        else if ((g_strncasecmp(argv[1], "-v", 255) == 0) ||
                 (g_strncasecmp(argv[1], "--version", 255) == 0))
        {
            g_writeln("");
            g_writeln("xrdp: A Remote Desktop Protocol server.");
            g_writeln("Copyright (C) Jay Sorg 2004-2011");
            g_writeln("See http://xrdp.sourceforge.net for more information.");
            g_writeln("Version %s", PACKAGE_VERSION);
            g_writeln("");
            g_exit(0);
        }
        else
        {
            g_writeln("Unknown Parameter");
            g_writeln("xrdp -h for help");
            g_writeln("");
            g_exit(0);
        }
    }
    else if (argc > 1)
    {
        g_writeln("Unknown Parameter");
        g_writeln("xrdp -h for help");
        g_writeln("");
        g_exit(0);
    }

    if (g_file_exist(pid_file)) /* xrdp.pid */
    {
        g_writeln("It looks like xrdp is allready running,");
        g_writeln("if not delete the xrdp.pid file and try again");
        g_exit(0);
    }

    if (!no_daemon)
    {
        /* make sure we can write to pid file */
        fd = g_file_open(pid_file); /* xrdp.pid */

        if (fd == -1)
        {
            g_writeln("running in daemon mode with no access to pid files, quitting");
            g_exit(0);
        }

        if (g_file_write(fd, "0", 1) == -1)
        {
            g_writeln("running in daemon mode with no access to pid files, quitting");
            g_exit(0);
        }

        g_file_close(fd);
        g_file_delete(pid_file);
    }

    if (!no_daemon)
    {
        /* start of daemonizing code */
        pid = g_fork();

        if (pid == -1)
        {
            g_writeln("problem forking");
            g_exit(1);
        }

        if (0 != pid)
        {
            g_writeln("process %d started ok", pid);
            /* exit, this is the main process */
            g_exit(0);
        }

        g_sleep(1000);
        g_file_close(0);
        g_file_close(1);
        g_file_close(2);
        g_file_open("/dev/null");
        g_file_open("/dev/null");
        g_file_open("/dev/null");
        /* end of daemonizing code */
    }

    if (!no_daemon)
    {
        /* write the pid to file */
        pid = g_getpid();
        fd = g_file_open(pid_file); /* xrdp.pid */

        if (fd == -1)
        {
            g_writeln("trying to write process id to xrdp.pid");
            g_writeln("problem opening xrdp.pid");
            g_writeln("maybe no rights");
        }
        else
        {
            g_sprintf(text, "%d", pid);
            g_file_write(fd, text, g_strlen(text));
            g_file_close(fd);
        }
    }

#endif
    g_threadid = tc_get_threadid();
    g_listen = xrdp_listen_create();
    g_signal_user_interrupt(xrdp_shutdown); /* SIGINT */
    g_signal_kill(xrdp_shutdown); /* SIGKILL */
    g_signal_pipe(pipe_sig); /* SIGPIPE */
    g_signal_terminate(xrdp_shutdown); /* SIGTERM */
    g_sync_mutex = tc_mutex_create();
    g_sync1_mutex = tc_mutex_create();
    pid = g_getpid();
    g_snprintf(text, 255, "xrdp_%8.8x_main_term", pid);
    g_term_event = g_create_wait_obj(text);
    g_snprintf(text, 255, "xrdp_%8.8x_main_sync", pid);
    g_sync_event = g_create_wait_obj(text);

    if (g_term_event == 0)
    {
        g_writeln("error creating g_term_event");
    }

    xrdp_listen_main_loop(g_listen);
    xrdp_listen_delete(g_listen);
    tc_mutex_delete(g_sync_mutex);
    tc_mutex_delete(g_sync1_mutex);
    g_delete_wait_obj(g_term_event);
    g_delete_wait_obj(g_sync_event);
#if defined(_WIN32)
    /* I don't think it ever gets here */
    /* when running in win32 app mode, control c exits right away */
    WSACleanup();
#else
    /* delete the xrdp.pid file */
    g_file_delete(pid_file);
#endif
    return 0;
}
예제 #6
0
파일: xrdpwin.c 프로젝트: AsherBond/xrdp
VOID WINAPI
MyServiceMain(DWORD dwArgc, LPTSTR *lpszArgv)
{
    WSADATA w;
    char text[256];
    int pid;
    //HANDLE event_han;
    //  int fd;
    //  char text[256];

    //  fd = g_file_open("c:\\temp\\xrdp\\log.txt");
    //  g_file_write(fd, "hi\r\n", 4);
    //event_han = RegisterEventSource(0, "xrdp");
    //log_event(event_han, "hi xrdp log");
    g_threadid = tc_get_threadid();
    g_set_current_dir("c:\\temp\\xrdp");
    g_listen = 0;
    WSAStartup(2, &w);
    g_sync_mutex = tc_mutex_create();
    g_sync1_mutex = tc_mutex_create();
    pid = g_getpid();
    g_snprintf(text, 255, "xrdp_%8.8x_main_term", pid);
    g_term_event = g_create_wait_obj(text);
    g_snprintf(text, 255, "xrdp_%8.8x_main_sync", pid);
    g_sync_event = g_create_wait_obj(text);
    g_memset(&g_service_status, 0, sizeof(SERVICE_STATUS));
    g_service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    g_service_status.dwCurrentState = SERVICE_RUNNING;
    g_service_status.dwControlsAccepted = SERVICE_CONTROL_INTERROGATE |
                                          SERVICE_ACCEPT_STOP |
                                          SERVICE_ACCEPT_SHUTDOWN;
    g_service_status.dwWin32ExitCode = NO_ERROR;
    g_service_status.dwServiceSpecificExitCode = 0;
    g_service_status.dwCheckPoint = 0;
    g_service_status.dwWaitHint = 0;
    //  g_sprintf(text, "calling RegisterServiceCtrlHandler\r\n");
    //  g_file_write(fd, text, g_strlen(text));
    g_ssh = RegisterServiceCtrlHandler("xrdp", MyHandler);

    if (g_ssh != 0)
    {
        //    g_sprintf(text, "ok\r\n");
        //    g_file_write(fd, text, g_strlen(text));
        SetServiceStatus(g_ssh, &g_service_status);
        g_listen = xrdp_listen_create();
        xrdp_listen_main_loop(g_listen);
        g_sleep(100);
        g_service_status.dwCurrentState = SERVICE_STOPPED;
        SetServiceStatus(g_ssh, &g_service_status);
    }
    else
    {
        //g_sprintf(text, "RegisterServiceCtrlHandler failed\r\n");
        //g_file_write(fd, text, g_strlen(text));
    }

    xrdp_listen_delete(g_listen);
    tc_mutex_delete(g_sync_mutex);
    tc_mutex_delete(g_sync1_mutex);
    g_destroy_wait_obj(g_term_event);
    g_destroy_wait_obj(g_sync_event);
    WSACleanup();
    //CloseHandle(event_han);
}
예제 #7
0
파일: xrdp.c 프로젝트: dlinz/xrdp-ng
int main(int argc, char **argv)
{
	int fd;
	int pid;
	int no_daemon;
	char text[256];
	char pid_file[256];
	char cfg_file[256];
	enum logReturns error;
	xrdpStartupParams* startup_params;

	g_init("xrdp");

	g_snprintf(cfg_file, 255, "%s/xrdp.ini", XRDP_CFG_PATH);

	/* starting logging subsystem */
	error = log_start(cfg_file, "XRDP");

	if (error != LOG_STARTUP_OK)
	{
		switch (error)
		{
			case LOG_ERROR_MALLOC:
				g_writeln("error on malloc. cannot start logging. quitting.");
				break;

			case LOG_ERROR_FILE_OPEN:
				g_writeln("error opening log file [%s]. quitting.", getLogFile(text, 255));
				break;

			default:
				g_writeln("log_start error");
				break;
		}

		g_deinit();
		g_exit(1);
	}

	startup_params = (xrdpStartupParams *) g_malloc(sizeof(xrdpStartupParams), 1);

	if (xrdp_process_params(argc, argv, startup_params) != 0)
	{
		g_writeln("Unknown Parameter");
		g_writeln("xrdp -h for help");
		g_writeln("");
		g_deinit();
		g_exit(0);
	}

	g_snprintf(pid_file, 255, "%s/xrdp-ng.pid", XRDP_PID_PATH);
	no_daemon = 0;

	if (startup_params->kill)
	{
		g_writeln("stopping xrdp");
		/* read the xrdp.pid file */
		fd = -1;

		if (g_file_exist(pid_file)) /* xrdp-ng.pid */
		{
			fd = g_file_open(pid_file); /* xrdp-ng.pid */
		}

		if (fd == -1)
		{
			g_writeln("problem opening to xrdp-ng.pid [%s]", pid_file);
			g_writeln("maybe its not running");
		}
		else
		{
			g_memset(text, 0, 32);
			g_file_read(fd, (unsigned char*) text, 31);
			pid = g_atoi(text);
			g_writeln("stopping process id %d", pid);

			if (pid > 0)
			{
				g_sigterm(pid);
			}

			g_file_close(fd);
		}

		g_deinit();
		g_exit(0);
	}

	if (startup_params->no_daemon)
	{
		no_daemon = 1;
	}

	if (startup_params->help)
	{
		g_writeln("");
		g_writeln("xrdp: A Remote Desktop Protocol server.");
		g_writeln("Copyright (C) Jay Sorg 2004-2011");
		g_writeln("See http://xrdp.sourceforge.net for more information.");
		g_writeln("");
		g_writeln("Usage: xrdp [options]");
		g_writeln("   --help: show help");
		g_writeln("   --nodaemon: don't fork into background");
		g_writeln("   --kill: shut down xrdp");
		g_writeln("   --port: tcp listen port");
		g_writeln("   --fork: fork on new connection");
		g_writeln("");
		g_deinit();
		g_exit(0);
	}

	if (startup_params->version)
	{
		g_writeln("");
		g_writeln("xrdp: A Remote Desktop Protocol server.");
		g_writeln("Copyright (C) Jay Sorg 2004-2011");
		g_writeln("See http://xrdp.sourceforge.net for more information.");
		g_writeln("Version %s", XRDP_NG_VERSION_FULL);
		g_writeln("");
		g_deinit();
		g_exit(0);
	}

	if (g_file_exist(pid_file)) /* xrdp-ng.pid */
	{
		g_writeln("It looks like xrdp is already running,");
		g_writeln("if not delete the xrdp-ng.pid file and try again");
		g_deinit();
		g_exit(0);
	}

	if (!no_daemon)
	{

		/* make sure containing directory exists */
		g_create_path(pid_file);

		/* make sure we can write to pid file */
		fd = g_file_open(pid_file); /* xrdp-ng.pid */

		if (fd == -1)
		{
			g_writeln("running in daemon mode with no access to pid files, quitting");
			g_deinit();
			g_exit(0);
		}

		if (g_file_write(fd, (unsigned char*) "0", 1) == -1)
		{
			g_writeln("running in daemon mode with no access to pid files, quitting");
			g_deinit();
			g_exit(0);
		}

		g_file_close(fd);
		g_file_delete(pid_file);
	}

	if (!no_daemon)
	{
		/* start of daemonizing code */
		pid = g_fork();

		if (pid == -1)
		{
			g_writeln("problem forking");
			g_deinit();
			g_exit(1);
		}

		if (0 != pid)
		{
			g_writeln("process %d started ok", pid);
			/* exit, this is the main process */
			g_deinit();
			g_exit(0);
		}

		g_sleep(1000);
		/* write the pid to file */
		pid = g_getpid();
		fd = g_file_open(pid_file); /* xrdp-ng.pid */

		if (fd == -1)
		{
			g_writeln("trying to write process id to xrdp-ng.pid");
			g_writeln("problem opening xrdp-ng.pid");
			g_writeln("maybe no rights");
		}
		else
		{
			g_sprintf(text, "%d", pid);
			g_file_write(fd, (unsigned char*) text, g_strlen(text));
			g_file_close(fd);
		}

		g_sleep(1000);
		g_file_close(0);
		g_file_close(1);
		g_file_close(2);
		g_file_open("/dev/null");
		g_file_open("/dev/null");
		g_file_open("/dev/null");
		/* end of daemonizing code */
	}

	g_threadid = tc_get_threadid();
	g_listen = xrdp_listen_create();
	g_signal_user_interrupt(xrdp_shutdown); /* SIGINT */
	g_signal_kill(xrdp_shutdown); /* SIGKILL */
	g_signal_pipe(pipe_sig); /* SIGPIPE */
	g_signal_terminate(xrdp_shutdown); /* SIGTERM */
	g_signal_child_stop(xrdp_child); /* SIGCHLD */
	g_sync_mutex = tc_mutex_create();
	g_sync1_mutex = tc_mutex_create();
	pid = g_getpid();

	g_TermEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	g_SyncEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

	xrdp_listen_main_loop(g_listen);
	xrdp_listen_delete(g_listen);

	tc_mutex_delete(g_sync_mutex);
	tc_mutex_delete(g_sync1_mutex);

	CloseHandle(g_TermEvent);
	CloseHandle(g_SyncEvent);

	/* only main process should delete pid file */
	if ((!no_daemon) && (pid == g_getpid()))
	{
		/* delete the xrdp-ng.pid file */
		g_file_delete(pid_file);
	}

	free(startup_params);
	g_deinit();

	return 0;
}
예제 #8
0
파일: log.c 프로젝트: speidy/xrdp
enum logReturns DEFAULT_CC
log_message(const enum logLevels lvl, const char *msg, ...)
{
    char buff[LOG_BUFFER_SIZE + 31]; /* 19 (datetime) 4 (space+cr+lf+\0) */
    va_list ap;
    int len = 0;
    enum logReturns rv = LOG_STARTUP_OK;
    int writereply = 0;
    time_t now_t;
    struct tm *now;

    if (g_staticLogConfig == NULL)
    {
        g_writeln("The log reference is NULL - log not initialized properly");
        return LOG_ERROR_NO_CFG;
    }

    if (0 > g_staticLogConfig->fd && g_staticLogConfig->enable_syslog == 0)
    {
        return LOG_ERROR_FILE_NOT_OPEN;
    }

    now_t = time(&now_t);
    now = localtime(&now_t);

    snprintf(buff, 21, "[%.4d%.2d%.2d-%.2d:%.2d:%.2d] ", now->tm_year + 1900,
             now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min,
             now->tm_sec);

    internal_log_lvl2str(lvl, buff + 20);

    va_start(ap, msg);
    len = vsnprintf(buff + 28, LOG_BUFFER_SIZE, msg, ap);
    va_end(ap);

    /* checking for truncated messages */
    if (len > LOG_BUFFER_SIZE)
    {
        log_message(LOG_LEVEL_WARNING, "next message will be truncated");
    }

    /* forcing the end of message string */
#ifdef _WIN32
    buff[len + 28] = '\r';
    buff[len + 29] = '\n';
    buff[len + 30] = '\0';
#else
#ifdef _MACOS
    buff[len + 28] = '\r';
    buff[len + 29] = '\0';
#else
    buff[len + 28] = '\n';
    buff[len + 29] = '\0';
#endif
#endif

    if (g_staticLogConfig->enable_syslog && (lvl <= g_staticLogConfig->syslog_level))
    {
        /* log to syslog*/
        /* %s fix compiler warning 'not a string literal' */
        syslog(internal_log_xrdp2syslog(lvl), "(%d)(%ld)%s", g_getpid(),
               tc_get_threadid(), buff + 20);
    }

    if (lvl <= g_staticLogConfig->log_level)
    {
        /* log to console */
        g_printf("%s", buff);

        /* log to application logfile */
#ifdef LOG_ENABLE_THREAD
        pthread_mutex_lock(&(g_staticLogConfig->log_lock));
#endif

        if (g_staticLogConfig->fd > 0)
        {
            writereply = g_file_write(g_staticLogConfig->fd, buff, g_strlen(buff));

            if (writereply <= 0)
            {
                rv = LOG_ERROR_NULL_FILE;
            }
        }

#ifdef LOG_ENABLE_THREAD
        pthread_mutex_unlock(&(g_staticLogConfig->log_lock));
#endif
    }

    return rv;
}