1 /*
2    Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com>
3    All rights reserved.
4 
5 This file is part of x11vnc.
6 
7 x11vnc is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or (at
10 your option) any later version.
11 
12 x11vnc is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with x11vnc; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
20 or see <http://www.gnu.org/licenses/>.
21 
22 In addition, as a special exception, Karl J. Runge
23 gives permission to link the code of its release of x11vnc with the
24 OpenSSL project's "OpenSSL" library (or with modified versions of it
25 that use the same license as the "OpenSSL" library), and distribute
26 the linked executables.  You must obey the GNU General Public License
27 in all respects for all of the code used other than "OpenSSL".  If you
28 modify this file, you may extend this exception to your version of the
29 file, but you are not obligated to do so.  If you do not wish to do
30 so, delete this exception statement from your version.
31 */
32 
33 /* -- cleanup.c -- */
34 
35 #include "x11vnc.h"
36 #include "xwrappers.h"
37 #include "xdamage.h"
38 #include "remote.h"
39 #include "keyboard.h"
40 #include "scan.h"
41 #include "gui.h"
42 #include "solid.h"
43 #include "unixpw.h"
44 #include "sslcmds.h"
45 #include "sslhelper.h"
46 #include "connections.h"
47 #include "macosx.h"
48 #include "macosxCG.h"
49 #include "avahi.h"
50 #include "screen.h"
51 #include "xrecord.h"
52 #include "xevents.h"
53 #include "uinput.h"
54 
55 /*
56  * Exiting and error handling routines
57  */
58 
59 int trapped_xerror = 0;
60 int trapped_xioerror = 0;
61 int trapped_getimage_xerror = 0;
62 int trapped_record_xerror = 0;
63 XErrorEvent *trapped_xerror_event;
64 
65 /* XXX CHECK BEFORE RELEASE */
66 int crash_debug = 0;
67 
68 void clean_shm(int quick);
69 void clean_up_exit(int ret);
70 int trap_xerror(Display *d, XErrorEvent *error);
71 int trap_xioerror(Display *d);
72 int trap_getimage_xerror(Display *d, XErrorEvent *error);
73 char *xerror_string(XErrorEvent *error);
74 void initialize_crash_handler(void);
75 void initialize_signals(void);
76 void unset_signals(void);
77 void close_exec_fds(void);
78 int known_sigpipe_mode(char *s);
79 
80 
81 static int exit_flag = 0;
82 static int exit_sig = 0;
83 
84 static void clean_icon_mode(void);
85 static int Xerror(Display *d, XErrorEvent *error);
86 static int XIOerr(Display *d);
87 static void crash_shell_help(void);
88 static void crash_shell(void);
89 static void interrupted (int sig);
90 
91 
clean_shm(int quick)92 void clean_shm(int quick) {
93 	int i, cnt = 0;
94 
95 	/*
96 	 * to avoid deadlock, etc, under quick=1 we just delete the shm
97 	 * areas and leave the X stuff hanging.
98 	 */
99 	if (quick) {
100 		shm_delete(&scanline_shm);
101 		shm_delete(&fullscreen_shm);
102 		shm_delete(&snaprect_shm);
103 	} else {
104 		shm_clean(&scanline_shm, scanline);
105 		shm_clean(&fullscreen_shm, fullscreen);
106 		shm_clean(&snaprect_shm, snaprect);
107 	}
108 
109 	/*
110 	 * Here we have to clean up quite a few shm areas for all
111 	 * the possible tile row runs (40 for 1280), not as robust
112 	 * as one might like... sometimes need to run ipcrm(1).
113 	 */
114 	for(i=1; i<=ntiles_x; i++) {
115 		if (i > tile_shm_count) {
116 			break;
117 		}
118 		if (quick) {
119 			shm_delete(&tile_row_shm[i]);
120 		} else {
121 			shm_clean(&tile_row_shm[i], tile_row[i]);
122 		}
123 		cnt++;
124 		if (single_copytile_count && i >= single_copytile_count) {
125 			break;
126 		}
127 	}
128 	if (!quiet && cnt > 0) {
129 		rfbLog("deleted %d tile_row polling images.\n", cnt);
130 	}
131 }
132 
clean_icon_mode(void)133 static void clean_icon_mode(void) {
134 	if (icon_mode && icon_mode_fh) {
135 		fprintf(icon_mode_fh, "quit\n");
136 		fflush(icon_mode_fh);
137 		fclose(icon_mode_fh);
138 		icon_mode_fh = NULL;
139 		if (icon_mode_file) {
140 			unlink(icon_mode_file);
141 			icon_mode_file = NULL;
142 		}
143 	}
144 }
145 
146 /*
147  * Normal exiting
148  */
clean_up_exit(int ret)149 void clean_up_exit(int ret) {
150 	static int depth = 0;
151 	exit_flag = 1;
152 
153 	if (depth++ > 2) {
154 		exit(ret);
155 	}
156 
157 	if (icon_mode) {
158 		clean_icon_mode();
159 	}
160 
161 	/* remove the shm areas: */
162 	clean_shm(0);
163 
164 	stop_stunnel();
165 	if (use_openssl) {
166 		ssl_helper_pid(0, 0);	/* killall */
167 	}
168 
169 	if (ssh_pid > 0) {
170 		kill(ssh_pid, SIGTERM);
171 		ssh_pid = 0;
172 	}
173 
174 #ifdef MACOSX
175 	if (client_connect_file) {
176 		if (strstr(client_connect_file, "/tmp/x11vnc-macosx-remote")
177 		    == client_connect_file) {
178 			unlink(client_connect_file);
179 		}
180 	}
181 	if (macosx_console) {
182 		macosxCG_fini();
183 	}
184 #endif
185 
186 	if (pipeinput_fh != NULL) {
187 		pclose(pipeinput_fh);
188 		pipeinput_fh = NULL;
189 	}
190 
191 	shutdown_uinput();
192 
193 	if (unix_sock) {
194 		if (unix_sock_fd >= 0) {
195 			rfbLog("deleting unix sock: %s\n", unix_sock);
196 			close(unix_sock_fd);
197 			unix_sock_fd = -1;
198 			unlink(unix_sock);
199 		}
200 	}
201 
202 	if (! dpy) {	/* raw_rb hack */
203 		if (rm_flagfile) {
204 			unlink(rm_flagfile);
205 			rm_flagfile = NULL;
206 		}
207 		exit(ret);
208 	}
209 
210 	/* X keyboard cleanups */
211 	delete_added_keycodes(0);
212 
213 	if (clear_mods == 1) {
214 		clear_modifiers(0);
215 	} else if (clear_mods == 2) {
216 		clear_keys();
217 	} else if (clear_mods == 3) {
218 		clear_keys();
219 		clear_locks();
220 	}
221 
222 	if (no_autorepeat) {
223 		autorepeat(1, 0);
224 	}
225 	if (use_solid_bg) {
226 		solid_bg(1);
227 	}
228 	if (ncache || ncache0) {
229 		kde_no_animate(1);
230 	}
231 	X_LOCK;
232 	XTestDiscard_wr(dpy);
233 #if LIBVNCSERVER_HAVE_LIBXDAMAGE
234 	if (xdamage) {
235 		XDamageDestroy(dpy, xdamage);
236 	}
237 #endif
238 #if LIBVNCSERVER_HAVE_LIBXTRAP
239 	if (trap_ctx) {
240 		XEFreeTC(trap_ctx);
241 	}
242 #endif
243 	/* XXX rdpy_ctrl, etc. cannot close w/o blocking */
244 	XCloseDisplay_wr(dpy);
245 	X_UNLOCK;
246 
247 	fflush(stderr);
248 
249 	if (rm_flagfile) {
250 		unlink(rm_flagfile);
251 		rm_flagfile = NULL;
252 	}
253 
254 	if (avahi) {
255 		avahi_cleanup();
256 		fflush(stderr);
257 	}
258 
259 	exit(ret);
260 }
261 
262 /* X11 error handlers */
263 
264 static XErrorHandler   Xerror_def;
265 static XIOErrorHandler XIOerr_def;
266 
trap_xerror(Display * d,XErrorEvent * error)267 int trap_xerror(Display *d, XErrorEvent *error) {
268 	trapped_xerror = 1;
269 	trapped_xerror_event = error;
270 
271 	if (d) {} /* unused vars warning: */
272 
273 	return 0;
274 }
275 
trap_xioerror(Display * d)276 int trap_xioerror(Display *d) {
277 	trapped_xioerror = 1;
278 
279 	if (d) {} /* unused vars warning: */
280 
281 	return 0;
282 }
283 
trap_getimage_xerror(Display * d,XErrorEvent * error)284 int trap_getimage_xerror(Display *d, XErrorEvent *error) {
285 	trapped_getimage_xerror = 1;
286 	trapped_xerror_event = error;
287 
288 	if (d) {} /* unused vars warning: */
289 
290 	return 0;
291 }
292 
293 /* Are silly Xorg people removing X_ShmAttach from XShm.h? */
294 /* INDEED!  What stupid, myopic morons...  */
295 /* Maintenance Monkeys busy typing at their keyboards... */
296 #ifndef X_ShmAttach
297 #define X_ShmAttach 1
298 #endif
299 
Xerror(Display * d,XErrorEvent * error)300 static int Xerror(Display *d, XErrorEvent *error) {
301 	X_UNLOCK;
302 
303 	if (getenv("X11VNC_PRINT_XERROR")) {
304 		fprintf(stderr, "Xerror: major_opcode: %d minor_opcode: %d error_code: %d\n",
305 		    error->request_code, error->minor_code, error->error_code);
306 	}
307 
308 	if (xshm_opcode > 0 && error->request_code == xshm_opcode) {
309 		if (error->minor_code == X_ShmAttach) {
310 			char *dstr = DisplayString(dpy);
311 			fprintf(stderr, "\nX11 MIT Shared Memory Attach failed:\n");
312 			fprintf(stderr, "  Is your DISPLAY=%s on a remote machine?\n", dstr);
313 			if (strstr(dstr, "localhost:")) {
314 				fprintf(stderr, "  Note:   DISPLAY=localhost:N suggests a SSH X11 redir to a remote machine.\n");
315 			} else if (dstr[0] != ':') {
316 				fprintf(stderr, "  Note:   DISPLAY=hostname:N suggests a remote display.\n");
317 			}
318 			fprintf(stderr, "  Suggestion, use: x11vnc -display :0 ... for local display :0\n\n");
319 		}
320 	}
321 
322 	interrupted(0);
323 
324 	if (d) {} /* unused vars warning: */
325 
326 	return (*Xerror_def)(d, error);
327 }
328 
329 void watch_loop(void);
330 
XIOerr(Display * d)331 static int XIOerr(Display *d) {
332 	static int reopen = 0, rmax = 1;
333 	X_UNLOCK;
334 
335 	if (getenv("X11VNC_REOPEN_DISPLAY")) {
336 		rmax = atoi(getenv("X11VNC_REOPEN_DISPLAY"));
337 	}
338 
339 #if !NO_X11
340 	if (reopen < rmax && getenv("X11VNC_REOPEN_DISPLAY")) {
341 		int db = getenv("X11VNC_REOPEN_DEBUG") ? 1 : 0;
342 		int sleepmax = 10, i;
343 		Display *save_dpy = dpy;
344 		char *dstr = strdup(DisplayString(save_dpy));
345 		reopen++;
346 		if (getenv("X11VNC_REOPEN_SLEEP_MAX")) {
347 			sleepmax = atoi(getenv("X11VNC_REOPEN_SLEEP_MAX"));
348 		}
349 		rfbLog("*** XIO error: Trying to reopen[%d/%d] display '%s'\n", reopen, rmax, dstr);
350 		rfbLog("*** XIO error: Note the reopened state may be unstable.\n");
351 		for (i=0; i < sleepmax; i++) {
352 			usleep (1000 * 1000);
353 			dpy = XOpenDisplay_wr(dstr);
354 			rfbLog("dpy[%d/%d]: %p\n", i+1, sleepmax, dpy);
355 			if (dpy) {
356 				break;
357 			}
358 		}
359 		last_open_xdisplay = time(NULL);
360 		if (dpy) {
361 			rfbLog("*** XIO error: Reopened display '%s' successfully.\n", dstr);
362 			if (db) rfbLog("*** XIO error: '%s' 0x%x\n", dstr, dpy);
363 			scr = DefaultScreen(dpy);
364 			rootwin = RootWindow(dpy, scr);
365 			if (db) rfbLog("*** XIO error: disable_grabserver\n");
366 			disable_grabserver(dpy, 0);
367 			if (db) rfbLog("*** XIO error: xrecord\n");
368 			zerodisp_xrecord();
369 			initialize_xrecord();
370 			if (db) rfbLog("*** XIO error: xdamage\n");
371 			create_xdamage_if_needed(1);
372 			if (db) rfbLog("*** XIO error: do_new_fb\n");
373 			if (using_shm) {
374 				if (db) rfbLog("*** XIO error: clean_shm\n");
375 				clean_shm(1);
376 			}
377 			do_new_fb(1);
378 			if (db) rfbLog("*** XIO error: check_xevents\n");
379 			check_xevents(1);
380 
381 			/* sadly, we can never return... */
382 			if (db) rfbLog("*** XIO error: watch_loop\n");
383 			watch_loop();
384 			clean_up_exit(1);
385 		}
386 	}
387 #endif
388 
389 	interrupted(-1);
390 
391 	if (d) {} /* unused vars warning: */
392 
393 	return (*XIOerr_def)(d);
394 }
395 
396 static char *xerrors[] = {
397 	"Success",
398 	"BadRequest",
399 	"BadValue",
400 	"BadWindow",
401 	"BadPixmap",
402 	"BadAtom",
403 	"BadCursor",
404 	"BadFont",
405 	"BadMatch",
406 	"BadDrawable",
407 	"BadAccess",
408 	"BadAlloc",
409 	"BadColor",
410 	"BadGC",
411 	"BadIDChoice",
412 	"BadName",
413 	"BadLength",
414 	"BadImplementation",
415 	"unknown"
416 };
417 static int xerrors_max = BadImplementation;
418 
xerror_string(XErrorEvent * error)419 char *xerror_string(XErrorEvent *error) {
420 	int index = -1;
421 	if (error) {
422 		index = (int) error->error_code;
423 	}
424 	if (0 <= index && index <= xerrors_max) {
425 		return xerrors[index];
426 	} else {
427 		return xerrors[xerrors_max+1];
428 	}
429 }
430 
431 static char *crash_stack_command1 = NULL;
432 static char *crash_stack_command2 = NULL;
433 static char *crash_debug_command = NULL;
434 
initialize_crash_handler(void)435 void initialize_crash_handler(void) {
436 	int pid = program_pid;
437 	crash_stack_command1 = (char *) malloc(1000);
438 	crash_stack_command2 = (char *) malloc(1000);
439 	crash_debug_command =  (char *) malloc(1000);
440 
441 	snprintf(crash_stack_command1, 500, "echo where > /tmp/gdb.%d;"
442 	    " env PATH=$PATH:/usr/local/bin:/usr/sfw/bin:/usr/bin"
443 	    " gdb -x /tmp/gdb.%d -batch -n %s %d;"
444 	    " rm -f /tmp/gdb.%d", pid, pid, program_name, pid, pid);
445 	snprintf(crash_stack_command2, 500, "pstack %d", program_pid);
446 
447 	snprintf(crash_debug_command, 500, "gdb %s %d", program_name, pid);
448 }
449 
crash_shell_help(void)450 static void crash_shell_help(void) {
451 	int pid = program_pid;
452 	fprintf(stderr, "\n");
453 	fprintf(stderr, "   *** Welcome to the x11vnc crash shell! ***\n");
454 	fprintf(stderr, "\n");
455 	fprintf(stderr, "PROGRAM: %s  PID: %d\n", program_name, pid);
456 	fprintf(stderr, "\n");
457 	fprintf(stderr, "POSSIBLE DEBUGGER COMMAND:\n");
458 	fprintf(stderr, "\n");
459 	fprintf(stderr, "  %s\n", crash_debug_command);
460 	fprintf(stderr, "\n");
461 	fprintf(stderr, "Press \"q\" to quit.\n");
462 	fprintf(stderr, "Press \"h\" or \"?\" for this help.\n");
463 	fprintf(stderr, "Press \"s\" to try to run some commands to"
464 	    " show a stack trace (gdb/pstack).\n");
465 	fprintf(stderr, "\n");
466 	fprintf(stderr, "Anything else is passed to -Q query function.\n");
467 	fprintf(stderr, "\n");
468 }
469 
crash_shell(void)470 static void crash_shell(void) {
471 	char qry[1000], cmd[1000], line[1000];
472 	char *str, *p;
473 
474 	crash_shell_help();
475 	fprintf(stderr, "\ncrash> ");
476 	while (fgets(line, 1000, stdin) != NULL) {
477 		str = lblanks(line);
478 
479 		p = str;
480 		while(*p) {
481 			if (*p == '\n') {
482 				*p = '\0';
483 			}
484 			p++;
485 		}
486 
487 		if (*str == 'q' && *(str+1) == '\0') {
488 			fprintf(stderr, "quiting.\n");
489 			return;
490 		} else if (*str == 'h' && *(str+1) == '\0') {
491 			crash_shell_help();
492 		} else if (*str == '?' && *(str+1) == '\0') {
493 			crash_shell_help();
494 		} else if (*str == 's' && *(str+1) == '\0') {
495 			sprintf(cmd, "sh -c '(%s) &'", crash_stack_command1);
496 			/* crash */
497 			if (no_external_cmds || !cmd_ok("crash")) {
498 				fprintf(stderr, "\nno_external_cmds=%d\n",
499 				    no_external_cmds);
500 				goto crash_prompt;
501 			}
502 			fprintf(stderr, "\nrunning:\n\t%s\n\n",
503 			    crash_stack_command1);
504 			system(cmd);
505 			usleep(1000*1000);
506 
507 			sprintf(cmd, "sh -c '(%s) &'", crash_stack_command2);
508 			fprintf(stderr, "\nrunning:\n\t%s\n\n",
509 			    crash_stack_command2);
510 			system(cmd);
511 			usleep(1000*1000);
512 		} else {
513 			snprintf(qry, 1000, "qry=%s", str);
514 			p = process_remote_cmd(qry, 1);
515 			fprintf(stderr, "\n\nresult:\n%s\n", p);
516 			free(p);
517 		}
518 
519 crash_prompt:
520 		fprintf(stderr, "crash> ");
521 	}
522 }
523 
524 /*
525  * General problem handler
526  */
interrupted(int sig)527 static void interrupted (int sig) {
528 	exit_sig = sig;
529 	if (exit_flag) {
530 		fprintf(stderr, "extra[%d] signal: %d\n", exit_flag, sig);
531 		exit_flag++;
532 		if (use_threads) {
533 			usleep2(250 * 1000);
534 		} else if (exit_flag <= 2) {
535 			return;
536 		}
537 		if (rm_flagfile) {
538 			unlink(rm_flagfile);
539 			rm_flagfile = NULL;
540 		}
541 		exit(4);
542 	}
543 	exit_flag++;
544 	if (sig == 0) {
545 		fprintf(stderr, "caught X11 error:\n");
546 		if (crash_debug) { crash_shell(); }
547 	} else if (sig == -1) {
548 		fprintf(stderr, "caught XIO error:\n");
549 	} else {
550 		fprintf(stderr, "caught signal: %d\n", sig);
551 	}
552 	if (sig == SIGINT) {
553 		shut_down = 1;
554 		return;
555 	}
556 
557 	if (crash_debug) {
558 		crash_shell();
559 	}
560 
561 	X_UNLOCK;
562 
563 	if (icon_mode) {
564 		clean_icon_mode();
565 	}
566 	/* remove the shm areas with quick=1: */
567 	clean_shm(1);
568 
569 	if (sig == -1) {
570 		/* not worth trying any more cleanup, X server probably gone */
571 		if (rm_flagfile) {
572 			unlink(rm_flagfile);
573 			rm_flagfile = NULL;
574 		}
575 		exit(3);
576 	}
577 
578 	/* X keyboard cleanups */
579 	delete_added_keycodes(0);
580 
581 	if (clear_mods == 1) {
582 		clear_modifiers(0);
583 	} else if (clear_mods == 2) {
584 		clear_keys();
585 	} else if (clear_mods == 3) {
586 		clear_keys();
587 		clear_locks();
588 	}
589 	if (no_autorepeat) {
590 		autorepeat(1, 0);
591 	}
592 	if (use_solid_bg) {
593 		solid_bg(1);
594 	}
595 	if (ncache || ncache0) {
596 		kde_no_animate(1);
597 	}
598 	stop_stunnel();
599 
600 	if (crash_debug) {
601 		crash_shell();
602 	}
603 
604 	if (sig) {
605 		if (rm_flagfile) {
606 			unlink(rm_flagfile);
607 			rm_flagfile = NULL;
608 		}
609 		exit(2);
610 	}
611 }
612 
ignore_sigs(char * list)613 static void ignore_sigs(char *list) {
614 	char *str, *p;
615 	int ignore = 1;
616 	if (list == NULL || *list == '\0') {
617 		return;
618 	}
619 	str = strdup(list);
620 	p = strtok(str, ":,");
621 
622 #define SETSIG(x, y) \
623 	if (strstr(p, x)) { \
624 		if (ignore) { \
625 			signal(y, SIG_IGN); \
626 		} else { \
627 			signal(y, interrupted); \
628 		} \
629 	}
630 
631 #ifdef SIG_IGN
632 	while (p) {
633 		if (!strcmp(p, "ignore")) {
634 			ignore = 1;
635 		} else if (!strcmp(p, "exit")) {
636 			ignore = 0;
637 		}
638 		/* Take off every 'sig' ;-) */
639 #ifdef SIGHUP
640 		SETSIG("HUP", SIGHUP);
641 #endif
642 #ifdef SIGINT
643 		SETSIG("INT", SIGINT);
644 #endif
645 #ifdef SIGQUIT
646 		SETSIG("QUIT", SIGQUIT);
647 #endif
648 #ifdef SIGTRAP
649 		SETSIG("TRAP", SIGTRAP);
650 #endif
651 #ifdef SIGABRT
652 		SETSIG("ABRT", SIGABRT);
653 #endif
654 #ifdef SIGBUS
655 		SETSIG("BUS", SIGBUS);
656 #endif
657 #ifdef SIGFPE
658 		SETSIG("FPE", SIGFPE);
659 #endif
660 #ifdef SIGSEGV
661 		SETSIG("SEGV", SIGSEGV);
662 #endif
663 #ifdef SIGPIPE
664 		SETSIG("PIPE", SIGPIPE);
665 #endif
666 #ifdef SIGTERM
667 		SETSIG("TERM", SIGTERM);
668 #endif
669 #ifdef SIGUSR1
670 		SETSIG("USR1", SIGUSR1);
671 #endif
672 #ifdef SIGUSR2
673 		SETSIG("USR2", SIGUSR2);
674 #endif
675 #ifdef SIGCONT
676 		SETSIG("CONT", SIGCONT);
677 #endif
678 #ifdef SIGSTOP
679 		SETSIG("STOP", SIGSTOP);
680 #endif
681 #ifdef SIGTSTP
682 		SETSIG("TSTP", SIGTSTP);
683 #endif
684 		p = strtok(NULL, ":,");
685 	}
686 #endif	/* SIG_IGN */
687 	free(str);
688 }
689 
690 /* signal handlers */
initialize_signals(void)691 void initialize_signals(void) {
692 	signal(SIGHUP,  interrupted);
693 	signal(SIGINT,  interrupted);
694 	signal(SIGQUIT, interrupted);
695 	signal(SIGABRT, interrupted);
696 	signal(SIGTERM, interrupted);
697 	signal(SIGBUS,  interrupted);
698 	signal(SIGSEGV, interrupted);
699 	signal(SIGFPE,  interrupted);
700 
701 	if (!sigpipe || *sigpipe == '\0' || !strcmp(sigpipe, "skip")) {
702 		;
703 	} else if (strstr(sigpipe, "ignore:") == sigpipe) {
704 		ignore_sigs(sigpipe);
705 	} else if (strstr(sigpipe, "exit:") == sigpipe) {
706 		ignore_sigs(sigpipe);
707 	} else if (!strcmp(sigpipe, "ignore")) {
708 #ifdef SIG_IGN
709 		signal(SIGPIPE, SIG_IGN);
710 #endif
711 	} else if (!strcmp(sigpipe, "exit")) {
712 		rfbLog("initialize_signals: will exit on SIGPIPE\n");
713 		signal(SIGPIPE, interrupted);
714 	}
715 
716 #if NO_X11
717 	return;
718 #else
719 	X_LOCK;
720 	Xerror_def = XSetErrorHandler(Xerror);
721 	XIOerr_def = XSetIOErrorHandler(XIOerr);
722 	X_UNLOCK;
723 #endif	/* NO_X11 */
724 }
725 
unset_signals(void)726 void unset_signals(void) {
727 	signal(SIGHUP,  SIG_DFL);
728 	signal(SIGINT,  SIG_DFL);
729 	signal(SIGQUIT, SIG_DFL);
730 	signal(SIGABRT, SIG_DFL);
731 	signal(SIGTERM, SIG_DFL);
732 	signal(SIGBUS,  SIG_DFL);
733 	signal(SIGSEGV, SIG_DFL);
734 	signal(SIGFPE,  SIG_DFL);
735 	signal(SIGPIPE, SIG_DFL);
736 }
737 
close_exec_fds(void)738 void close_exec_fds(void) {
739 	int fd;
740 #ifdef FD_CLOEXEC
741 	for (fd = 3; fd < 64; fd++) {
742 		int flags = fcntl(fd, F_GETFD);
743 		if (flags != -1) {
744 			flags |= FD_CLOEXEC;
745 			fcntl(fd, F_SETFD, flags);
746 		}
747 	}
748 #endif
749 }
750 
known_sigpipe_mode(char * s)751 int known_sigpipe_mode(char *s) {
752 /*
753  * skip, ignore, exit
754  */
755 	if (strstr(s, "ignore:") == s) {
756 		return 1;
757 	}
758 	if (strstr(s, "exit:") == s) {
759 		return 1;
760 	}
761 	if (strcmp(s, "skip") && strcmp(s, "ignore") &&
762 	    strcmp(s, "exit")) {
763 		return 0;
764 	} else {
765 		return 1;
766 	}
767 }
768 
769 
770