1 /**
2 * xrdp: A Remote Desktop Protocol server.
3 *
4 * Copyright (C) Jay Sorg 2004-2014
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * main program
19 */
20
21 #if defined(HAVE_CONFIG_H)
22 #include <config_ac.h>
23 #endif
24
25 #if defined(_WIN32)
26 #include <windows.h>
27 #endif
28 #include "xrdp.h"
29
30 static struct xrdp_listen *g_listen = 0;
31 static long g_threadid = 0; /* main threadid */
32
33 #if defined(_WIN32)
34 static SERVICE_STATUS_HANDLE g_ssh = 0;
35 static SERVICE_STATUS g_service_status;
36 #endif
37 static long g_sync_mutex = 0;
38 static long g_sync1_mutex = 0;
39 static tbus g_term_event = 0;
40 static tbus g_sync_event = 0;
41 /* synchronize stuff */
42 static int g_sync_command = 0;
43 static long g_sync_result = 0;
44 static long g_sync_param1 = 0;
45 static long g_sync_param2 = 0;
46 static long (*g_sync_func)(long param1, long param2);
47
48 /*****************************************************************************/
49 long
g_xrdp_sync(long (* sync_func)(long param1,long param2),long sync_param1,long sync_param2)50 g_xrdp_sync(long (*sync_func)(long param1, long param2), long sync_param1,
51 long sync_param2)
52 {
53 long sync_result;
54 int sync_command;
55
56 if (tc_threadid_equal(tc_get_threadid(), g_threadid))
57 {
58 /* this is the main thread, call the function directly */
59 sync_result = sync_func(sync_param1, sync_param2);
60 }
61 else
62 {
63 tc_mutex_lock(g_sync1_mutex);
64 tc_mutex_lock(g_sync_mutex);
65 g_sync_param1 = sync_param1;
66 g_sync_param2 = sync_param2;
67 g_sync_func = sync_func;
68 g_sync_command = 100;
69 tc_mutex_unlock(g_sync_mutex);
70 g_set_wait_obj(g_sync_event);
71
72 do
73 {
74 g_sleep(100);
75 tc_mutex_lock(g_sync_mutex);
76 sync_command = g_sync_command;
77 sync_result = g_sync_result;
78 tc_mutex_unlock(g_sync_mutex);
79 }
80 while (sync_command != 0);
81
82 tc_mutex_unlock(g_sync1_mutex);
83 }
84
85 return sync_result;
86 }
87
88 /*****************************************************************************/
89 void
xrdp_shutdown(int sig)90 xrdp_shutdown(int sig)
91 {
92 tbus threadid;
93
94 threadid = tc_get_threadid();
95 g_writeln("shutting down");
96 g_writeln("signal %d threadid %p", sig, threadid);
97
98 if (!g_is_wait_obj_set(g_term_event))
99 {
100 g_set_wait_obj(g_term_event);
101 }
102 }
103
104 /*****************************************************************************/
105 int
g_is_term(void)106 g_is_term(void)
107 {
108 return g_is_wait_obj_set(g_term_event);
109 }
110
111 /*****************************************************************************/
112 void
g_set_term(int in_val)113 g_set_term(int in_val)
114 {
115 if (in_val)
116 {
117 g_set_wait_obj(g_term_event);
118 }
119 else
120 {
121 g_reset_wait_obj(g_term_event);
122 }
123 }
124
125 /*****************************************************************************/
126 tbus
g_get_term_event(void)127 g_get_term_event(void)
128 {
129 return g_term_event;
130 }
131
132 /*****************************************************************************/
133 tbus
g_get_sync_event(void)134 g_get_sync_event(void)
135 {
136 return g_sync_event;
137 }
138
139 /*****************************************************************************/
140 void
pipe_sig(int sig_num)141 pipe_sig(int sig_num)
142 {
143 /* do nothing */
144 g_writeln("got XRDP WIN SIGPIPE(%d)", sig_num);
145 }
146
147 /*****************************************************************************/
148 void
g_process_waiting_function(void)149 g_process_waiting_function(void)
150 {
151 tc_mutex_lock(g_sync_mutex);
152
153 if (g_sync_command != 0)
154 {
155 if (g_sync_func != 0)
156 {
157 if (g_sync_command == 100)
158 {
159 g_sync_result = g_sync_func(g_sync_param1, g_sync_param2);
160 }
161 }
162
163 g_sync_command = 0;
164 }
165
166 tc_mutex_unlock(g_sync_mutex);
167 }
168
169 /* win32 service control functions */
170 #if defined(_WIN32)
171
172 /*****************************************************************************/
173 VOID WINAPI
MyHandler(DWORD fdwControl)174 MyHandler(DWORD fdwControl)
175 {
176 if (g_ssh == 0)
177 {
178 return;
179 }
180
181 if (fdwControl == SERVICE_CONTROL_STOP)
182 {
183 g_service_status.dwCurrentState = SERVICE_STOP_PENDING;
184 g_set_term(1);
185 }
186 else if (fdwControl == SERVICE_CONTROL_PAUSE)
187 {
188 /* shouldn't happen */
189 }
190 else if (fdwControl == SERVICE_CONTROL_CONTINUE)
191 {
192 /* shouldn't happen */
193 }
194 else if (fdwControl == SERVICE_CONTROL_INTERROGATE)
195 {
196 }
197 else if (fdwControl == SERVICE_CONTROL_SHUTDOWN)
198 {
199 g_service_status.dwCurrentState = SERVICE_STOP_PENDING;
200 g_set_term(1);
201 }
202
203 SetServiceStatus(g_ssh, &g_service_status);
204 }
205
206 /*****************************************************************************/
207 static void
log_event(HANDLE han,char * msg)208 log_event(HANDLE han, char *msg)
209 {
210 ReportEvent(han, EVENTLOG_INFORMATION_TYPE, 0, 0, 0, 1, 0, &msg, 0);
211 }
212
213 /*****************************************************************************/
214 VOID WINAPI
MyServiceMain(DWORD dwArgc,LPTSTR * lpszArgv)215 MyServiceMain(DWORD dwArgc, LPTSTR *lpszArgv)
216 {
217 WSADATA w;
218 char text[256];
219 int pid;
220 //HANDLE event_han;
221 // int fd;
222 // char text[256];
223
224 // fd = g_file_open("c:\\temp\\xrdp\\log.txt");
225 // g_file_write(fd, "hi\r\n", 4);
226 //event_han = RegisterEventSource(0, "xrdp");
227 //log_event(event_han, "hi xrdp log");
228 g_threadid = tc_get_threadid();
229 g_set_current_dir("c:\\temp\\xrdp");
230 g_listen = 0;
231 WSAStartup(2, &w);
232 g_sync_mutex = tc_mutex_create();
233 g_sync1_mutex = tc_mutex_create();
234 pid = g_getpid();
235 g_snprintf(text, 255, "xrdp_%8.8x_main_term", pid);
236 g_term_event = g_create_wait_obj(text);
237 g_snprintf(text, 255, "xrdp_%8.8x_main_sync", pid);
238 g_sync_event = g_create_wait_obj(text);
239 g_memset(&g_service_status, 0, sizeof(SERVICE_STATUS));
240 g_service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
241 g_service_status.dwCurrentState = SERVICE_RUNNING;
242 g_service_status.dwControlsAccepted = SERVICE_CONTROL_INTERROGATE |
243 SERVICE_ACCEPT_STOP |
244 SERVICE_ACCEPT_SHUTDOWN;
245 g_service_status.dwWin32ExitCode = NO_ERROR;
246 g_service_status.dwServiceSpecificExitCode = 0;
247 g_service_status.dwCheckPoint = 0;
248 g_service_status.dwWaitHint = 0;
249 // g_sprintf(text, "calling RegisterServiceCtrlHandler\r\n");
250 // g_file_write(fd, text, g_strlen(text));
251 g_ssh = RegisterServiceCtrlHandler("xrdp", MyHandler);
252
253 if (g_ssh != 0)
254 {
255 // g_sprintf(text, "ok\r\n");
256 // g_file_write(fd, text, g_strlen(text));
257 SetServiceStatus(g_ssh, &g_service_status);
258 g_listen = xrdp_listen_create();
259 xrdp_listen_main_loop(g_listen);
260 g_sleep(100);
261 g_service_status.dwCurrentState = SERVICE_STOPPED;
262 SetServiceStatus(g_ssh, &g_service_status);
263 }
264 else
265 {
266 //g_sprintf(text, "RegisterServiceCtrlHandler failed\r\n");
267 //g_file_write(fd, text, g_strlen(text));
268 }
269
270 xrdp_listen_delete(g_listen);
271 tc_mutex_delete(g_sync_mutex);
272 tc_mutex_delete(g_sync1_mutex);
273 g_destroy_wait_obj(g_term_event);
274 g_destroy_wait_obj(g_sync_event);
275 WSACleanup();
276 //CloseHandle(event_han);
277 }
278
279 #endif
280 /*****************************************************************************/
281 int
main(int argc,char ** argv)282 main(int argc, char **argv)
283 {
284 int test;
285 int host_be;
286 #if defined(_WIN32)
287 WSADATA w;
288 SC_HANDLE sc_man;
289 SC_HANDLE sc_ser;
290 int run_as_service;
291 SERVICE_TABLE_ENTRY te[2];
292 #else
293 int pid;
294 int fd;
295 int no_daemon;
296 char text[256];
297 char pid_file[256];
298 #endif
299
300 g_init();
301 ssl_init();
302 /* check compiled endian with actual endian */
303 test = 1;
304 host_be = !((int)(*(unsigned char *)(&test)));
305 #if defined(B_ENDIAN)
306
307 if (!host_be)
308 #endif
309 #if defined(L_ENDIAN)
310 if (host_be)
311 #endif
312 {
313 g_writeln("endian wrong, edit arch.h");
314 return 0;
315 }
316
317 /* check long, int and void* sizes */
318 if (sizeof(int) != 4)
319 {
320 g_writeln("unusable int size, must be 4");
321 return 0;
322 }
323
324 if (sizeof(long) != sizeof(void *))
325 {
326 g_writeln("long size must match void* size");
327 return 0;
328 }
329
330 if (sizeof(long) != 4 && sizeof(long) != 8)
331 {
332 g_writeln("unusable long size, must be 4 or 8");
333 return 0;
334 }
335
336 if (sizeof(tui64) != 8)
337 {
338 g_writeln("unusable tui64 size, must be 8");
339 return 0;
340 }
341
342 #if defined(_WIN32)
343 run_as_service = 1;
344
345 if (argc == 2)
346 {
347 if (g_strncasecmp(argv[1], "-help", 255) == 0 ||
348 g_strncasecmp(argv[1], "--help", 255) == 0 ||
349 g_strncasecmp(argv[1], "-h", 255) == 0)
350 {
351 g_writeln("%s", "");
352 g_writeln("xrdp: A Remote Desktop Protocol server.");
353 g_writeln("Copyright (C) Jay Sorg 2004-2011");
354 g_writeln("See http://www.xrdp.org for more information.");
355 g_writeln("%s", "");
356 g_writeln("Usage: xrdp [options]");
357 g_writeln(" -h: show help");
358 g_writeln(" -install: install service");
359 g_writeln(" -remove: remove service");
360 g_writeln("%s", "");
361 g_exit(0);
362 }
363 else if (g_strncasecmp(argv[1], "-install", 255) == 0 ||
364 g_strncasecmp(argv[1], "--install", 255) == 0 ||
365 g_strncasecmp(argv[1], "-i", 255) == 0)
366 {
367 /* open service manager */
368 sc_man = OpenSCManager(0, 0, GENERIC_WRITE);
369
370 if (sc_man == 0)
371 {
372 g_writeln("error OpenSCManager, do you have rights?");
373 g_exit(0);
374 }
375
376 /* check if service is already installed */
377 sc_ser = OpenService(sc_man, "xrdp", SERVICE_ALL_ACCESS);
378
379 if (sc_ser == 0)
380 {
381 /* install service */
382 CreateService(sc_man, "xrdp", "xrdp", SERVICE_ALL_ACCESS,
383 SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START,
384 SERVICE_ERROR_IGNORE, "c:\\temp\\xrdp\\xrdp.exe",
385 0, 0, 0, 0, 0);
386
387 }
388 else
389 {
390 g_writeln("error service is already installed");
391 CloseServiceHandle(sc_ser);
392 CloseServiceHandle(sc_man);
393 g_exit(0);
394 }
395
396 CloseServiceHandle(sc_man);
397 g_exit(0);
398 }
399 else if (g_strncasecmp(argv[1], "-remove", 255) == 0 ||
400 g_strncasecmp(argv[1], "--remove", 255) == 0 ||
401 g_strncasecmp(argv[1], "-r", 255) == 0)
402 {
403 /* open service manager */
404 sc_man = OpenSCManager(0, 0, GENERIC_WRITE);
405
406 if (sc_man == 0)
407 {
408 g_writeln("error OpenSCManager, do you have rights?");
409 g_exit(0);
410 }
411
412 /* check if service is already installed */
413 sc_ser = OpenService(sc_man, "xrdp", SERVICE_ALL_ACCESS);
414
415 if (sc_ser == 0)
416 {
417 g_writeln("error service is not installed");
418 CloseServiceHandle(sc_man);
419 g_exit(0);
420 }
421
422 DeleteService(sc_ser);
423 CloseServiceHandle(sc_man);
424 g_exit(0);
425 }
426 else
427 {
428 g_writeln("Unknown Parameter");
429 g_writeln("xrdp -h for help");
430 g_writeln("%s", "");
431 g_exit(0);
432 }
433 }
434 else if (argc > 1)
435 {
436 g_writeln("Unknown Parameter");
437 g_writeln("xrdp -h for help");
438 g_writeln("%s", "");
439 g_exit(0);
440 }
441
442 if (run_as_service)
443 {
444 g_memset(&te, 0, sizeof(te));
445 te[0].lpServiceName = "xrdp";
446 te[0].lpServiceProc = MyServiceMain;
447 StartServiceCtrlDispatcher(&te);
448 g_exit(0);
449 }
450
451 WSAStartup(2, &w);
452 #else /* _WIN32 */
453 g_snprintf(pid_file, 255, "%s/xrdp.pid", XRDP_PID_PATH);
454 no_daemon = 0;
455
456 if (argc == 2)
457 {
458 if ((g_strncasecmp(argv[1], "-kill", 255) == 0) ||
459 (g_strncasecmp(argv[1], "--kill", 255) == 0) ||
460 (g_strncasecmp(argv[1], "-k", 255) == 0))
461 {
462 g_writeln("stopping xrdp");
463 /* read the xrdp.pid file */
464 fd = -1;
465
466 if (g_file_exist(pid_file)) /* xrdp.pid */
467 {
468 fd = g_file_open(pid_file); /* xrdp.pid */
469 }
470
471 if (fd == -1)
472 {
473 g_writeln("cannot open %s, maybe xrdp is not running",
474 pid_file);
475 }
476 else
477 {
478 g_memset(text, 0, 32);
479 g_file_read(fd, text, 31);
480 pid = g_atoi(text);
481 g_writeln("stopping process id %d", pid);
482
483 if (pid > 0)
484 {
485 g_sigterm(pid);
486 }
487
488 g_file_close(fd);
489 }
490
491 g_exit(0);
492 }
493 else if (g_strncasecmp(argv[1], "-nodaemon", 255) == 0 ||
494 g_strncasecmp(argv[1], "--nodaemon", 255) == 0 ||
495 g_strncasecmp(argv[1], "-nd", 255) == 0 ||
496 g_strncasecmp(argv[1], "--nd", 255) == 0 ||
497 g_strncasecmp(argv[1], "-ns", 255) == 0 ||
498 g_strncasecmp(argv[1], "--ns", 255) == 0)
499 {
500 no_daemon = 1;
501 }
502 else if (g_strncasecmp(argv[1], "-help", 255) == 0 ||
503 g_strncasecmp(argv[1], "--help", 255) == 0 ||
504 g_strncasecmp(argv[1], "-h", 255) == 0)
505 {
506 g_writeln("%s", "");
507 g_writeln("xrdp: A Remote Desktop Protocol server.");
508 g_writeln("Copyright (C) Jay Sorg 2004-2011");
509 g_writeln("See http://www.xrdp.org for more information.");
510 g_writeln("%s", "");
511 g_writeln("Usage: xrdp [options]");
512 g_writeln(" -h: show help");
513 g_writeln(" -nodaemon: don't fork into background");
514 g_writeln(" -kill: shut down xrdp");
515 g_writeln("%s", "");
516 g_exit(0);
517 }
518 else if ((g_strncasecmp(argv[1], "-v", 255) == 0) ||
519 (g_strncasecmp(argv[1], "--version", 255) == 0))
520 {
521 g_writeln("%s", "");
522 g_writeln("xrdp: A Remote Desktop Protocol server.");
523 g_writeln("Copyright (C) Jay Sorg 2004-2011");
524 g_writeln("See http://www.xrdp.org for more information.");
525 g_writeln("Version %s", PACKAGE_VERSION);
526 g_writeln("%s", "");
527 g_exit(0);
528 }
529 else
530 {
531 g_writeln("Unknown Parameter");
532 g_writeln("xrdp -h for help");
533 g_writeln("%s", "");
534 g_exit(0);
535 }
536 }
537 else if (argc > 1)
538 {
539 g_writeln("Unknown Parameter");
540 g_writeln("xrdp -h for help");
541 g_writeln("%s", "");
542 g_exit(0);
543 }
544
545 if (g_file_exist(pid_file)) /* xrdp.pid */
546 {
547 g_writeln("It looks like xrdp is already running.");
548 g_writeln("If not, delete %s and try again.", pid_file);
549 g_exit(0);
550 }
551
552 if (!no_daemon)
553 {
554 /* make sure we can write to pid file */
555 fd = g_file_open(pid_file); /* xrdp.pid */
556
557 if (fd == -1)
558 {
559 g_writeln("running in daemon mode with no access to pid files, quitting");
560 g_exit(0);
561 }
562
563 if (g_file_write(fd, "0", 1) == -1)
564 {
565 g_writeln("running in daemon mode with no access to pid files, quitting");
566 g_exit(0);
567 }
568
569 g_file_close(fd);
570 g_file_delete(pid_file);
571 }
572
573 if (!no_daemon)
574 {
575 /* start of daemonizing code */
576 pid = g_fork();
577
578 if (pid == -1)
579 {
580 g_writeln("problem forking");
581 g_exit(1);
582 }
583
584 if (0 != pid)
585 {
586 g_writeln("process %d started ok", pid);
587 /* exit, this is the main process */
588 g_exit(0);
589 }
590
591 g_sleep(1000);
592 g_file_close(0);
593 g_file_close(1);
594 g_file_close(2);
595 g_file_open("/dev/null");
596 g_file_open("/dev/null");
597 g_file_open("/dev/null");
598 /* end of daemonizing code */
599 }
600
601 if (!no_daemon)
602 {
603 /* write the pid to file */
604 pid = g_getpid();
605 fd = g_file_open(pid_file); /* xrdp.pid */
606
607 if (fd == -1)
608 {
609 g_writeln("trying to write process id to xrdp.pid");
610 g_writeln("problem opening xrdp.pid");
611 g_writeln("maybe no rights");
612 }
613 else
614 {
615 g_sprintf(text, "%d", pid);
616 g_file_write(fd, text, g_strlen(text));
617 g_file_close(fd);
618 }
619 }
620
621 #endif
622 g_threadid = tc_get_threadid();
623 g_listen = xrdp_listen_create();
624 g_signal_user_interrupt(xrdp_shutdown); /* SIGINT */
625 g_signal_pipe(pipe_sig); /* SIGPIPE */
626 g_signal_terminate(xrdp_shutdown); /* SIGTERM */
627 g_sync_mutex = tc_mutex_create();
628 g_sync1_mutex = tc_mutex_create();
629 pid = g_getpid();
630 g_snprintf(text, 255, "xrdp_%8.8x_main_term", pid);
631 g_term_event = g_create_wait_obj(text);
632 g_snprintf(text, 255, "xrdp_%8.8x_main_sync", pid);
633 g_sync_event = g_create_wait_obj(text);
634
635 if (g_term_event == 0)
636 {
637 g_writeln("error creating g_term_event");
638 }
639
640 xrdp_listen_main_loop(g_listen);
641 xrdp_listen_delete(g_listen);
642 tc_mutex_delete(g_sync_mutex);
643 tc_mutex_delete(g_sync1_mutex);
644 g_delete_wait_obj(g_term_event);
645 g_delete_wait_obj(g_sync_event);
646 #if defined(_WIN32)
647 /* I don't think it ever gets here */
648 /* when running in win32 app mode, control c exits right away */
649 WSACleanup();
650 #else
651 /* delete the xrdp.pid file */
652 g_file_delete(pid_file);
653 #endif
654 return 0;
655 }
656