xref: /vim-8.2.3635/src/os_unix.c (revision 8b8d829f)
1 /* vi:set ts=8 sts=4 sw=4 noet:
2  *
3  * VIM - Vi IMproved	by Bram Moolenaar
4  *	      OS/2 port by Paul Slootman
5  *	      VMS merge by Zoltan Arpadffy
6  *
7  * Do ":help uganda"  in Vim to read copying and usage conditions.
8  * Do ":help credits" in Vim to see a list of people who contributed.
9  * See README.txt for an overview of the Vim source code.
10  */
11 
12 /*
13  * os_unix.c -- code for all flavors of Unix (BSD, SYSV, SVR4, POSIX, ...)
14  *	     Also for OS/2, using the excellent EMX package!!!
15  *	     Also for Atari MiNT.
16  *
17  * A lot of this file was originally written by Juergen Weigert and later
18  * changed beyond recognition.
19  */
20 
21 #include "vim.h"
22 
23 #ifdef FEAT_MZSCHEME
24 # include "if_mzsch.h"
25 #endif
26 
27 #include "os_unixx.h"	    // unix includes for os_unix.c only
28 
29 #ifdef USE_XSMP
30 # include <X11/SM/SMlib.h>
31 #endif
32 
33 #ifdef HAVE_SELINUX
34 # include <selinux/selinux.h>
35 static int selinux_enabled = -1;
36 #endif
37 
38 #ifdef HAVE_SMACK
39 # include <attr/xattr.h>
40 # include <linux/xattr.h>
41 # ifndef SMACK_LABEL_LEN
42 #  define SMACK_LABEL_LEN 1024
43 # endif
44 #endif
45 
46 #ifdef __CYGWIN__
47 # ifndef MSWIN
48 #  include <cygwin/version.h>
49 #  include <sys/cygwin.h>	// for cygwin_conv_to_posix_path() and/or
50 				// for cygwin_conv_path()
51 #  ifdef FEAT_CYGWIN_WIN32_CLIPBOARD
52 #   define WIN32_LEAN_AND_MEAN
53 #   include <windows.h>
54 #   include "winclip.pro"
55 #  endif
56 # endif
57 #endif
58 
59 #ifdef FEAT_MOUSE_GPM
60 # include <gpm.h>
61 // <linux/keyboard.h> contains defines conflicting with "keymap.h",
62 // I just copied relevant defines here. A cleaner solution would be to put gpm
63 // code into separate file and include there linux/keyboard.h
64 // #include <linux/keyboard.h>
65 # define KG_SHIFT	0
66 # define KG_CTRL	2
67 # define KG_ALT		3
68 # define KG_ALTGR	1
69 # define KG_SHIFTL	4
70 # define KG_SHIFTR	5
71 # define KG_CTRLL	6
72 # define KG_CTRLR	7
73 # define KG_CAPSSHIFT	8
74 
75 static void gpm_close(void);
76 static int gpm_open(void);
77 static int mch_gpm_process(void);
78 #endif
79 
80 #ifdef FEAT_SYSMOUSE
81 # include <sys/consio.h>
82 # include <sys/fbio.h>
83 
84 static int sysmouse_open(void);
85 static void sysmouse_close(void);
86 static RETSIGTYPE sig_sysmouse SIGPROTOARG;
87 #endif
88 
89 /*
90  * end of autoconf section. To be extended...
91  */
92 
93 // Are the following #ifdefs still required? And why? Is that for X11?
94 
95 #if defined(ESIX) || defined(M_UNIX) && !defined(SCO)
96 # ifdef SIGWINCH
97 #  undef SIGWINCH
98 # endif
99 # ifdef TIOCGWINSZ
100 #  undef TIOCGWINSZ
101 # endif
102 #endif
103 
104 #if defined(SIGWINDOW) && !defined(SIGWINCH)	// hpux 9.01 has it
105 # define SIGWINCH SIGWINDOW
106 #endif
107 
108 #ifdef FEAT_X11
109 # include <X11/Xlib.h>
110 # include <X11/Xutil.h>
111 # include <X11/Xatom.h>
112 # ifdef FEAT_XCLIPBOARD
113 #  include <X11/Intrinsic.h>
114 #  include <X11/Shell.h>
115 #  include <X11/StringDefs.h>
116 static Widget	xterm_Shell = (Widget)0;
117 static void clip_update(void);
118 static void xterm_update(void);
119 # endif
120 
121 # if defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE)
122 Window	    x11_window = 0;
123 # endif
124 Display	    *x11_display = NULL;
125 #endif
126 
127 static int ignore_sigtstp = FALSE;
128 
129 #ifdef FEAT_TITLE
130 static int get_x11_title(int);
131 
132 static char_u	*oldtitle = NULL;
133 static volatile sig_atomic_t oldtitle_outdated = FALSE;
134 static int	unix_did_set_title = FALSE;
135 static char_u	*oldicon = NULL;
136 static int	did_set_icon = FALSE;
137 #endif
138 
139 static void may_core_dump(void);
140 
141 #ifdef HAVE_UNION_WAIT
142 typedef union wait waitstatus;
143 #else
144 typedef int waitstatus;
145 #endif
146 static int  WaitForChar(long msec, int *interrupted, int ignore_input);
147 static int  WaitForCharOrMouse(long msec, int *interrupted, int ignore_input);
148 #ifdef VMS
149 int  RealWaitForChar(int, long, int *, int *interrupted);
150 #else
151 static int  RealWaitForChar(int, long, int *, int *interrupted);
152 #endif
153 
154 #ifdef FEAT_XCLIPBOARD
155 static int do_xterm_trace(void);
156 # define XT_TRACE_DELAY	50	// delay for xterm tracing
157 #endif
158 
159 static void handle_resize(void);
160 
161 #if defined(SIGWINCH)
162 static RETSIGTYPE sig_winch SIGPROTOARG;
163 #endif
164 #if defined(SIGINT)
165 static RETSIGTYPE catch_sigint SIGPROTOARG;
166 #endif
167 #if defined(SIGUSR1)
168 static RETSIGTYPE catch_sigusr1 SIGPROTOARG;
169 #endif
170 #if defined(SIGPWR)
171 static RETSIGTYPE catch_sigpwr SIGPROTOARG;
172 #endif
173 #if defined(SIGALRM) && defined(FEAT_X11) \
174 	&& defined(FEAT_TITLE) && !defined(FEAT_GUI_GTK)
175 # define SET_SIG_ALARM
176 static RETSIGTYPE sig_alarm SIGPROTOARG;
177 // volatile because it is used in signal handler sig_alarm().
178 static volatile sig_atomic_t sig_alarm_called;
179 #endif
180 static RETSIGTYPE deathtrap SIGPROTOARG;
181 
182 static void catch_int_signal(void);
183 static void set_signals(void);
184 static void catch_signals(RETSIGTYPE (*func_deadly)(), RETSIGTYPE (*func_other)());
185 #ifdef HAVE_SIGPROCMASK
186 # define SIGSET_DECL(set)	sigset_t set;
187 # define BLOCK_SIGNALS(set)	block_signals(set)
188 # define UNBLOCK_SIGNALS(set)	unblock_signals(set)
189 #else
190 # define SIGSET_DECL(set)
191 # define BLOCK_SIGNALS(set)	do { /**/ } while (0)
192 # define UNBLOCK_SIGNALS(set)	do { /**/ } while (0)
193 #endif
194 static int  have_wildcard(int, char_u **);
195 static int  have_dollars(int, char_u **);
196 
197 static int save_patterns(int num_pat, char_u **pat, int *num_file, char_u ***file);
198 
199 #ifndef SIG_ERR
200 # define SIG_ERR	((RETSIGTYPE (*)())-1)
201 #endif
202 
203 // volatile because it is used in signal handler sig_winch().
204 static volatile sig_atomic_t do_resize = FALSE;
205 static char_u	*extra_shell_arg = NULL;
206 static int	show_shell_mess = TRUE;
207 // volatile because it is used in signal handler deathtrap().
208 static volatile sig_atomic_t deadly_signal = 0;	   // The signal we caught
209 // volatile because it is used in signal handler deathtrap().
210 static volatile sig_atomic_t in_mch_delay = FALSE; // sleeping in mch_delay()
211 
212 #if defined(FEAT_JOB_CHANNEL) && !defined(USE_SYSTEM)
213 static int dont_check_job_ended = 0;
214 #endif
215 
216 // Current terminal mode from mch_settmode().  Can differ from cur_tmode.
217 static tmode_T mch_cur_tmode = TMODE_COOK;
218 
219 #ifdef USE_XSMP
220 typedef struct
221 {
222     SmcConn smcconn;	    // The SM connection ID
223     IceConn iceconn;	    // The ICE connection ID
224     char *clientid;	    // The client ID for the current smc session
225     Bool save_yourself;     // If we're in the middle of a save_yourself
226     Bool shutdown;	    // If we're in shutdown mode
227 } xsmp_config_T;
228 
229 static xsmp_config_T xsmp;
230 #endif
231 
232 #ifdef SYS_SIGLIST_DECLARED
233 /*
234  * I have seen
235  *  extern char *_sys_siglist[NSIG];
236  * on Irix, Linux, NetBSD and Solaris. It contains a nice list of strings
237  * that describe the signals. That is nearly what we want here.  But
238  * autoconf does only check for sys_siglist (without the underscore), I
239  * do not want to change everything today.... jw.
240  * This is why AC_DECL_SYS_SIGLIST is commented out in configure.ac.
241  */
242 #endif
243 
244 static struct signalinfo
245 {
246     int	    sig;	// Signal number, eg. SIGSEGV etc
247     char    *name;	// Signal name (not char_u!).
248     char    deadly;	// Catch as a deadly signal?
249 } signal_info[] =
250 {
251 #ifdef SIGHUP
252     {SIGHUP,	    "HUP",	TRUE},
253 #endif
254 #ifdef SIGQUIT
255     {SIGQUIT,	    "QUIT",	TRUE},
256 #endif
257 #ifdef SIGILL
258     {SIGILL,	    "ILL",	TRUE},
259 #endif
260 #ifdef SIGTRAP
261     {SIGTRAP,	    "TRAP",	TRUE},
262 #endif
263 #ifdef SIGABRT
264     {SIGABRT,	    "ABRT",	TRUE},
265 #endif
266 #ifdef SIGEMT
267     {SIGEMT,	    "EMT",	TRUE},
268 #endif
269 #ifdef SIGFPE
270     {SIGFPE,	    "FPE",	TRUE},
271 #endif
272 #ifdef SIGBUS
273     {SIGBUS,	    "BUS",	TRUE},
274 #endif
275 #if defined(SIGSEGV) && !defined(FEAT_MZSCHEME)
276     // MzScheme uses SEGV in its garbage collector
277     {SIGSEGV,	    "SEGV",	TRUE},
278 #endif
279 #ifdef SIGSYS
280     {SIGSYS,	    "SYS",	TRUE},
281 #endif
282 #ifdef SIGALRM
283     {SIGALRM,	    "ALRM",	FALSE},	// Perl's alarm() can trigger it
284 #endif
285 #ifdef SIGTERM
286     {SIGTERM,	    "TERM",	TRUE},
287 #endif
288 #if defined(SIGVTALRM) && !defined(FEAT_RUBY)
289     {SIGVTALRM,	    "VTALRM",	TRUE},
290 #endif
291 #if defined(SIGPROF) && !defined(FEAT_MZSCHEME) && !defined(WE_ARE_PROFILING)
292     // MzScheme uses SIGPROF for its own needs; On Linux with profiling
293     // this makes Vim exit.  WE_ARE_PROFILING is defined in Makefile.
294     {SIGPROF,	    "PROF",	TRUE},
295 #endif
296 #ifdef SIGXCPU
297     {SIGXCPU,	    "XCPU",	TRUE},
298 #endif
299 #ifdef SIGXFSZ
300     {SIGXFSZ,	    "XFSZ",	TRUE},
301 #endif
302 #ifdef SIGUSR1
303     {SIGUSR1,	    "USR1",	FALSE},
304 #endif
305 #if defined(SIGUSR2) && !defined(FEAT_SYSMOUSE)
306     // Used for sysmouse handling
307     {SIGUSR2,	    "USR2",	TRUE},
308 #endif
309 #ifdef SIGINT
310     {SIGINT,	    "INT",	FALSE},
311 #endif
312 #ifdef SIGWINCH
313     {SIGWINCH,	    "WINCH",	FALSE},
314 #endif
315 #ifdef SIGTSTP
316     {SIGTSTP,	    "TSTP",	FALSE},
317 #endif
318 #ifdef SIGPIPE
319     {SIGPIPE,	    "PIPE",	FALSE},
320 #endif
321     {-1,	    "Unknown!", FALSE}
322 };
323 
324     int
mch_chdir(char * path)325 mch_chdir(char *path)
326 {
327     if (p_verbose >= 5)
328     {
329 	verbose_enter();
330 	smsg("chdir(%s)", path);
331 	verbose_leave();
332     }
333 # ifdef VMS
334     return chdir(vms_fixfilename(path));
335 # else
336     return chdir(path);
337 # endif
338 }
339 
340 // Why is NeXT excluded here (and not in os_unixx.h)?
341 #if defined(ECHOE) && defined(ICANON) \
342     && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) \
343     && !defined(__NeXT__)
344 # define NEW_TTY_SYSTEM
345 #endif
346 
347 /*
348  * Write s[len] to the screen (stdout).
349  */
350     void
mch_write(char_u * s,int len)351 mch_write(char_u *s, int len)
352 {
353     vim_ignored = (int)write(1, (char *)s, len);
354     if (p_wd)		// Unix is too fast, slow down a bit more
355 	RealWaitForChar(read_cmd_fd, p_wd, NULL, NULL);
356 }
357 
358 /*
359  * Function passed to inchar_loop() to handle window resizing.
360  * If "check_only" is TRUE: Return whether there was a resize.
361  * If "check_only" is FALSE: Deal with the window resized.
362  */
363     static int
resize_func(int check_only)364 resize_func(int check_only)
365 {
366     if (check_only)
367 	return do_resize;
368     while (do_resize)
369 	handle_resize();
370     return FALSE;
371 }
372 
373 /*
374  * mch_inchar(): low level input function.
375  * Get a characters from the keyboard.
376  * Return the number of characters that are available.
377  * If wtime == 0 do not wait for characters.
378  * If wtime == n wait a short time for characters.
379  * If wtime == -1 wait forever for characters.
380  */
381     int
mch_inchar(char_u * buf,int maxlen,long wtime,int tb_change_cnt)382 mch_inchar(
383     char_u	*buf,
384     int		maxlen,
385     long	wtime,	    // don't use "time", MIPS cannot handle it
386     int		tb_change_cnt)
387 {
388     return inchar_loop(buf, maxlen, wtime, tb_change_cnt,
389 		       WaitForChar, resize_func);
390 }
391 
392     static void
handle_resize(void)393 handle_resize(void)
394 {
395     do_resize = FALSE;
396     shell_resized();
397 }
398 
399 /*
400  * Return non-zero if a character is available.
401  */
402     int
mch_char_avail(void)403 mch_char_avail(void)
404 {
405     return WaitForChar(0L, NULL, FALSE);
406 }
407 
408 #if defined(FEAT_TERMINAL) || defined(PROTO)
409 /*
410  * Check for any pending input or messages.
411  */
412     int
mch_check_messages(void)413 mch_check_messages(void)
414 {
415     return WaitForChar(0L, NULL, TRUE);
416 }
417 #endif
418 
419 #if defined(HAVE_TOTAL_MEM) || defined(PROTO)
420 # ifdef HAVE_SYS_RESOURCE_H
421 #  include <sys/resource.h>
422 # endif
423 # if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTL)
424 #  include <sys/sysctl.h>
425 # endif
426 # if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
427 #  include <sys/sysinfo.h>
428 # endif
429 # ifdef MACOS_X
430 #  include <mach/mach_host.h>
431 #  include <mach/mach_port.h>
432 # endif
433 
434 /*
435  * Return total amount of memory available in Kbyte.
436  * Doesn't change when memory has been allocated.
437  */
438     long_u
mch_total_mem(int special UNUSED)439 mch_total_mem(int special UNUSED)
440 {
441     long_u	mem = 0;
442     long_u	shiftright = 10;  // how much to shift "mem" right for Kbyte
443 
444 # ifdef MACOS_X
445     {
446 	// Mac (Darwin) way of getting the amount of RAM available
447 	mach_port_t		host = mach_host_self();
448 	kern_return_t		kret;
449 #  ifdef HOST_VM_INFO64
450 	struct vm_statistics64	vm_stat;
451 	natural_t		count = HOST_VM_INFO64_COUNT;
452 
453 	kret = host_statistics64(host, HOST_VM_INFO64,
454 					     (host_info64_t)&vm_stat, &count);
455 #  else
456 	struct vm_statistics	vm_stat;
457 	natural_t		count = HOST_VM_INFO_COUNT;
458 
459 	kret = host_statistics(host, HOST_VM_INFO,
460 					       (host_info_t)&vm_stat, &count);
461 #  endif
462 	if (kret == KERN_SUCCESS)
463 	    // get the amount of user memory by summing each usage
464 	    mem = (long_u)(vm_stat.free_count + vm_stat.active_count
465 					    + vm_stat.inactive_count
466 #  ifdef MAC_OS_X_VERSION_10_9
467 					    + vm_stat.compressor_page_count
468 #  endif
469 					    ) * sysconf(_SC_PAGESIZE);
470 	mach_port_deallocate(mach_task_self(), host);
471     }
472 # endif
473 
474 # ifdef HAVE_SYSCTL
475     if (mem == 0)
476     {
477 	// BSD way of getting the amount of RAM available.
478 	int		mib[2];
479 	size_t		len = sizeof(long_u);
480 #  ifdef HW_USERMEM64
481 	long_u		physmem;
482 #  else
483 	// sysctl() may return 32 bit or 64 bit, accept both
484 	union {
485 	    int_u	u32;
486 	    long_u	u64;
487 	} physmem;
488 #  endif
489 
490 	mib[0] = CTL_HW;
491 #  ifdef HW_USERMEM64
492 	mib[1] = HW_USERMEM64;
493 #  else
494 	mib[1] = HW_USERMEM;
495 #  endif
496 	if (sysctl(mib, 2, &physmem, &len, NULL, 0) == 0)
497 	{
498 #  ifdef HW_USERMEM64
499 	    mem = (long_u)physmem;
500 #  else
501 	    if (len == sizeof(physmem.u64))
502 		mem = (long_u)physmem.u64;
503 	    else
504 		mem = (long_u)physmem.u32;
505 #  endif
506 	}
507     }
508 # endif
509 
510 # if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
511     if (mem == 0)
512     {
513 	struct sysinfo sinfo;
514 
515 	// Linux way of getting amount of RAM available
516 	if (sysinfo(&sinfo) == 0)
517 	{
518 #  ifdef HAVE_SYSINFO_MEM_UNIT
519 	    // avoid overflow as much as possible
520 	    while (shiftright > 0 && (sinfo.mem_unit & 1) == 0)
521 	    {
522 		sinfo.mem_unit = sinfo.mem_unit >> 1;
523 		--shiftright;
524 	    }
525 	    mem = sinfo.totalram * sinfo.mem_unit;
526 #  else
527 	    mem = sinfo.totalram;
528 #  endif
529 	}
530     }
531 # endif
532 
533 # ifdef HAVE_SYSCONF
534     if (mem == 0)
535     {
536 	long	    pagesize, pagecount;
537 
538 	// Solaris way of getting amount of RAM available
539 	pagesize = sysconf(_SC_PAGESIZE);
540 	pagecount = sysconf(_SC_PHYS_PAGES);
541 	if (pagesize > 0 && pagecount > 0)
542 	{
543 	    // avoid overflow as much as possible
544 	    while (shiftright > 0 && (pagesize & 1) == 0)
545 	    {
546 		pagesize = (long_u)pagesize >> 1;
547 		--shiftright;
548 	    }
549 	    mem = (long_u)pagesize * pagecount;
550 	}
551     }
552 # endif
553 
554     // Return the minimum of the physical memory and the user limit, because
555     // using more than the user limit may cause Vim to be terminated.
556 # if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT)
557     {
558 	struct rlimit	rlp;
559 
560 	if (getrlimit(RLIMIT_DATA, &rlp) == 0
561 		&& rlp.rlim_cur < ((rlim_t)1 << (sizeof(long_u) * 8 - 1))
562 #  ifdef RLIM_INFINITY
563 		&& rlp.rlim_cur != RLIM_INFINITY
564 #  endif
565 		&& ((long_u)rlp.rlim_cur >> 10) < (mem >> shiftright)
566 	   )
567 	{
568 	    mem = (long_u)rlp.rlim_cur;
569 	    shiftright = 10;
570 	}
571     }
572 # endif
573 
574     if (mem > 0)
575 	return mem >> shiftright;
576     return (long_u)0x1fffff;
577 }
578 #endif
579 
580 /*
581  * "flags": MCH_DELAY_IGNOREINPUT - don't read input
582  *	    MCH_DELAY_SETTMODE - use settmode() even for short delays
583  */
584     void
mch_delay(long msec,int flags)585 mch_delay(long msec, int flags)
586 {
587     tmode_T	old_tmode;
588     int		call_settmode;
589 #ifdef FEAT_MZSCHEME
590     long	total = msec; // remember original value
591 #endif
592 
593     if (flags & MCH_DELAY_IGNOREINPUT)
594     {
595 	// Go to cooked mode without echo, to allow SIGINT interrupting us
596 	// here.  But we don't want QUIT to kill us (CTRL-\ used in a
597 	// shell may produce SIGQUIT).
598 	// Only do this if sleeping for more than half a second.
599 	in_mch_delay = TRUE;
600 	call_settmode = mch_cur_tmode == TMODE_RAW
601 			       && (msec > 500 || (flags & MCH_DELAY_SETTMODE));
602 	if (call_settmode)
603 	{
604 	    old_tmode = mch_cur_tmode;
605 	    settmode(TMODE_SLEEP);
606 	}
607 
608 	/*
609 	 * Everybody sleeps in a different way...
610 	 * Prefer nanosleep(), some versions of usleep() can only sleep up to
611 	 * one second.
612 	 */
613 #ifdef FEAT_MZSCHEME
614 	do
615 	{
616 	    // if total is large enough, wait by portions in p_mzq
617 	    if (total > p_mzq)
618 		msec = p_mzq;
619 	    else
620 		msec = total;
621 	    total -= msec;
622 #endif
623 #ifdef HAVE_NANOSLEEP
624 	{
625 	    struct timespec ts;
626 
627 	    ts.tv_sec = msec / 1000;
628 	    ts.tv_nsec = (msec % 1000) * 1000000;
629 	    (void)nanosleep(&ts, NULL);
630 	}
631 #else
632 # ifdef HAVE_USLEEP
633 	while (msec >= 1000)
634 	{
635 	    usleep((unsigned int)(999 * 1000));
636 	    msec -= 999;
637 	}
638 	usleep((unsigned int)(msec * 1000));
639 # else
640 #  ifndef HAVE_SELECT
641 	poll(NULL, 0, (int)msec);
642 #  else
643 	{
644 	    struct timeval tv;
645 
646 	    tv.tv_sec = msec / 1000;
647 	    tv.tv_usec = (msec % 1000) * 1000;
648 	    // NOTE: Solaris 2.6 has a bug that makes select() hang here.  Get
649 	    // a patch from Sun to fix this.  Reported by Gunnar Pedersen.
650 	    select(0, NULL, NULL, NULL, &tv);
651 	}
652 #  endif // HAVE_SELECT
653 # endif // HAVE_NANOSLEEP
654 #endif // HAVE_USLEEP
655 #ifdef FEAT_MZSCHEME
656 	}
657 	while (total > 0);
658 #endif
659 
660 	if (call_settmode)
661 	    settmode(old_tmode);
662 	in_mch_delay = FALSE;
663     }
664     else
665 	WaitForChar(msec, NULL, FALSE);
666 }
667 
668 #if defined(HAVE_STACK_LIMIT) \
669 	|| (!defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGSTACK))
670 # define HAVE_CHECK_STACK_GROWTH
671 /*
672  * Support for checking for an almost-out-of-stack-space situation.
673  */
674 
675 /*
676  * Return a pointer to an item on the stack.  Used to find out if the stack
677  * grows up or down.
678  */
679 static int stack_grows_downwards;
680 
681 /*
682  * Find out if the stack grows upwards or downwards.
683  * "p" points to a variable on the stack of the caller.
684  */
685     static void
check_stack_growth(char * p)686 check_stack_growth(char *p)
687 {
688     int		i;
689 
690     stack_grows_downwards = (p > (char *)&i);
691 }
692 #endif
693 
694 #if defined(HAVE_STACK_LIMIT) || defined(PROTO)
695 static char *stack_limit = NULL;
696 
697 #if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
698 # include <pthread.h>
699 # include <pthread_np.h>
700 #endif
701 
702 /*
703  * Find out until how var the stack can grow without getting into trouble.
704  * Called when starting up and when switching to the signal stack in
705  * deathtrap().
706  */
707     static void
get_stack_limit(void)708 get_stack_limit(void)
709 {
710     struct rlimit	rlp;
711     int			i;
712     long		lim;
713 
714     // Set the stack limit to 15/16 of the allowable size.  Skip this when the
715     // limit doesn't fit in a long (rlim_cur might be "long long").
716     if (getrlimit(RLIMIT_STACK, &rlp) == 0
717 	    && rlp.rlim_cur < ((rlim_t)1 << (sizeof(long_u) * 8 - 1))
718 #  ifdef RLIM_INFINITY
719 	    && rlp.rlim_cur != RLIM_INFINITY
720 #  endif
721        )
722     {
723 	lim = (long)rlp.rlim_cur;
724 #if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
725 	{
726 	    pthread_attr_t  attr;
727 	    size_t	    size;
728 
729 	    // On FreeBSD the initial thread always has a fixed stack size, no
730 	    // matter what the limits are set to.  Normally it's 1 Mbyte.
731 	    pthread_attr_init(&attr);
732 	    if (pthread_attr_get_np(pthread_self(), &attr) == 0)
733 	    {
734 		pthread_attr_getstacksize(&attr, &size);
735 		if (lim > (long)size)
736 		    lim = (long)size;
737 	    }
738 	    pthread_attr_destroy(&attr);
739 	}
740 #endif
741 	if (stack_grows_downwards)
742 	{
743 	    stack_limit = (char *)((long)&i - (lim / 16L * 15L));
744 	    if (stack_limit >= (char *)&i)
745 		// overflow, set to 1/16 of current stack position
746 		stack_limit = (char *)((long)&i / 16L);
747 	}
748 	else
749 	{
750 	    stack_limit = (char *)((long)&i + (lim / 16L * 15L));
751 	    if (stack_limit <= (char *)&i)
752 		stack_limit = NULL;	// overflow
753 	}
754     }
755 }
756 
757 /*
758  * Return FAIL when running out of stack space.
759  * "p" must point to any variable local to the caller that's on the stack.
760  */
761     int
mch_stackcheck(char * p)762 mch_stackcheck(char *p)
763 {
764     if (stack_limit != NULL)
765     {
766 	if (stack_grows_downwards)
767 	{
768 	    if (p < stack_limit)
769 		return FAIL;
770 	}
771 	else if (p > stack_limit)
772 	    return FAIL;
773     }
774     return OK;
775 }
776 #endif
777 
778 #if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
779 /*
780  * Support for using the signal stack.
781  * This helps when we run out of stack space, which causes a SIGSEGV.  The
782  * signal handler then must run on another stack, since the normal stack is
783  * completely full.
784  */
785 
786 # ifdef HAVE_SIGALTSTACK
787 static stack_t sigstk;			// for sigaltstack()
788 # else
789 static struct sigstack sigstk;		// for sigstack()
790 # endif
791 
792 /*
793  * Get a size of signal stack.
794  * Preference (if available): sysconf > SIGSTKSZ > guessed size
795  */
get_signal_stack_size()796 static long int get_signal_stack_size()
797 {
798 # ifdef HAVE_SYSCONF_SIGSTKSZ
799     long int size = -1;
800 
801     // return size only if sysconf doesn't return an error
802     if ((size = sysconf(_SC_SIGSTKSZ)) > -1)
803 	return size;
804 # endif
805 
806 # ifdef SIGSTKSZ
807     // if sysconf() isn't available or gives error, return SIGSTKSZ
808     // if defined
809     return SIGSTKSZ;
810 # endif
811 
812     // otherwise guess the size
813     return 8000;
814 }
815 
816 static char *signal_stack;
817 
818     static void
init_signal_stack(void)819 init_signal_stack(void)
820 {
821     if (signal_stack != NULL)
822     {
823 # ifdef HAVE_SIGALTSTACK
824 #  ifdef HAVE_SS_BASE
825 	sigstk.ss_base = signal_stack;
826 #  else
827 	sigstk.ss_sp = signal_stack;
828 #  endif
829 	sigstk.ss_size = get_signal_stack_size();
830 	sigstk.ss_flags = 0;
831 	(void)sigaltstack(&sigstk, NULL);
832 # else
833 	sigstk.ss_sp = signal_stack;
834 	if (stack_grows_downwards)
835 	    sigstk.ss_sp += get_signal_stack_size() - 1;
836 	sigstk.ss_onstack = 0;
837 	(void)sigstack(&sigstk, NULL);
838 # endif
839     }
840 }
841 #endif
842 
843 /*
844  * We need correct prototypes for a signal function, otherwise mean compilers
845  * will barf when the second argument to signal() is ``wrong''.
846  * Let me try it with a few tricky defines from my own osdef.h	(jw).
847  */
848 #if defined(SIGWINCH)
849     static RETSIGTYPE
SIGDEFARG(sigarg)850 sig_winch SIGDEFARG(sigarg)
851 {
852     // this is not required on all systems, but it doesn't hurt anybody
853     signal(SIGWINCH, (RETSIGTYPE (*)())sig_winch);
854     do_resize = TRUE;
855     SIGRETURN;
856 }
857 #endif
858 
859 #if defined(SIGINT)
860     static RETSIGTYPE
SIGDEFARG(sigarg)861 catch_sigint SIGDEFARG(sigarg)
862 {
863     // this is not required on all systems, but it doesn't hurt anybody
864     signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
865     got_int = TRUE;
866     SIGRETURN;
867 }
868 #endif
869 
870 #if defined(SIGUSR1)
871     static RETSIGTYPE
SIGDEFARG(sigarg)872 catch_sigusr1 SIGDEFARG(sigarg)
873 {
874     // this is not required on all systems, but it doesn't hurt anybody
875     signal(SIGUSR1, (RETSIGTYPE (*)())catch_sigusr1);
876     got_sigusr1 = TRUE;
877     SIGRETURN;
878 }
879 #endif
880 
881 #if defined(SIGPWR)
882     static RETSIGTYPE
SIGDEFARG(sigarg)883 catch_sigpwr SIGDEFARG(sigarg)
884 {
885     // this is not required on all systems, but it doesn't hurt anybody
886     signal(SIGPWR, (RETSIGTYPE (*)())catch_sigpwr);
887     /*
888      * I'm not sure we get the SIGPWR signal when the system is really going
889      * down or when the batteries are almost empty.  Just preserve the swap
890      * files and don't exit, that can't do any harm.
891      */
892     ml_sync_all(FALSE, FALSE);
893     SIGRETURN;
894 }
895 #endif
896 
897 #ifdef SET_SIG_ALARM
898 /*
899  * signal function for alarm().
900  */
901     static RETSIGTYPE
SIGDEFARG(sigarg)902 sig_alarm SIGDEFARG(sigarg)
903 {
904     // doesn't do anything, just to break a system call
905     sig_alarm_called = TRUE;
906     SIGRETURN;
907 }
908 #endif
909 
910 #if (defined(HAVE_SETJMP_H) \
911 	&& ((defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) \
912 	    || defined(FEAT_LIBCALL))) \
913     || defined(PROTO)
914 # define USING_SETJMP 1
915 
916 // argument to SETJMP()
917 static JMP_BUF lc_jump_env;
918 
919 # ifdef SIGHASARG
920 // Caught signal number, 0 when no signal was caught; used for mch_libcall().
921 // Volatile because it is used in signal handlers.
922 static volatile sig_atomic_t lc_signal;
923 # endif
924 
925 // TRUE when lc_jump_env is valid.
926 // Volatile because it is used in signal handler deathtrap().
927 static volatile sig_atomic_t lc_active INIT(= FALSE);
928 
929 /*
930  * A simplistic version of setjmp() that only allows one level of using.
931  * Used to protect areas where we could crash.
932  * Don't call twice before calling mch_endjmp()!.
933  *
934  * Usage:
935  *	mch_startjmp();
936  *	if (SETJMP(lc_jump_env) != 0)
937  *	{
938  *	    mch_didjmp();
939  *	    emsg("crash!");
940  *	}
941  *	else
942  *	{
943  *	    do_the_work;
944  *	    mch_endjmp();
945  *	}
946  * Note: Can't move SETJMP() here, because a function calling setjmp() must
947  * not return before the saved environment is used.
948  * Returns OK for normal return, FAIL when the protected code caused a
949  * problem and LONGJMP() was used.
950  */
951     static void
mch_startjmp(void)952 mch_startjmp(void)
953 {
954 # ifdef SIGHASARG
955     lc_signal = 0;
956 # endif
957     lc_active = TRUE;
958 }
959 
960     static void
mch_endjmp(void)961 mch_endjmp(void)
962 {
963     lc_active = FALSE;
964 }
965 
966     static void
mch_didjmp(void)967 mch_didjmp(void)
968 {
969 # if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
970     // On FreeBSD the signal stack has to be reset after using siglongjmp(),
971     // otherwise catching the signal only works once.
972     init_signal_stack();
973 # endif
974 }
975 #endif
976 
977 /*
978  * This function handles deadly signals.
979  * It tries to preserve any swap files and exit properly.
980  * (partly from Elvis).
981  * NOTE: Avoid unsafe functions, such as allocating memory, they can result in
982  * a deadlock.
983  */
984     static RETSIGTYPE
SIGDEFARG(sigarg)985 deathtrap SIGDEFARG(sigarg)
986 {
987     static int	entered = 0;	    // count the number of times we got here.
988 				    // Note: when memory has been corrupted
989 				    // this may get an arbitrary value!
990 #ifdef SIGHASARG
991     int		i;
992 #endif
993 
994 #if defined(USING_SETJMP)
995     /*
996      * Catch a crash in protected code.
997      * Restores the environment saved in lc_jump_env, which looks like
998      * SETJMP() returns 1.
999      */
1000     if (lc_active)
1001     {
1002 # if defined(SIGHASARG)
1003 	lc_signal = sigarg;
1004 # endif
1005 	lc_active = FALSE;	// don't jump again
1006 	LONGJMP(lc_jump_env, 1);
1007 	// NOTREACHED
1008     }
1009 #endif
1010 
1011 #ifdef SIGHASARG
1012 # ifdef SIGQUIT
1013     // While in mch_delay() we go to cooked mode to allow a CTRL-C to
1014     // interrupt us.  But in cooked mode we may also get SIGQUIT, e.g., when
1015     // pressing CTRL-\, but we don't want Vim to exit then.
1016     if (in_mch_delay && sigarg == SIGQUIT)
1017 	SIGRETURN;
1018 # endif
1019 
1020     // When SIGHUP, SIGQUIT, etc. are blocked: postpone the effect and return
1021     // here.  This avoids that a non-reentrant function is interrupted, e.g.,
1022     // free().  Calling free() again may then cause a crash.
1023     if (entered == 0
1024 	    && (0
1025 # ifdef SIGHUP
1026 		|| sigarg == SIGHUP
1027 # endif
1028 # ifdef SIGQUIT
1029 		|| sigarg == SIGQUIT
1030 # endif
1031 # ifdef SIGTERM
1032 		|| sigarg == SIGTERM
1033 # endif
1034 # ifdef SIGPWR
1035 		|| sigarg == SIGPWR
1036 # endif
1037 # ifdef SIGUSR1
1038 		|| sigarg == SIGUSR1
1039 # endif
1040 # ifdef SIGUSR2
1041 		|| sigarg == SIGUSR2
1042 # endif
1043 		)
1044 	    && !vim_handle_signal(sigarg))
1045 	SIGRETURN;
1046 #endif
1047 
1048     // Remember how often we have been called.
1049     ++entered;
1050 
1051     // Executing autocommands is likely to use more stack space than we have
1052     // available in the signal stack.
1053     block_autocmds();
1054 
1055 #ifdef FEAT_EVAL
1056     // Set the v:dying variable.
1057     set_vim_var_nr(VV_DYING, (long)entered);
1058 #endif
1059     v_dying = entered;
1060 
1061 #ifdef HAVE_STACK_LIMIT
1062     // Since we are now using the signal stack, need to reset the stack
1063     // limit.  Otherwise using a regexp will fail.
1064     get_stack_limit();
1065 #endif
1066 
1067 #if 0
1068     // This is for opening gdb the moment Vim crashes.
1069     // You need to manually adjust the file name and Vim executable name.
1070     // Suggested by SungHyun Nam.
1071     {
1072 # define VI_GDB_FILE "/tmp/vimgdb"
1073 # define VIM_NAME "/usr/bin/vim"
1074 	FILE *fp = fopen(VI_GDB_FILE, "w");
1075 	if (fp)
1076 	{
1077 	    fprintf(fp,
1078 		    "file %s\n"
1079 		    "attach %d\n"
1080 		    "set height 1000\n"
1081 		    "bt full\n"
1082 		    , VIM_NAME, getpid());
1083 	    fclose(fp);
1084 	    system("xterm -e gdb -x "VI_GDB_FILE);
1085 	    unlink(VI_GDB_FILE);
1086 	}
1087     }
1088 #endif
1089 
1090 #ifdef SIGHASARG
1091     // try to find the name of this signal
1092     for (i = 0; signal_info[i].sig != -1; i++)
1093 	if (sigarg == signal_info[i].sig)
1094 	    break;
1095     deadly_signal = sigarg;
1096 #endif
1097 
1098     full_screen = FALSE;	// don't write message to the GUI, it might be
1099 				// part of the problem...
1100     /*
1101      * If something goes wrong after entering here, we may get here again.
1102      * When this happens, give a message and try to exit nicely (resetting the
1103      * terminal mode, etc.)
1104      * When this happens twice, just exit, don't even try to give a message,
1105      * stack may be corrupt or something weird.
1106      * When this still happens again (or memory was corrupted in such a way
1107      * that "entered" was clobbered) use _exit(), don't try freeing resources.
1108      */
1109     if (entered >= 3)
1110     {
1111 	reset_signals();	// don't catch any signals anymore
1112 	may_core_dump();
1113 	if (entered >= 4)
1114 	    _exit(8);
1115 	exit(7);
1116     }
1117     if (entered == 2)
1118     {
1119 	// No translation, it may call malloc().
1120 	OUT_STR("Vim: Double signal, exiting\n");
1121 	out_flush();
1122 	getout(1);
1123     }
1124 
1125     // No translation, it may call malloc().
1126 #ifdef SIGHASARG
1127     sprintf((char *)IObuff, "Vim: Caught deadly signal %s\r\n",
1128 							 signal_info[i].name);
1129 #else
1130     sprintf((char *)IObuff, "Vim: Caught deadly signal\r\n");
1131 #endif
1132 
1133     // Preserve files and exit.  This sets the really_exiting flag to prevent
1134     // calling free().
1135     preserve_exit();
1136 
1137     // NOTREACHED
1138 
1139 #ifdef NBDEBUG
1140     reset_signals();
1141     may_core_dump();
1142     abort();
1143 #endif
1144 
1145     SIGRETURN;
1146 }
1147 
1148 /*
1149  * Invoked after receiving SIGCONT.  We don't know what happened while
1150  * sleeping, deal with part of that.
1151  */
1152     static void
after_sigcont(void)1153 after_sigcont(void)
1154 {
1155 # ifdef FEAT_TITLE
1156     // Don't change "oldtitle" in a signal handler, set a flag to obtain it
1157     // again later.
1158     oldtitle_outdated = TRUE;
1159 # endif
1160     settmode(TMODE_RAW);
1161     need_check_timestamps = TRUE;
1162     did_check_timestamps = FALSE;
1163 }
1164 
1165 #if defined(SIGCONT)
1166 static RETSIGTYPE sigcont_handler SIGPROTOARG;
1167 static volatile sig_atomic_t in_mch_suspend = FALSE;
1168 
1169 /*
1170  * With multi-threading, suspending might not work immediately.  Catch the
1171  * SIGCONT signal, which will be used as an indication whether the suspending
1172  * has been done or not.
1173  *
1174  * On Linux, signal is not always handled immediately either.
1175  * See https://bugs.launchpad.net/bugs/291373
1176  * Probably because the signal is handled in another thread.
1177  *
1178  * volatile because it is used in signal handler sigcont_handler().
1179  */
1180 static volatile sig_atomic_t sigcont_received;
1181 static RETSIGTYPE sigcont_handler SIGPROTOARG;
1182 
1183 /*
1184  * signal handler for SIGCONT
1185  */
1186     static RETSIGTYPE
SIGDEFARG(sigarg)1187 sigcont_handler SIGDEFARG(sigarg)
1188 {
1189     if (in_mch_suspend)
1190     {
1191 	sigcont_received = TRUE;
1192     }
1193     else
1194     {
1195 	// We didn't suspend ourselves, assume we were stopped by a SIGSTOP
1196 	// signal (which can't be intercepted) and get a SIGCONT.  Need to get
1197 	// back to a sane mode. We should redraw, but we can't really do that
1198 	// in a signal handler, do a redraw later.
1199 	after_sigcont();
1200 	redraw_later(CLEAR);
1201 	cursor_on_force();
1202 	out_flush();
1203     }
1204 
1205     SIGRETURN;
1206 }
1207 #endif
1208 
1209 #if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
1210 # ifdef USE_SYSTEM
1211 static void *clip_star_save = NULL;
1212 static void *clip_plus_save = NULL;
1213 # endif
1214 
1215 /*
1216  * Called when Vim is going to sleep or execute a shell command.
1217  * We can't respond to requests for the X selections.  Lose them, otherwise
1218  * other applications will hang.  But first copy the text to cut buffer 0.
1219  */
1220     static void
loose_clipboard(void)1221 loose_clipboard(void)
1222 {
1223     if (clip_star.owned || clip_plus.owned)
1224     {
1225 	x11_export_final_selection();
1226 	if (clip_star.owned)
1227 	    clip_lose_selection(&clip_star);
1228 	if (clip_plus.owned)
1229 	    clip_lose_selection(&clip_plus);
1230 	if (x11_display != NULL)
1231 	    XFlush(x11_display);
1232     }
1233 }
1234 
1235 # ifdef USE_SYSTEM
1236 /*
1237  * Save clipboard text to restore later.
1238  */
1239     static void
save_clipboard(void)1240 save_clipboard(void)
1241 {
1242     if (clip_star.owned)
1243 	clip_star_save = get_register('*', TRUE);
1244     if (clip_plus.owned)
1245 	clip_plus_save = get_register('+', TRUE);
1246 }
1247 
1248 /*
1249  * Restore clipboard text if no one own the X selection.
1250  */
1251     static void
restore_clipboard(void)1252 restore_clipboard(void)
1253 {
1254     if (clip_star_save != NULL)
1255     {
1256 	if (!clip_gen_owner_exists(&clip_star))
1257 	    put_register('*', clip_star_save);
1258 	else
1259 	    free_register(clip_star_save);
1260 	clip_star_save = NULL;
1261     }
1262     if (clip_plus_save != NULL)
1263     {
1264 	if (!clip_gen_owner_exists(&clip_plus))
1265 	    put_register('+', clip_plus_save);
1266 	else
1267 	    free_register(clip_plus_save);
1268 	clip_plus_save = NULL;
1269     }
1270 }
1271 # endif
1272 #endif
1273 
1274 /*
1275  * If the machine has job control, use it to suspend the program,
1276  * otherwise fake it by starting a new shell.
1277  */
1278     void
mch_suspend(void)1279 mch_suspend(void)
1280 {
1281     if (ignore_sigtstp)
1282 	return;
1283 
1284 #if defined(SIGTSTP)
1285     in_mch_suspend = TRUE;
1286 
1287     out_flush();	    // needed to make cursor visible on some systems
1288     settmode(TMODE_COOK);
1289     out_flush();	    // needed to disable mouse on some systems
1290 
1291 # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
1292     loose_clipboard();
1293 # endif
1294 # if defined(SIGCONT)
1295     sigcont_received = FALSE;
1296 # endif
1297 
1298     kill(0, SIGTSTP);	    // send ourselves a STOP signal
1299 
1300 # if defined(SIGCONT)
1301     /*
1302      * Wait for the SIGCONT signal to be handled. It generally happens
1303      * immediately, but somehow not all the time, probably because it's handled
1304      * in another thread. Do not call pause() because there would be race
1305      * condition which would hang Vim if signal happened in between the test of
1306      * sigcont_received and the call to pause(). If signal is not yet received,
1307      * sleep 0, 1, 2, 3 ms. Don't bother waiting further if signal is not
1308      * received after 1+2+3 ms (not expected to happen).
1309      */
1310     {
1311 	long wait_time;
1312 
1313 	for (wait_time = 0; !sigcont_received && wait_time <= 3L; wait_time++)
1314 	    mch_delay(wait_time, 0);
1315     }
1316 # endif
1317     in_mch_suspend = FALSE;
1318 
1319     after_sigcont();
1320 #else
1321     suspend_shell();
1322 #endif
1323 }
1324 
1325     void
mch_init(void)1326 mch_init(void)
1327 {
1328     Columns = 80;
1329     Rows = 24;
1330 
1331     out_flush();
1332 
1333 #ifdef SIGTSTP
1334     // Check whether we were invoked with SIGTSTP set to be ignored. If it is
1335     // that indicates the shell (or program) that launched us does not support
1336     // tty job control and thus we should ignore that signal. If invoked as a
1337     // restricted editor (e.g., as "rvim") SIGTSTP is always ignored.
1338     ignore_sigtstp = restricted || SIG_IGN == signal(SIGTSTP, SIG_ERR);
1339 #endif
1340     set_signals();
1341 
1342 #ifdef MACOS_CONVERT
1343     mac_conv_init();
1344 #endif
1345 #ifdef FEAT_CYGWIN_WIN32_CLIPBOARD
1346     win_clip_init();
1347 #endif
1348 }
1349 
1350     static void
set_signals(void)1351 set_signals(void)
1352 {
1353 #if defined(SIGWINCH)
1354     /*
1355      * WINDOW CHANGE signal is handled with sig_winch().
1356      */
1357     signal(SIGWINCH, (RETSIGTYPE (*)())sig_winch);
1358 #endif
1359 
1360 #ifdef SIGTSTP
1361     // See mch_init() for the conditions under which we ignore SIGTSTP.
1362     signal(SIGTSTP, ignore_sigtstp ? SIG_IGN : SIG_DFL);
1363 #endif
1364 #if defined(SIGCONT)
1365     signal(SIGCONT, sigcont_handler);
1366 #endif
1367 #ifdef SIGPIPE
1368     /*
1369      * We want to ignore breaking of PIPEs.
1370      */
1371     signal(SIGPIPE, SIG_IGN);
1372 #endif
1373 
1374 #ifdef SIGINT
1375     catch_int_signal();
1376 #endif
1377 
1378 #ifdef SIGUSR1
1379     /*
1380      * Call user's handler on SIGUSR1
1381      */
1382     signal(SIGUSR1, (RETSIGTYPE (*)())catch_sigusr1);
1383 #endif
1384 
1385     /*
1386      * Ignore alarm signals (Perl's alarm() generates it).
1387      */
1388 #ifdef SIGALRM
1389     signal(SIGALRM, SIG_IGN);
1390 #endif
1391 
1392 #ifdef SIGPWR
1393     /*
1394      * Catch SIGPWR (power failure?) to preserve the swap files, so that no
1395      * work will be lost.
1396      */
1397     signal(SIGPWR, (RETSIGTYPE (*)())catch_sigpwr);
1398 #endif
1399 
1400     /*
1401      * Arrange for other signals to gracefully shutdown Vim.
1402      */
1403     catch_signals(deathtrap, SIG_ERR);
1404 
1405 #if defined(FEAT_GUI) && defined(SIGHUP)
1406     /*
1407      * When the GUI is running, ignore the hangup signal.
1408      */
1409     if (gui.in_use)
1410 	signal(SIGHUP, SIG_IGN);
1411 #endif
1412 }
1413 
1414 #if defined(SIGINT) || defined(PROTO)
1415 /*
1416  * Catch CTRL-C (only works while in Cooked mode).
1417  */
1418     static void
catch_int_signal(void)1419 catch_int_signal(void)
1420 {
1421     signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
1422 }
1423 #endif
1424 
1425     void
reset_signals(void)1426 reset_signals(void)
1427 {
1428     catch_signals(SIG_DFL, SIG_DFL);
1429 #if defined(SIGCONT)
1430     // SIGCONT isn't in the list, because its default action is ignore
1431     signal(SIGCONT, SIG_DFL);
1432 #endif
1433 }
1434 
1435     static void
catch_signals(RETSIGTYPE (* func_deadly)(),RETSIGTYPE (* func_other)())1436 catch_signals(
1437     RETSIGTYPE (*func_deadly)(),
1438     RETSIGTYPE (*func_other)())
1439 {
1440     int	    i;
1441 
1442     for (i = 0; signal_info[i].sig != -1; i++)
1443     {
1444 	if (signal_info[i].deadly)
1445 	{
1446 #if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION)
1447 	    struct sigaction sa;
1448 
1449 	    // Setup to use the alternate stack for the signal function.
1450 	    sa.sa_handler = func_deadly;
1451 	    sigemptyset(&sa.sa_mask);
1452 # if defined(__linux__) && defined(_REENTRANT)
1453 	    // On Linux, with glibc compiled for kernel 2.2, there is a bug in
1454 	    // thread handling in combination with using the alternate stack:
1455 	    // pthread library functions try to use the stack pointer to
1456 	    // identify the current thread, causing a SEGV signal, which
1457 	    // recursively calls deathtrap() and hangs.
1458 	    sa.sa_flags = 0;
1459 # else
1460 	    sa.sa_flags = SA_ONSTACK;
1461 # endif
1462 	    sigaction(signal_info[i].sig, &sa, NULL);
1463 #else
1464 # if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGVEC)
1465 	    struct sigvec sv;
1466 
1467 	    // Setup to use the alternate stack for the signal function.
1468 	    sv.sv_handler = func_deadly;
1469 	    sv.sv_mask = 0;
1470 	    sv.sv_flags = SV_ONSTACK;
1471 	    sigvec(signal_info[i].sig, &sv, NULL);
1472 # else
1473 	    signal(signal_info[i].sig, func_deadly);
1474 # endif
1475 #endif
1476 	}
1477 	else if (func_other != SIG_ERR)
1478 	{
1479 	    // Deal with non-deadly signals.
1480 #ifdef SIGTSTP
1481 	    signal(signal_info[i].sig,
1482 		    signal_info[i].sig == SIGTSTP && ignore_sigtstp
1483 						       ? SIG_IGN : func_other);
1484 #else
1485 	    signal(signal_info[i].sig, func_other);
1486 #endif
1487 	}
1488     }
1489 }
1490 
1491 #ifdef HAVE_SIGPROCMASK
1492     static void
block_signals(sigset_t * set)1493 block_signals(sigset_t *set)
1494 {
1495     sigset_t	newset;
1496     int		i;
1497 
1498     sigemptyset(&newset);
1499 
1500     for (i = 0; signal_info[i].sig != -1; i++)
1501 	sigaddset(&newset, signal_info[i].sig);
1502 
1503 # if defined(SIGCONT)
1504     // SIGCONT isn't in the list, because its default action is ignore
1505     sigaddset(&newset, SIGCONT);
1506 # endif
1507 
1508     sigprocmask(SIG_BLOCK, &newset, set);
1509 }
1510 
1511     static void
unblock_signals(sigset_t * set)1512 unblock_signals(sigset_t *set)
1513 {
1514     sigprocmask(SIG_SETMASK, set, NULL);
1515 }
1516 #endif
1517 
1518 /*
1519  * Handling of SIGHUP, SIGQUIT and SIGTERM:
1520  * "when" == a signal:       when busy, postpone and return FALSE, otherwise
1521  *			     return TRUE
1522  * "when" == SIGNAL_BLOCK:   Going to be busy, block signals
1523  * "when" == SIGNAL_UNBLOCK: Going to wait, unblock signals, use postponed
1524  *			     signal
1525  * Returns TRUE when Vim should exit.
1526  */
1527     int
vim_handle_signal(int sig)1528 vim_handle_signal(int sig)
1529 {
1530     static int got_signal = 0;
1531     static int blocked = TRUE;
1532 
1533     switch (sig)
1534     {
1535 	case SIGNAL_BLOCK:   blocked = TRUE;
1536 			     break;
1537 
1538 	case SIGNAL_UNBLOCK: blocked = FALSE;
1539 			     if (got_signal != 0)
1540 			     {
1541 				 kill(getpid(), got_signal);
1542 				 got_signal = 0;
1543 			     }
1544 			     break;
1545 
1546 	default:	     if (!blocked)
1547 				 return TRUE;	// exit!
1548 			     got_signal = sig;
1549 #ifdef SIGPWR
1550 			     if (sig != SIGPWR)
1551 #endif
1552 				 got_int = TRUE;    // break any loops
1553 			     break;
1554     }
1555     return FALSE;
1556 }
1557 
1558 /*
1559  * Check_win checks whether we have an interactive stdout.
1560  */
1561     int
mch_check_win(int argc UNUSED,char ** argv UNUSED)1562 mch_check_win(int argc UNUSED, char **argv UNUSED)
1563 {
1564     if (isatty(1))
1565 	return OK;
1566     return FAIL;
1567 }
1568 
1569 /*
1570  * Return TRUE if the input comes from a terminal, FALSE otherwise.
1571  */
1572     int
mch_input_isatty(void)1573 mch_input_isatty(void)
1574 {
1575     if (isatty(read_cmd_fd))
1576 	return TRUE;
1577     return FALSE;
1578 }
1579 
1580 #ifdef FEAT_X11
1581 
1582 # if defined(ELAPSED_TIMEVAL) \
1583 	&& (defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE))
1584 
1585 /*
1586  * Give a message about the elapsed time for opening the X window.
1587  */
1588     static void
xopen_message(long elapsed_msec)1589 xopen_message(long elapsed_msec)
1590 {
1591     smsg(_("Opening the X display took %ld msec"), elapsed_msec);
1592 }
1593 # endif
1594 #endif
1595 
1596 #if defined(FEAT_X11) && (defined(FEAT_TITLE) || defined(FEAT_XCLIPBOARD))
1597 /*
1598  * A few functions shared by X11 title and clipboard code.
1599  */
1600 
1601 static int	got_x_error = FALSE;
1602 
1603 /*
1604  * X Error handler, otherwise X just exits!  (very rude) -- webb
1605  */
1606     static int
x_error_handler(Display * dpy,XErrorEvent * error_event)1607 x_error_handler(Display *dpy, XErrorEvent *error_event)
1608 {
1609     XGetErrorText(dpy, error_event->error_code, (char *)IObuff, IOSIZE);
1610     STRCAT(IObuff, _("\nVim: Got X error\n"));
1611 
1612     // In the GUI we cannot print a message and continue, because no X calls
1613     // are allowed here (causes my system to hang).  Silently continuing seems
1614     // like the best alternative.  Do preserve files, in case we crash.
1615     ml_sync_all(FALSE, FALSE);
1616 
1617 #ifdef FEAT_GUI
1618     if (!gui.in_use)
1619 #endif
1620 	msg((char *)IObuff);
1621 
1622     return 0;		// NOTREACHED
1623 }
1624 
1625 /*
1626  * Another X Error handler, just used to check for errors.
1627  */
1628     static int
x_error_check(Display * dpy UNUSED,XErrorEvent * error_event UNUSED)1629 x_error_check(Display *dpy UNUSED, XErrorEvent *error_event UNUSED)
1630 {
1631     got_x_error = TRUE;
1632     return 0;
1633 }
1634 
1635 /*
1636  * Return TRUE when connection to the X server is desired.
1637  */
1638     static int
x_connect_to_server(void)1639 x_connect_to_server(void)
1640 {
1641     // No point in connecting if we are exiting or dying.
1642     if (exiting || v_dying)
1643 	return FALSE;
1644 
1645 #if defined(FEAT_CLIENTSERVER)
1646     if (x_force_connect)
1647 	return TRUE;
1648 #endif
1649     if (x_no_connect)
1650 	return FALSE;
1651 
1652     // Check for a match with "exclude:" from 'clipboard'.
1653     if (clip_exclude_prog != NULL)
1654     {
1655 	// Just in case we get called recursively, return FALSE.  This could
1656 	// happen if vpeekc() is used while executing the prog and it causes a
1657 	// related callback to be invoked.
1658 	if (regprog_in_use(clip_exclude_prog))
1659 	    return FALSE;
1660 
1661 	if (vim_regexec_prog(&clip_exclude_prog, FALSE, T_NAME, (colnr_T)0))
1662 	    return FALSE;
1663     }
1664     return TRUE;
1665 }
1666 
1667 #if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
1668 # if defined(USING_SETJMP)
1669 /*
1670  * An X IO Error handler, used to catch error while opening the display.
1671  */
1672     static int
x_IOerror_check(Display * dpy UNUSED)1673 x_IOerror_check(Display *dpy UNUSED)
1674 {
1675     // This function should not return, it causes exit().  Longjump instead.
1676     LONGJMP(lc_jump_env, 1);
1677 #  if defined(VMS) || defined(__CYGWIN__)
1678     return 0;  // avoid the compiler complains about missing return value
1679 #  endif
1680 }
1681 # endif
1682 
1683 /*
1684  * An X IO Error handler, used to catch terminal errors.
1685  */
1686 static int xterm_dpy_retry_count = 0;
1687 
1688     static int
x_IOerror_handler(Display * dpy UNUSED)1689 x_IOerror_handler(Display *dpy UNUSED)
1690 {
1691     xterm_dpy = NULL;
1692     xterm_dpy_retry_count = 5;  // Try reconnecting five times
1693     x11_window = 0;
1694     x11_display = NULL;
1695     xterm_Shell = (Widget)0;
1696 
1697     // This function should not return, it causes exit().  Longjump instead.
1698     LONGJMP(x_jump_env, 1);
1699 # if defined(VMS) || defined(__CYGWIN__)
1700     return 0;  // avoid the compiler complains about missing return value
1701 # endif
1702 }
1703 
1704 /*
1705  * If the X11 connection was lost try to restore it.
1706  * Helps when the X11 server was stopped and restarted while Vim was inactive
1707  * (e.g. through tmux).
1708  */
1709     static void
may_restore_clipboard(void)1710 may_restore_clipboard(void)
1711 {
1712     // No point in restoring the connecting if we are exiting or dying.
1713     if (!exiting && !v_dying && xterm_dpy_retry_count > 0)
1714     {
1715 	--xterm_dpy_retry_count;
1716 
1717 # ifndef LESSTIF_VERSION
1718 	// This has been reported to avoid Vim getting stuck.
1719 	if (app_context != (XtAppContext)NULL)
1720 	{
1721 	    XtDestroyApplicationContext(app_context);
1722 	    app_context = (XtAppContext)NULL;
1723 	    x11_display = NULL; // freed by XtDestroyApplicationContext()
1724 	}
1725 # endif
1726 
1727 	setup_term_clip();
1728 	get_x11_title(FALSE);
1729     }
1730 }
1731 
1732     void
ex_xrestore(exarg_T * eap)1733 ex_xrestore(exarg_T *eap)
1734 {
1735     if (eap->arg != NULL && STRLEN(eap->arg) > 0)
1736     {
1737         if (xterm_display_allocated)
1738             vim_free(xterm_display);
1739         xterm_display = (char *)vim_strsave(eap->arg);
1740         xterm_display_allocated = TRUE;
1741     }
1742     smsg(_("restoring display %s"), xterm_display == NULL
1743 		    ? (char *)mch_getenv((char_u *)"DISPLAY") : xterm_display);
1744 
1745     clear_xterm_clip();
1746     x11_window = 0;
1747     xterm_dpy_retry_count = 5;  // Try reconnecting five times
1748     may_restore_clipboard();
1749 }
1750 #endif
1751 
1752 /*
1753  * Test if "dpy" and x11_window are valid by getting the window title.
1754  * I don't actually want it yet, so there may be a simpler call to use, but
1755  * this will cause the error handler x_error_check() to be called if anything
1756  * is wrong, such as the window pointer being invalid (as can happen when the
1757  * user changes his DISPLAY, but not his WINDOWID) -- webb
1758  */
1759     static int
test_x11_window(Display * dpy)1760 test_x11_window(Display *dpy)
1761 {
1762     int			(*old_handler)();
1763     XTextProperty	text_prop;
1764 
1765     old_handler = XSetErrorHandler(x_error_check);
1766     got_x_error = FALSE;
1767     if (XGetWMName(dpy, x11_window, &text_prop))
1768 	XFree((void *)text_prop.value);
1769     XSync(dpy, False);
1770     (void)XSetErrorHandler(old_handler);
1771 
1772     if (p_verbose > 0 && got_x_error)
1773 	verb_msg(_("Testing the X display failed"));
1774 
1775     return (got_x_error ? FAIL : OK);
1776 }
1777 #endif
1778 
1779 #ifdef FEAT_TITLE
1780 
1781 #ifdef FEAT_X11
1782 
1783 static int get_x11_thing(int get_title, int test_only);
1784 
1785 /*
1786  * try to get x11 window and display
1787  *
1788  * return FAIL for failure, OK otherwise
1789  */
1790     static int
get_x11_windis(void)1791 get_x11_windis(void)
1792 {
1793     char	    *winid;
1794     static int	    result = -1;
1795 #define XD_NONE	 0	// x11_display not set here
1796 #define XD_HERE	 1	// x11_display opened here
1797 #define XD_GUI	 2	// x11_display used from gui.dpy
1798 #define XD_XTERM 3	// x11_display used from xterm_dpy
1799     static int	    x11_display_from = XD_NONE;
1800     static int	    did_set_error_handler = FALSE;
1801 
1802     if (!did_set_error_handler)
1803     {
1804 	// X just exits if it finds an error otherwise!
1805 	(void)XSetErrorHandler(x_error_handler);
1806 	did_set_error_handler = TRUE;
1807     }
1808 
1809 #if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)
1810     if (gui.in_use)
1811     {
1812 	/*
1813 	 * If the X11 display was opened here before, for the window where Vim
1814 	 * was started, close that one now to avoid a memory leak.
1815 	 */
1816 	if (x11_display_from == XD_HERE && x11_display != NULL)
1817 	{
1818 	    XCloseDisplay(x11_display);
1819 	    x11_display_from = XD_NONE;
1820 	}
1821 	if (gui_get_x11_windis(&x11_window, &x11_display) == OK)
1822 	{
1823 	    x11_display_from = XD_GUI;
1824 	    return OK;
1825 	}
1826 	x11_display = NULL;
1827 	return FAIL;
1828     }
1829     else if (x11_display_from == XD_GUI)
1830     {
1831 	// GUI must have stopped somehow, clear x11_display
1832 	x11_window = 0;
1833 	x11_display = NULL;
1834 	x11_display_from = XD_NONE;
1835     }
1836 #endif
1837 
1838     // When started with the "-X" argument, don't try connecting.
1839     if (!x_connect_to_server())
1840 	return FAIL;
1841 
1842     /*
1843      * If WINDOWID not set, should try another method to find out
1844      * what the current window number is. The only code I know for
1845      * this is very complicated.
1846      * We assume that zero is invalid for WINDOWID.
1847      */
1848     if (x11_window == 0 && (winid = getenv("WINDOWID")) != NULL)
1849 	x11_window = (Window)atol(winid);
1850 
1851 #ifdef FEAT_XCLIPBOARD
1852     if (xterm_dpy == x11_display)
1853 	// x11_display may have been set to xterm_dpy elsewhere
1854 	x11_display_from = XD_XTERM;
1855 
1856     if (xterm_dpy != NULL && x11_window != 0)
1857     {
1858 	// We may have checked it already, but Gnome terminal can move us to
1859 	// another window, so we need to check every time.
1860 	if (x11_display_from != XD_XTERM)
1861 	{
1862 	    /*
1863 	     * If the X11 display was opened here before, for the window where
1864 	     * Vim was started, close that one now to avoid a memory leak.
1865 	     */
1866 	    if (x11_display_from == XD_HERE && x11_display != NULL)
1867 		XCloseDisplay(x11_display);
1868 	    x11_display = xterm_dpy;
1869 	    x11_display_from = XD_XTERM;
1870 	}
1871 	if (test_x11_window(x11_display) == FAIL)
1872 	{
1873 	    // probably bad $WINDOWID
1874 	    x11_window = 0;
1875 	    x11_display = NULL;
1876 	    x11_display_from = XD_NONE;
1877 	    return FAIL;
1878 	}
1879 	return OK;
1880     }
1881 #endif
1882 
1883     if (x11_window == 0 || x11_display == NULL)
1884 	result = -1;
1885 
1886     if (result != -1)	    // Have already been here and set this
1887 	return result;	    // Don't do all these X calls again
1888 
1889     if (x11_window != 0 && x11_display == NULL)
1890     {
1891 #ifdef SET_SIG_ALARM
1892 	RETSIGTYPE (*sig_save)();
1893 #endif
1894 #ifdef ELAPSED_FUNC
1895 	elapsed_T start_tv;
1896 
1897 	if (p_verbose > 0)
1898 	    ELAPSED_INIT(start_tv);
1899 #endif
1900 
1901 #ifdef SET_SIG_ALARM
1902 	/*
1903 	 * Opening the Display may hang if the DISPLAY setting is wrong, or
1904 	 * the network connection is bad.  Set an alarm timer to get out.
1905 	 */
1906 	sig_alarm_called = FALSE;
1907 	sig_save = (RETSIGTYPE (*)())signal(SIGALRM,
1908 						 (RETSIGTYPE (*)())sig_alarm);
1909 	alarm(2);
1910 #endif
1911 	x11_display = XOpenDisplay(NULL);
1912 
1913 #ifdef SET_SIG_ALARM
1914 	alarm(0);
1915 	signal(SIGALRM, (RETSIGTYPE (*)())sig_save);
1916 	if (p_verbose > 0 && sig_alarm_called)
1917 	    verb_msg(_("Opening the X display timed out"));
1918 #endif
1919 	if (x11_display != NULL)
1920 	{
1921 # ifdef ELAPSED_FUNC
1922 	    if (p_verbose > 0)
1923 	    {
1924 		verbose_enter();
1925 		xopen_message(ELAPSED_FUNC(start_tv));
1926 		verbose_leave();
1927 	    }
1928 # endif
1929 	    if (test_x11_window(x11_display) == FAIL)
1930 	    {
1931 		// Maybe window id is bad
1932 		x11_window = 0;
1933 		XCloseDisplay(x11_display);
1934 		x11_display = NULL;
1935 	    }
1936 	    else
1937 		x11_display_from = XD_HERE;
1938 	}
1939     }
1940     if (x11_window == 0 || x11_display == NULL)
1941 	return (result = FAIL);
1942 
1943 # ifdef FEAT_EVAL
1944     set_vim_var_nr(VV_WINDOWID, (long)x11_window);
1945 # endif
1946 
1947     return (result = OK);
1948 }
1949 
1950 /*
1951  * Determine original x11 Window Title
1952  */
1953     static int
get_x11_title(int test_only)1954 get_x11_title(int test_only)
1955 {
1956     return get_x11_thing(TRUE, test_only);
1957 }
1958 
1959 /*
1960  * Determine original x11 Window icon
1961  */
1962     static int
get_x11_icon(int test_only)1963 get_x11_icon(int test_only)
1964 {
1965     int		retval = FALSE;
1966 
1967     retval = get_x11_thing(FALSE, test_only);
1968 
1969     // could not get old icon, use terminal name
1970     if (oldicon == NULL && !test_only)
1971     {
1972 	if (STRNCMP(T_NAME, "builtin_", 8) == 0)
1973 	    oldicon = vim_strsave(T_NAME + 8);
1974 	else
1975 	    oldicon = vim_strsave(T_NAME);
1976     }
1977 
1978     return retval;
1979 }
1980 
1981     static int
get_x11_thing(int get_title,int test_only)1982 get_x11_thing(
1983     int		get_title,	// get title string
1984     int		test_only)
1985 {
1986     XTextProperty	text_prop;
1987     int			retval = FALSE;
1988     Status		status;
1989 
1990     if (get_x11_windis() == OK)
1991     {
1992 	// Get window/icon name if any
1993 	if (get_title)
1994 	    status = XGetWMName(x11_display, x11_window, &text_prop);
1995 	else
1996 	    status = XGetWMIconName(x11_display, x11_window, &text_prop);
1997 
1998 	/*
1999 	 * If terminal is xterm, then x11_window may be a child window of the
2000 	 * outer xterm window that actually contains the window/icon name, so
2001 	 * keep traversing up the tree until a window with a title/icon is
2002 	 * found.
2003 	 */
2004 	// Previously this was only done for xterm and alike.  I don't see a
2005 	// reason why it would fail for other terminal emulators.
2006 	// if (term_is_xterm)
2007 	{
2008 	    Window	    root;
2009 	    Window	    parent;
2010 	    Window	    win = x11_window;
2011 	    Window	   *children;
2012 	    unsigned int    num_children;
2013 
2014 	    while (!status || text_prop.value == NULL)
2015 	    {
2016 		if (!XQueryTree(x11_display, win, &root, &parent, &children,
2017 							       &num_children))
2018 		    break;
2019 		if (children)
2020 		    XFree((void *)children);
2021 		if (parent == root || parent == 0)
2022 		    break;
2023 
2024 		win = parent;
2025 		if (get_title)
2026 		    status = XGetWMName(x11_display, win, &text_prop);
2027 		else
2028 		    status = XGetWMIconName(x11_display, win, &text_prop);
2029 	    }
2030 	}
2031 	if (status && text_prop.value != NULL)
2032 	{
2033 	    retval = TRUE;
2034 	    if (!test_only)
2035 	    {
2036 		if (get_title)
2037 		    vim_free(oldtitle);
2038 		else
2039 		    vim_free(oldicon);
2040 		if (text_prop.encoding == XA_STRING && !has_mbyte)
2041 		{
2042 		    if (get_title)
2043 			oldtitle = vim_strsave((char_u *)text_prop.value);
2044 		    else
2045 			oldicon = vim_strsave((char_u *)text_prop.value);
2046 		}
2047 		else
2048 		{
2049 		    char    **cl;
2050 		    Status  transform_status;
2051 		    int	    n = 0;
2052 
2053 		    transform_status = XmbTextPropertyToTextList(x11_display,
2054 								 &text_prop,
2055 								 &cl, &n);
2056 		    if (transform_status >= Success && n > 0 && cl[0])
2057 		    {
2058 			if (get_title)
2059 			    oldtitle = vim_strsave((char_u *) cl[0]);
2060 			else
2061 			    oldicon = vim_strsave((char_u *) cl[0]);
2062 			XFreeStringList(cl);
2063 		    }
2064 		    else
2065 		    {
2066 			if (get_title)
2067 			    oldtitle = vim_strsave((char_u *)text_prop.value);
2068 			else
2069 			    oldicon = vim_strsave((char_u *)text_prop.value);
2070 		    }
2071 		}
2072 	    }
2073 	    XFree((void *)text_prop.value);
2074 	}
2075     }
2076     return retval;
2077 }
2078 
2079 // Xutf8 functions are not available on older systems. Note that on some
2080 // systems X_HAVE_UTF8_STRING may be defined in a header file but
2081 // Xutf8SetWMProperties() is not in the X11 library.  Configure checks for
2082 // that and defines HAVE_XUTF8SETWMPROPERTIES.
2083 #if defined(X_HAVE_UTF8_STRING)
2084 # if X_HAVE_UTF8_STRING && HAVE_XUTF8SETWMPROPERTIES
2085 #  define USE_UTF8_STRING
2086 # endif
2087 #endif
2088 
2089 /*
2090  * Set x11 Window Title
2091  *
2092  * get_x11_windis() must be called before this and have returned OK
2093  */
2094     static void
set_x11_title(char_u * title)2095 set_x11_title(char_u *title)
2096 {
2097 	// XmbSetWMProperties() and Xutf8SetWMProperties() should use a STRING
2098 	// when possible, COMPOUND_TEXT otherwise.  COMPOUND_TEXT isn't
2099 	// supported everywhere and STRING doesn't work for multi-byte titles.
2100 #ifdef USE_UTF8_STRING
2101     if (enc_utf8)
2102 	Xutf8SetWMProperties(x11_display, x11_window, (const char *)title,
2103 					     NULL, NULL, 0, NULL, NULL, NULL);
2104     else
2105 #endif
2106     {
2107 #if XtSpecificationRelease >= 4
2108 # ifdef FEAT_XFONTSET
2109 	XmbSetWMProperties(x11_display, x11_window, (const char *)title,
2110 					     NULL, NULL, 0, NULL, NULL, NULL);
2111 # else
2112 	XTextProperty	text_prop;
2113 	char		*c_title = (char *)title;
2114 
2115 	// directly from example 3-18 "basicwin" of Xlib Programming Manual
2116 	(void)XStringListToTextProperty(&c_title, 1, &text_prop);
2117 	XSetWMProperties(x11_display, x11_window, &text_prop,
2118 					     NULL, NULL, 0, NULL, NULL, NULL);
2119 # endif
2120 #else
2121 	XStoreName(x11_display, x11_window, (char *)title);
2122 #endif
2123     }
2124     XFlush(x11_display);
2125 }
2126 
2127 /*
2128  * Set x11 Window icon
2129  *
2130  * get_x11_windis() must be called before this and have returned OK
2131  */
2132     static void
set_x11_icon(char_u * icon)2133 set_x11_icon(char_u *icon)
2134 {
2135     // See above for comments about using X*SetWMProperties().
2136 #ifdef USE_UTF8_STRING
2137     if (enc_utf8)
2138 	Xutf8SetWMProperties(x11_display, x11_window, NULL, (const char *)icon,
2139 						   NULL, 0, NULL, NULL, NULL);
2140     else
2141 #endif
2142     {
2143 #if XtSpecificationRelease >= 4
2144 # ifdef FEAT_XFONTSET
2145 	XmbSetWMProperties(x11_display, x11_window, NULL, (const char *)icon,
2146 						   NULL, 0, NULL, NULL, NULL);
2147 # else
2148 	XTextProperty	text_prop;
2149 	char		*c_icon = (char *)icon;
2150 
2151 	(void)XStringListToTextProperty(&c_icon, 1, &text_prop);
2152 	XSetWMProperties(x11_display, x11_window, NULL, &text_prop,
2153 						   NULL, 0, NULL, NULL, NULL);
2154 # endif
2155 #else
2156 	XSetIconName(x11_display, x11_window, (char *)icon);
2157 #endif
2158     }
2159     XFlush(x11_display);
2160 }
2161 
2162 #else  // FEAT_X11
2163 
2164     static int
get_x11_title(int test_only UNUSED)2165 get_x11_title(int test_only UNUSED)
2166 {
2167     return FALSE;
2168 }
2169 
2170     static int
get_x11_icon(int test_only)2171 get_x11_icon(int test_only)
2172 {
2173     if (!test_only)
2174     {
2175 	if (STRNCMP(T_NAME, "builtin_", 8) == 0)
2176 	    oldicon = vim_strsave(T_NAME + 8);
2177 	else
2178 	    oldicon = vim_strsave(T_NAME);
2179     }
2180     return FALSE;
2181 }
2182 
2183 #endif // FEAT_X11
2184 
2185     int
mch_can_restore_title(void)2186 mch_can_restore_title(void)
2187 {
2188     return get_x11_title(TRUE);
2189 }
2190 
2191     int
mch_can_restore_icon(void)2192 mch_can_restore_icon(void)
2193 {
2194     return get_x11_icon(TRUE);
2195 }
2196 
2197 /*
2198  * Set the window title and icon.
2199  */
2200     void
mch_settitle(char_u * title,char_u * icon)2201 mch_settitle(char_u *title, char_u *icon)
2202 {
2203     int		type = 0;
2204     static int	recursive = 0;
2205 
2206     if (T_NAME == NULL)	    // no terminal name (yet)
2207 	return;
2208     if (title == NULL && icon == NULL)	    // nothing to do
2209 	return;
2210 
2211     // When one of the X11 functions causes a deadly signal, we get here again
2212     // recursively.  Avoid hanging then (something is probably locked).
2213     if (recursive)
2214 	return;
2215     ++recursive;
2216 
2217     /*
2218      * if the window ID and the display is known, we may use X11 calls
2219      */
2220 #ifdef FEAT_X11
2221     if (get_x11_windis() == OK)
2222 	type = 1;
2223 #else
2224 # if defined(FEAT_GUI_PHOTON) \
2225     || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_HAIKU)
2226     if (gui.in_use)
2227 	type = 1;
2228 # endif
2229 #endif
2230 
2231     /*
2232      * Note: if "t_ts" is set, title is set with escape sequence rather
2233      *	     than x11 calls, because the x11 calls don't always work
2234      */
2235     if ((type || *T_TS != NUL) && title != NULL)
2236     {
2237 	if (oldtitle_outdated)
2238 	{
2239 	    oldtitle_outdated = FALSE;
2240 	    VIM_CLEAR(oldtitle);
2241 	}
2242 	if (oldtitle == NULL
2243 #ifdef FEAT_GUI
2244 		&& !gui.in_use
2245 #endif
2246 		)		// first call but not in GUI, save title
2247 	    (void)get_x11_title(FALSE);
2248 
2249 	if (*T_TS != NUL)		// it's OK if t_fs is empty
2250 	    term_settitle(title);
2251 #ifdef FEAT_X11
2252 	else
2253 # ifdef FEAT_GUI_GTK
2254 	if (!gui.in_use)		// don't do this if GTK+ is running
2255 # endif
2256 	    set_x11_title(title);		// x11
2257 #endif
2258 #if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_HAIKU) \
2259 	|| defined(FEAT_GUI_PHOTON)
2260 	else
2261 	    gui_mch_settitle(title, icon);
2262 #endif
2263 	unix_did_set_title = TRUE;
2264     }
2265 
2266     if ((type || *T_CIS != NUL) && icon != NULL)
2267     {
2268 	if (oldicon == NULL
2269 #ifdef FEAT_GUI
2270 		&& !gui.in_use
2271 #endif
2272 		)		// first call, save icon
2273 	    get_x11_icon(FALSE);
2274 
2275 	if (*T_CIS != NUL)
2276 	{
2277 	    out_str(T_CIS);			// set icon start
2278 	    out_str_nf(icon);
2279 	    out_str(T_CIE);			// set icon end
2280 	    out_flush();
2281 	}
2282 #ifdef FEAT_X11
2283 	else
2284 # ifdef FEAT_GUI_GTK
2285 	if (!gui.in_use)		// don't do this if GTK+ is running
2286 # endif
2287 	    set_x11_icon(icon);			// x11
2288 #endif
2289 	did_set_icon = TRUE;
2290     }
2291     --recursive;
2292 }
2293 
2294 /*
2295  * Restore the window/icon title.
2296  * "which" is one of:
2297  *  SAVE_RESTORE_TITLE only restore title
2298  *  SAVE_RESTORE_ICON  only restore icon
2299  *  SAVE_RESTORE_BOTH  restore title and icon
2300  */
2301     void
mch_restore_title(int which)2302 mch_restore_title(int which)
2303 {
2304     int	do_push_pop = unix_did_set_title || did_set_icon;
2305 
2306     // only restore the title or icon when it has been set
2307     mch_settitle(((which & SAVE_RESTORE_TITLE) && unix_did_set_title) ?
2308 			(oldtitle ? oldtitle : p_titleold) : NULL,
2309 	       ((which & SAVE_RESTORE_ICON) && did_set_icon) ? oldicon : NULL);
2310 
2311     if (do_push_pop)
2312     {
2313 	// pop and push from/to the stack
2314 	term_pop_title(which);
2315 	term_push_title(which);
2316     }
2317 }
2318 
2319 #endif // FEAT_TITLE
2320 
2321 /*
2322  * Return TRUE if "name" looks like some xterm name.
2323  * Seiichi Sato mentioned that "mlterm" works like xterm.
2324  */
2325     int
vim_is_xterm(char_u * name)2326 vim_is_xterm(char_u *name)
2327 {
2328     if (name == NULL)
2329 	return FALSE;
2330     return (STRNICMP(name, "xterm", 5) == 0
2331 		|| STRNICMP(name, "nxterm", 6) == 0
2332 		|| STRNICMP(name, "kterm", 5) == 0
2333 		|| STRNICMP(name, "mlterm", 6) == 0
2334 		|| STRNICMP(name, "rxvt", 4) == 0
2335 		|| STRNICMP(name, "screen.xterm", 12) == 0
2336 		|| STRCMP(name, "builtin_xterm") == 0);
2337 }
2338 
2339 #if defined(FEAT_MOUSE_XTERM) || defined(PROTO)
2340 /*
2341  * Return TRUE if "name" appears to be that of a terminal
2342  * known to support the xterm-style mouse protocol.
2343  * Relies on term_is_xterm having been set to its correct value.
2344  */
2345     int
use_xterm_like_mouse(char_u * name)2346 use_xterm_like_mouse(char_u *name)
2347 {
2348     return (name != NULL
2349 	    && (term_is_xterm
2350 		|| STRNICMP(name, "screen", 6) == 0
2351 		|| STRNICMP(name, "tmux", 4) == 0
2352 		|| STRICMP(name, "st") == 0
2353 		|| STRNICMP(name, "st-", 3) == 0
2354 		|| STRNICMP(name, "stterm", 6) == 0));
2355 }
2356 #endif
2357 
2358 /*
2359  * Return non-zero when using an xterm mouse, according to 'ttymouse'.
2360  * Return 1 for "xterm".
2361  * Return 2 for "xterm2".
2362  * Return 3 for "urxvt".
2363  * Return 4 for "sgr".
2364  */
2365     int
use_xterm_mouse(void)2366 use_xterm_mouse(void)
2367 {
2368     if (ttym_flags == TTYM_SGR)
2369 	return 4;
2370     if (ttym_flags == TTYM_URXVT)
2371 	return 3;
2372     if (ttym_flags == TTYM_XTERM2)
2373 	return 2;
2374     if (ttym_flags == TTYM_XTERM)
2375 	return 1;
2376     return 0;
2377 }
2378 
2379     int
vim_is_iris(char_u * name)2380 vim_is_iris(char_u *name)
2381 {
2382     if (name == NULL)
2383 	return FALSE;
2384     return (STRNICMP(name, "iris-ansi", 9) == 0
2385 	    || STRCMP(name, "builtin_iris-ansi") == 0);
2386 }
2387 
2388     int
vim_is_vt300(char_u * name)2389 vim_is_vt300(char_u *name)
2390 {
2391     if (name == NULL)
2392 	return FALSE;	       // actually all ANSI comp. terminals should be here
2393     // catch VT100 - VT5xx
2394     return ((STRNICMP(name, "vt", 2) == 0
2395 		&& vim_strchr((char_u *)"12345", name[2]) != NULL)
2396 	    || STRCMP(name, "builtin_vt320") == 0);
2397 }
2398 
2399 /*
2400  * Return TRUE if "name" is a terminal for which 'ttyfast' should be set.
2401  * This should include all windowed terminal emulators.
2402  */
2403     int
vim_is_fastterm(char_u * name)2404 vim_is_fastterm(char_u *name)
2405 {
2406     if (name == NULL)
2407 	return FALSE;
2408     if (vim_is_xterm(name) || vim_is_vt300(name) || vim_is_iris(name))
2409 	return TRUE;
2410     return (   STRNICMP(name, "hpterm", 6) == 0
2411 	    || STRNICMP(name, "sun-cmd", 7) == 0
2412 	    || STRNICMP(name, "screen", 6) == 0
2413 	    || STRNICMP(name, "tmux", 4) == 0
2414 	    || STRNICMP(name, "dtterm", 6) == 0);
2415 }
2416 
2417 /*
2418  * Insert user name in s[len].
2419  * Return OK if a name found.
2420  */
2421     int
mch_get_user_name(char_u * s,int len)2422 mch_get_user_name(char_u *s, int len)
2423 {
2424 #ifdef VMS
2425     vim_strncpy(s, (char_u *)cuserid(NULL), len - 1);
2426     return OK;
2427 #else
2428     return mch_get_uname(getuid(), s, len);
2429 #endif
2430 }
2431 
2432 /*
2433  * Insert user name for "uid" in s[len].
2434  * Return OK if a name found.
2435  */
2436     int
mch_get_uname(uid_t uid,char_u * s,int len)2437 mch_get_uname(uid_t uid, char_u *s, int len)
2438 {
2439 #if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
2440     struct passwd   *pw;
2441 
2442     if ((pw = getpwuid(uid)) != NULL
2443 	    && pw->pw_name != NULL && *(pw->pw_name) != NUL)
2444     {
2445 	vim_strncpy(s, (char_u *)pw->pw_name, len - 1);
2446 	return OK;
2447     }
2448 #endif
2449     sprintf((char *)s, "%d", (int)uid);	    // assumes s is long enough
2450     return FAIL;			    // a number is not a name
2451 }
2452 
2453 /*
2454  * Insert host name is s[len].
2455  */
2456 
2457 #ifdef HAVE_SYS_UTSNAME_H
2458     void
mch_get_host_name(char_u * s,int len)2459 mch_get_host_name(char_u *s, int len)
2460 {
2461     struct utsname vutsname;
2462 
2463     if (uname(&vutsname) < 0)
2464 	*s = NUL;
2465     else
2466 	vim_strncpy(s, (char_u *)vutsname.nodename, len - 1);
2467 }
2468 #else // HAVE_SYS_UTSNAME_H
2469 
2470 # ifdef HAVE_SYS_SYSTEMINFO_H
2471 #  define gethostname(nam, len) sysinfo(SI_HOSTNAME, nam, len)
2472 # endif
2473 
2474     void
mch_get_host_name(char_u * s,int len)2475 mch_get_host_name(char_u *s, int len)
2476 {
2477 # ifdef VAXC
2478     vaxc$gethostname((char *)s, len);
2479 # else
2480     gethostname((char *)s, len);
2481 # endif
2482     s[len - 1] = NUL;	// make sure it's terminated
2483 }
2484 #endif // HAVE_SYS_UTSNAME_H
2485 
2486 /*
2487  * return process ID
2488  */
2489     long
mch_get_pid(void)2490 mch_get_pid(void)
2491 {
2492     return (long)getpid();
2493 }
2494 
2495 /*
2496  * return TRUE if process "pid" is still running
2497  */
2498     int
mch_process_running(long pid)2499 mch_process_running(long pid)
2500 {
2501     // If there is no error the process must be running.
2502     if (kill(pid, 0) == 0)
2503 	return TRUE;
2504 #ifdef ESRCH
2505     // If the error is ESRCH then the process is not running.
2506     if (errno == ESRCH)
2507 	return FALSE;
2508 #endif
2509     // If the process is running and owned by another user we get EPERM.  With
2510     // other errors the process might be running, assuming it is then.
2511     return TRUE;
2512 }
2513 
2514 #if !defined(HAVE_STRERROR) && defined(USE_GETCWD)
2515     static char *
strerror(int err)2516 strerror(int err)
2517 {
2518     extern int	    sys_nerr;
2519     extern char	    *sys_errlist[];
2520     static char	    er[20];
2521 
2522     if (err > 0 && err < sys_nerr)
2523 	return (sys_errlist[err]);
2524     sprintf(er, "Error %d", err);
2525     return er;
2526 }
2527 #endif
2528 
2529 /*
2530  * Get name of current directory into buffer "buf" of length "len" bytes.
2531  * "len" must be at least PATH_MAX.
2532  * Return OK for success, FAIL for failure.
2533  */
2534     int
mch_dirname(char_u * buf,int len)2535 mch_dirname(char_u *buf, int len)
2536 {
2537 #if defined(USE_GETCWD)
2538     if (getcwd((char *)buf, len) == NULL)
2539     {
2540 	STRCPY(buf, strerror(errno));
2541 	return FAIL;
2542     }
2543     return OK;
2544 #else
2545     return (getwd((char *)buf) != NULL ? OK : FAIL);
2546 #endif
2547 }
2548 
2549 /*
2550  * Get absolute file name into "buf[len]".
2551  *
2552  * return FAIL for failure, OK for success
2553  */
2554     int
mch_FullName(char_u * fname,char_u * buf,int len,int force)2555 mch_FullName(
2556     char_u	*fname,
2557     char_u	*buf,
2558     int		len,
2559     int		force)		// also expand when already absolute path
2560 {
2561     int		l;
2562 #ifdef HAVE_FCHDIR
2563     int		fd = -1;
2564     static int	dont_fchdir = FALSE;	// TRUE when fchdir() doesn't work
2565 #endif
2566     char_u	olddir[MAXPATHL];
2567     char_u	*p;
2568     int		retval = OK;
2569 #ifdef __CYGWIN__
2570     char_u	posix_fname[MAXPATHL];	// Cygwin docs mention MAX_PATH, but
2571 					// it's not always defined
2572 #endif
2573 
2574 #ifdef VMS
2575     fname = vms_fixfilename(fname);
2576 #endif
2577 
2578 #ifdef __CYGWIN__
2579     /*
2580      * This helps for when "/etc/hosts" is a symlink to "c:/something/hosts".
2581      */
2582 # if CYGWIN_VERSION_DLL_MAJOR >= 1007
2583     // Use CCP_RELATIVE to avoid that it sometimes returns a path that ends in
2584     // a forward slash.
2585     cygwin_conv_path(CCP_WIN_A_TO_POSIX | CCP_RELATIVE,
2586 		     fname, posix_fname, MAXPATHL);
2587 # else
2588     cygwin_conv_to_posix_path(fname, posix_fname);
2589 # endif
2590     fname = posix_fname;
2591 #endif
2592 
2593     // Expand it if forced or not an absolute path.
2594     // Do not do it for "/file", the result is always "/".
2595     if ((force || !mch_isFullName(fname))
2596 	    && ((p = vim_strrchr(fname, '/')) == NULL || p != fname))
2597     {
2598 	/*
2599 	 * If the file name has a path, change to that directory for a moment,
2600 	 * and then get the directory (and get back to where we were).
2601 	 * This will get the correct path name with "../" things.
2602 	 */
2603 	if (p != NULL)
2604 	{
2605 	    if (STRCMP(p, "/..") == 0)
2606 		// for "/path/dir/.." include the "/.."
2607 		p += 3;
2608 
2609 #ifdef HAVE_FCHDIR
2610 	    /*
2611 	     * Use fchdir() if possible, it's said to be faster and more
2612 	     * reliable.  But on SunOS 4 it might not work.  Check this by
2613 	     * doing a fchdir() right now.
2614 	     */
2615 	    if (!dont_fchdir)
2616 	    {
2617 		fd = open(".", O_RDONLY | O_EXTRA, 0);
2618 		if (fd >= 0 && fchdir(fd) < 0)
2619 		{
2620 		    close(fd);
2621 		    fd = -1;
2622 		    dont_fchdir = TRUE;	    // don't try again
2623 		}
2624 	    }
2625 #endif
2626 
2627 	    // Only change directory when we are sure we can return to where
2628 	    // we are now.  After doing "su" chdir(".") might not work.
2629 	    if (
2630 #ifdef HAVE_FCHDIR
2631 		fd < 0 &&
2632 #endif
2633 			(mch_dirname(olddir, MAXPATHL) == FAIL
2634 					   || mch_chdir((char *)olddir) != 0))
2635 	    {
2636 		p = NULL;	// can't get current dir: don't chdir
2637 		retval = FAIL;
2638 	    }
2639 	    else
2640 	    {
2641 		// The directory is copied into buf[], to be able to remove
2642 		// the file name without changing it (could be a string in
2643 		// read-only memory)
2644 		if (p - fname >= len)
2645 		    retval = FAIL;
2646 		else
2647 		{
2648 		    vim_strncpy(buf, fname, p - fname);
2649 		    if (mch_chdir((char *)buf))
2650 		    {
2651 			// Path does not exist (yet).  For a full path fail,
2652 			// will use the path as-is.  For a relative path use
2653 			// the current directory and append the file name.
2654 			if (mch_isFullName(fname))
2655 			    retval = FAIL;
2656 			else
2657 			    p = NULL;
2658 		    }
2659 		    else if (*p == '/')
2660 			fname = p + 1;
2661 		    else
2662 			fname = p;
2663 		    *buf = NUL;
2664 		}
2665 	    }
2666 	}
2667 	if (mch_dirname(buf, len) == FAIL)
2668 	{
2669 	    retval = FAIL;
2670 	    *buf = NUL;
2671 	}
2672 	if (p != NULL)
2673 	{
2674 #ifdef HAVE_FCHDIR
2675 	    if (fd >= 0)
2676 	    {
2677 		if (p_verbose >= 5)
2678 		{
2679 		    verbose_enter();
2680 		    msg("fchdir() to previous dir");
2681 		    verbose_leave();
2682 		}
2683 		l = fchdir(fd);
2684 	    }
2685 	    else
2686 #endif
2687 		l = mch_chdir((char *)olddir);
2688 	    if (l != 0)
2689 		emsg(_(e_prev_dir));
2690 	}
2691 #ifdef HAVE_FCHDIR
2692 	if (fd >= 0)
2693 	    close(fd);
2694 #endif
2695 
2696 	l = STRLEN(buf);
2697 	if (l >= len - 1)
2698 	    retval = FAIL; // no space for trailing "/"
2699 #ifndef VMS
2700 	else if (l > 0 && buf[l - 1] != '/' && *fname != NUL
2701 						   && STRCMP(fname, ".") != 0)
2702 	    STRCAT(buf, "/");
2703 #endif
2704     }
2705 
2706     // Catch file names which are too long.
2707     if (retval == FAIL || (int)(STRLEN(buf) + STRLEN(fname)) >= len)
2708 	return FAIL;
2709 
2710     // Do not append ".", "/dir/." is equal to "/dir".
2711     if (STRCMP(fname, ".") != 0)
2712 	STRCAT(buf, fname);
2713 
2714     return OK;
2715 }
2716 
2717 /*
2718  * Return TRUE if "fname" does not depend on the current directory.
2719  */
2720     int
mch_isFullName(char_u * fname)2721 mch_isFullName(char_u *fname)
2722 {
2723 #ifdef VMS
2724     return ( fname[0] == '/'	       || fname[0] == '.'	    ||
2725 	     strchr((char *)fname,':') || strchr((char *)fname,'"') ||
2726 	    (strchr((char *)fname,'[') && strchr((char *)fname,']'))||
2727 	    (strchr((char *)fname,'<') && strchr((char *)fname,'>'))   );
2728 #else
2729     return (*fname == '/' || *fname == '~');
2730 #endif
2731 }
2732 
2733 #if defined(USE_FNAME_CASE) || defined(PROTO)
2734 /*
2735  * Set the case of the file name, if it already exists.  This will cause the
2736  * file name to remain exactly the same.
2737  * Only required for file systems where case is ignored and preserved.
2738  */
2739     void
fname_case(char_u * name,int len UNUSED)2740 fname_case(
2741     char_u	*name,
2742     int		len UNUSED)  // buffer size, only used when name gets longer
2743 {
2744     struct stat st;
2745     char_u	*slash, *tail;
2746     DIR		*dirp;
2747     struct dirent *dp;
2748 
2749     if (mch_lstat((char *)name, &st) >= 0)
2750     {
2751 	// Open the directory where the file is located.
2752 	slash = vim_strrchr(name, '/');
2753 	if (slash == NULL)
2754 	{
2755 	    dirp = opendir(".");
2756 	    tail = name;
2757 	}
2758 	else
2759 	{
2760 	    *slash = NUL;
2761 	    dirp = opendir((char *)name);
2762 	    *slash = '/';
2763 	    tail = slash + 1;
2764 	}
2765 
2766 	if (dirp != NULL)
2767 	{
2768 	    while ((dp = readdir(dirp)) != NULL)
2769 	    {
2770 		// Only accept names that differ in case and are the same byte
2771 		// length. TODO: accept different length name.
2772 		if (STRICMP(tail, dp->d_name) == 0
2773 			&& STRLEN(tail) == STRLEN(dp->d_name))
2774 		{
2775 		    char_u	newname[MAXPATHL + 1];
2776 		    struct stat st2;
2777 
2778 		    // Verify the inode is equal.
2779 		    vim_strncpy(newname, name, MAXPATHL);
2780 		    vim_strncpy(newname + (tail - name), (char_u *)dp->d_name,
2781 						    MAXPATHL - (tail - name));
2782 		    if (mch_lstat((char *)newname, &st2) >= 0
2783 			    && st.st_ino == st2.st_ino
2784 			    && st.st_dev == st2.st_dev)
2785 		    {
2786 			STRCPY(tail, dp->d_name);
2787 			break;
2788 		    }
2789 		}
2790 	    }
2791 
2792 	    closedir(dirp);
2793 	}
2794     }
2795 }
2796 #endif
2797 
2798 /*
2799  * Get file permissions for 'name'.
2800  * Returns -1 when it doesn't exist.
2801  */
2802     long
mch_getperm(char_u * name)2803 mch_getperm(char_u *name)
2804 {
2805     struct stat statb;
2806 
2807     // Keep the #ifdef outside of stat(), it may be a macro.
2808 #ifdef VMS
2809     if (stat((char *)vms_fixfilename(name), &statb))
2810 #else
2811     if (stat((char *)name, &statb))
2812 #endif
2813 	return -1;
2814 #ifdef __INTERIX
2815     // The top bit makes the value negative, which means the file doesn't
2816     // exist.  Remove the bit, we don't use it.
2817     return statb.st_mode & ~S_ADDACE;
2818 #else
2819     return statb.st_mode;
2820 #endif
2821 }
2822 
2823 /*
2824  * Set file permission for "name" to "perm".
2825  * Return FAIL for failure, OK otherwise.
2826  */
2827     int
mch_setperm(char_u * name,long perm)2828 mch_setperm(char_u *name, long perm)
2829 {
2830     return (chmod((char *)
2831 #ifdef VMS
2832 		    vms_fixfilename(name),
2833 #else
2834 		    name,
2835 #endif
2836 		    (mode_t)perm) == 0 ? OK : FAIL);
2837 }
2838 
2839 #if defined(HAVE_FCHMOD) || defined(PROTO)
2840 /*
2841  * Set file permission for open file "fd" to "perm".
2842  * Return FAIL for failure, OK otherwise.
2843  */
2844     int
mch_fsetperm(int fd,long perm)2845 mch_fsetperm(int fd, long perm)
2846 {
2847     return (fchmod(fd, (mode_t)perm) == 0 ? OK : FAIL);
2848 }
2849 #endif
2850 
2851 #if defined(HAVE_ACL) || defined(PROTO)
2852 # ifdef HAVE_SYS_ACL_H
2853 #  include <sys/acl.h>
2854 # endif
2855 # ifdef HAVE_SYS_ACCESS_H
2856 #  include <sys/access.h>
2857 # endif
2858 
2859 # ifdef HAVE_SOLARIS_ACL
2860 typedef struct vim_acl_solaris_T {
2861     int acl_cnt;
2862     aclent_t *acl_entry;
2863 } vim_acl_solaris_T;
2864 # endif
2865 
2866 #if defined(HAVE_SELINUX) || defined(PROTO)
2867 /*
2868  * Copy security info from "from_file" to "to_file".
2869  */
2870     void
mch_copy_sec(char_u * from_file,char_u * to_file)2871 mch_copy_sec(char_u *from_file, char_u *to_file)
2872 {
2873     if (from_file == NULL)
2874 	return;
2875 
2876     if (selinux_enabled == -1)
2877 	selinux_enabled = is_selinux_enabled();
2878 
2879     if (selinux_enabled > 0)
2880     {
2881 	// Use "char *" instead of "security_context_t" to avoid a deprecation
2882 	// warning.
2883 	char *from_context = NULL;
2884 	char *to_context = NULL;
2885 
2886 	if (getfilecon((char *)from_file, &from_context) < 0)
2887 	{
2888 	    // If the filesystem doesn't support extended attributes,
2889 	    // the original had no special security context and the
2890 	    // target cannot have one either.
2891 	    if (errno == EOPNOTSUPP)
2892 		return;
2893 
2894 	    msg_puts(_("\nCould not get security context for "));
2895 	    msg_outtrans(from_file);
2896 	    msg_putchar('\n');
2897 	    return;
2898 	}
2899 	if (getfilecon((char *)to_file, &to_context) < 0)
2900 	{
2901 	    msg_puts(_("\nCould not get security context for "));
2902 	    msg_outtrans(to_file);
2903 	    msg_putchar('\n');
2904 	    freecon (from_context);
2905 	    return ;
2906 	}
2907 	if (strcmp(from_context, to_context) != 0)
2908 	{
2909 	    if (setfilecon((char *)to_file, from_context) < 0)
2910 	    {
2911 		msg_puts(_("\nCould not set security context for "));
2912 		msg_outtrans(to_file);
2913 		msg_putchar('\n');
2914 	    }
2915 	}
2916 	freecon(to_context);
2917 	freecon(from_context);
2918     }
2919 }
2920 #endif // HAVE_SELINUX
2921 
2922 #if defined(HAVE_SMACK) && !defined(PROTO)
2923 /*
2924  * Copy security info from "from_file" to "to_file".
2925  */
2926     void
mch_copy_sec(char_u * from_file,char_u * to_file)2927 mch_copy_sec(char_u *from_file, char_u *to_file)
2928 {
2929     static const char * const smack_copied_attributes[] =
2930 	{
2931 	    XATTR_NAME_SMACK,
2932 	    XATTR_NAME_SMACKEXEC,
2933 	    XATTR_NAME_SMACKMMAP
2934 	};
2935 
2936     char	buffer[SMACK_LABEL_LEN];
2937     const char	*name;
2938     int		index;
2939     int		ret;
2940     ssize_t	size;
2941 
2942     if (from_file == NULL)
2943 	return;
2944 
2945     for (index = 0 ; index < (int)(sizeof(smack_copied_attributes)
2946 			      / sizeof(smack_copied_attributes)[0]) ; index++)
2947     {
2948 	// get the name of the attribute to copy
2949 	name = smack_copied_attributes[index];
2950 
2951 	// get the value of the attribute in buffer
2952 	size = getxattr((char*)from_file, name, buffer, sizeof(buffer));
2953 	if (size >= 0)
2954 	{
2955 	    // copy the attribute value of buffer
2956 	    ret = setxattr((char*)to_file, name, buffer, (size_t)size, 0);
2957 	    if (ret < 0)
2958 	    {
2959 		vim_snprintf((char *)IObuff, IOSIZE,
2960 			_("Could not set security context %s for %s"),
2961 			name, to_file);
2962 		msg_outtrans(IObuff);
2963 		msg_putchar('\n');
2964 	    }
2965 	}
2966 	else
2967 	{
2968 	    // what reason of not having the attribute value?
2969 	    switch (errno)
2970 	    {
2971 		case ENOTSUP:
2972 		    // extended attributes aren't supported or enabled
2973 		    // should a message be echoed? not sure...
2974 		    return; // leave because it isn't useful to continue
2975 
2976 		case ERANGE:
2977 		default:
2978 		    // no enough size OR unexpected error
2979 		     vim_snprintf((char *)IObuff, IOSIZE,
2980 			    _("Could not get security context %s for %s. Removing it!"),
2981 			    name, from_file);
2982 		    msg_puts((char *)IObuff);
2983 		    msg_putchar('\n');
2984 		    // FALLTHROUGH to remove the attribute
2985 
2986 		case ENODATA:
2987 		    // no attribute of this name
2988 		    ret = removexattr((char*)to_file, name);
2989 		    // Silently ignore errors, apparently this happens when
2990 		    // smack is not actually being used.
2991 		    break;
2992 	    }
2993 	}
2994     }
2995 }
2996 #endif // HAVE_SMACK
2997 
2998 /*
2999  * Return a pointer to the ACL of file "fname" in allocated memory.
3000  * Return NULL if the ACL is not available for whatever reason.
3001  */
3002     vim_acl_T
mch_get_acl(char_u * fname UNUSED)3003 mch_get_acl(char_u *fname UNUSED)
3004 {
3005     vim_acl_T	ret = NULL;
3006 #ifdef HAVE_POSIX_ACL
3007     ret = (vim_acl_T)acl_get_file((char *)fname, ACL_TYPE_ACCESS);
3008 #else
3009 #ifdef HAVE_SOLARIS_ZFS_ACL
3010     acl_t *aclent;
3011 
3012     if (acl_get((char *)fname, 0, &aclent) < 0)
3013 	return NULL;
3014     ret = (vim_acl_T)aclent;
3015 #else
3016 #ifdef HAVE_SOLARIS_ACL
3017     vim_acl_solaris_T   *aclent;
3018 
3019     aclent = malloc(sizeof(vim_acl_solaris_T));
3020     if ((aclent->acl_cnt = acl((char *)fname, GETACLCNT, 0, NULL)) < 0)
3021     {
3022 	free(aclent);
3023 	return NULL;
3024     }
3025     aclent->acl_entry = malloc(aclent->acl_cnt * sizeof(aclent_t));
3026     if (acl((char *)fname, GETACL, aclent->acl_cnt, aclent->acl_entry) < 0)
3027     {
3028 	free(aclent->acl_entry);
3029 	free(aclent);
3030 	return NULL;
3031     }
3032     ret = (vim_acl_T)aclent;
3033 #else
3034 #if defined(HAVE_AIX_ACL)
3035     int		aclsize;
3036     struct acl *aclent;
3037 
3038     aclsize = sizeof(struct acl);
3039     aclent = malloc(aclsize);
3040     if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
3041     {
3042 	if (errno == ENOSPC)
3043 	{
3044 	    aclsize = aclent->acl_len;
3045 	    aclent = realloc(aclent, aclsize);
3046 	    if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
3047 	    {
3048 		free(aclent);
3049 		return NULL;
3050 	    }
3051 	}
3052 	else
3053 	{
3054 	    free(aclent);
3055 	    return NULL;
3056 	}
3057     }
3058     ret = (vim_acl_T)aclent;
3059 #endif // HAVE_AIX_ACL
3060 #endif // HAVE_SOLARIS_ACL
3061 #endif // HAVE_SOLARIS_ZFS_ACL
3062 #endif // HAVE_POSIX_ACL
3063     return ret;
3064 }
3065 
3066 /*
3067  * Set the ACL of file "fname" to "acl" (unless it's NULL).
3068  */
3069     void
mch_set_acl(char_u * fname UNUSED,vim_acl_T aclent)3070 mch_set_acl(char_u *fname UNUSED, vim_acl_T aclent)
3071 {
3072     if (aclent == NULL)
3073 	return;
3074 #ifdef HAVE_POSIX_ACL
3075     acl_set_file((char *)fname, ACL_TYPE_ACCESS, (acl_t)aclent);
3076 #else
3077 #ifdef HAVE_SOLARIS_ZFS_ACL
3078     acl_set((char *)fname, (acl_t *)aclent);
3079 #else
3080 #ifdef HAVE_SOLARIS_ACL
3081     acl((char *)fname, SETACL, ((vim_acl_solaris_T *)aclent)->acl_cnt,
3082 	    ((vim_acl_solaris_T *)aclent)->acl_entry);
3083 #else
3084 #ifdef HAVE_AIX_ACL
3085     chacl((char *)fname, aclent, ((struct acl *)aclent)->acl_len);
3086 #endif // HAVE_AIX_ACL
3087 #endif // HAVE_SOLARIS_ACL
3088 #endif // HAVE_SOLARIS_ZFS_ACL
3089 #endif // HAVE_POSIX_ACL
3090 }
3091 
3092     void
mch_free_acl(vim_acl_T aclent)3093 mch_free_acl(vim_acl_T aclent)
3094 {
3095     if (aclent == NULL)
3096 	return;
3097 #ifdef HAVE_POSIX_ACL
3098     acl_free((acl_t)aclent);
3099 #else
3100 #ifdef HAVE_SOLARIS_ZFS_ACL
3101     acl_free((acl_t *)aclent);
3102 #else
3103 #ifdef HAVE_SOLARIS_ACL
3104     free(((vim_acl_solaris_T *)aclent)->acl_entry);
3105     free(aclent);
3106 #else
3107 #ifdef HAVE_AIX_ACL
3108     free(aclent);
3109 #endif // HAVE_AIX_ACL
3110 #endif // HAVE_SOLARIS_ACL
3111 #endif // HAVE_SOLARIS_ZFS_ACL
3112 #endif // HAVE_POSIX_ACL
3113 }
3114 #endif
3115 
3116 /*
3117  * Set hidden flag for "name".
3118  */
3119     void
mch_hide(char_u * name UNUSED)3120 mch_hide(char_u *name UNUSED)
3121 {
3122     // can't hide a file
3123 }
3124 
3125 /*
3126  * return TRUE if "name" is a directory or a symlink to a directory
3127  * return FALSE if "name" is not a directory
3128  * return FALSE for error
3129  */
3130     int
mch_isdir(char_u * name)3131 mch_isdir(char_u *name)
3132 {
3133     struct stat statb;
3134 
3135     if (*name == NUL)	    // Some stat()s don't flag "" as an error.
3136 	return FALSE;
3137     if (stat((char *)name, &statb))
3138 	return FALSE;
3139     return (S_ISDIR(statb.st_mode) ? TRUE : FALSE);
3140 }
3141 
3142 /*
3143  * return TRUE if "name" is a directory, NOT a symlink to a directory
3144  * return FALSE if "name" is not a directory
3145  * return FALSE for error
3146  */
3147     int
mch_isrealdir(char_u * name)3148 mch_isrealdir(char_u *name)
3149 {
3150     struct stat statb;
3151 
3152     if (*name == NUL)	    // Some stat()s don't flag "" as an error.
3153 	return FALSE;
3154     if (mch_lstat((char *)name, &statb))
3155 	return FALSE;
3156     return (S_ISDIR(statb.st_mode) ? TRUE : FALSE);
3157 }
3158 
3159 /*
3160  * Return 1 if "name" is an executable file, 0 if not or it doesn't exist.
3161  */
3162     static int
executable_file(char_u * name)3163 executable_file(char_u *name)
3164 {
3165     struct stat	st;
3166 
3167     if (stat((char *)name, &st))
3168 	return 0;
3169 #ifdef VMS
3170     // Like on Unix system file can have executable rights but not necessarily
3171     // be an executable, but on Unix is not a default for an ordinary file to
3172     // have an executable flag - on VMS it is in most cases.
3173     // Therefore, this check does not have any sense - let keep us to the
3174     // conventions instead:
3175     // *.COM and *.EXE files are the executables - the rest are not. This is
3176     // not ideal but better then it was.
3177     int vms_executable = 0;
3178     if (S_ISREG(st.st_mode) && mch_access((char *)name, X_OK) == 0)
3179     {
3180 	if (strstr(vms_tolower((char*)name),".exe") != NULL
3181 		|| strstr(vms_tolower((char*)name),".com")!= NULL)
3182 	    vms_executable = 1;
3183     }
3184     return vms_executable;
3185 #else
3186     return S_ISREG(st.st_mode) && mch_access((char *)name, X_OK) == 0;
3187 #endif
3188 }
3189 
3190 /*
3191  * Return TRUE if "name" can be found in $PATH and executed, FALSE if not.
3192  * If "use_path" is FALSE only check if "name" is executable.
3193  * Return -1 if unknown.
3194  */
3195     int
mch_can_exe(char_u * name,char_u ** path,int use_path)3196 mch_can_exe(char_u *name, char_u **path, int use_path)
3197 {
3198     char_u	*buf;
3199     char_u	*p, *e;
3200     int		retval;
3201 
3202     // When "use_path" is false and if it's an absolute or relative path don't
3203     // need to use $PATH.
3204     if (!use_path || gettail(name) != name)
3205     {
3206 	// There must be a path separator, files in the current directory
3207 	// can't be executed.
3208 	if ((use_path || gettail(name) != name) && executable_file(name))
3209 	{
3210 	    if (path != NULL)
3211 	    {
3212 		if (name[0] != '/')
3213 		    *path = FullName_save(name, TRUE);
3214 		else
3215 		    *path = vim_strsave(name);
3216 	    }
3217 	    return TRUE;
3218 	}
3219 	return FALSE;
3220     }
3221 
3222     p = (char_u *)getenv("PATH");
3223     if (p == NULL || *p == NUL)
3224 	return -1;
3225     buf = alloc(STRLEN(name) + STRLEN(p) + 2);
3226     if (buf == NULL)
3227 	return -1;
3228 
3229     /*
3230      * Walk through all entries in $PATH to check if "name" exists there and
3231      * is an executable file.
3232      */
3233     for (;;)
3234     {
3235 	e = (char_u *)strchr((char *)p, ':');
3236 	if (e == NULL)
3237 	    e = p + STRLEN(p);
3238 	if (e - p <= 1)		// empty entry means current dir
3239 	    STRCPY(buf, "./");
3240 	else
3241 	{
3242 	    vim_strncpy(buf, p, e - p);
3243 	    add_pathsep(buf);
3244 	}
3245 	STRCAT(buf, name);
3246 	retval = executable_file(buf);
3247 	if (retval == 1)
3248 	{
3249 	    if (path != NULL)
3250 	    {
3251 		if (buf[0] != '/')
3252 		    *path = FullName_save(buf, TRUE);
3253 		else
3254 		    *path = vim_strsave(buf);
3255 	    }
3256 	    break;
3257 	}
3258 
3259 	if (*e != ':')
3260 	    break;
3261 	p = e + 1;
3262     }
3263 
3264     vim_free(buf);
3265     return retval;
3266 }
3267 
3268 /*
3269  * Check what "name" is:
3270  * NODE_NORMAL: file or directory (or doesn't exist)
3271  * NODE_WRITABLE: writable device, socket, fifo, etc.
3272  * NODE_OTHER: non-writable things
3273  */
3274     int
mch_nodetype(char_u * name)3275 mch_nodetype(char_u *name)
3276 {
3277     struct stat	st;
3278 
3279     if (stat((char *)name, &st))
3280 	return NODE_NORMAL;
3281     if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
3282 	return NODE_NORMAL;
3283     if (S_ISBLK(st.st_mode))	// block device isn't writable
3284 	return NODE_OTHER;
3285     // Everything else is writable?
3286     return NODE_WRITABLE;
3287 }
3288 
3289     void
mch_early_init(void)3290 mch_early_init(void)
3291 {
3292 #ifdef HAVE_CHECK_STACK_GROWTH
3293     int			i;
3294 
3295     check_stack_growth((char *)&i);
3296 
3297 # ifdef HAVE_STACK_LIMIT
3298     get_stack_limit();
3299 # endif
3300 
3301 #endif
3302 
3303     /*
3304      * Setup an alternative stack for signals.  Helps to catch signals when
3305      * running out of stack space.
3306      * Use of sigaltstack() is preferred, it's more portable.
3307      * Ignore any errors.
3308      */
3309 #if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
3310     signal_stack = alloc(get_signal_stack_size());
3311     init_signal_stack();
3312 #endif
3313 }
3314 
3315 #if defined(EXITFREE) || defined(PROTO)
3316     void
mch_free_mem(void)3317 mch_free_mem(void)
3318 {
3319 # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
3320     if (clip_star.owned)
3321 	clip_lose_selection(&clip_star);
3322     if (clip_plus.owned)
3323 	clip_lose_selection(&clip_plus);
3324 # endif
3325 # if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
3326     if (xterm_Shell != (Widget)0)
3327 	XtDestroyWidget(xterm_Shell);
3328 #  ifndef LESSTIF_VERSION
3329     // Lesstif crashes here, lose some memory
3330     if (xterm_dpy != NULL)
3331 	XtCloseDisplay(xterm_dpy);
3332     if (app_context != (XtAppContext)NULL)
3333     {
3334 	XtDestroyApplicationContext(app_context);
3335 #   ifdef FEAT_X11
3336 	x11_display = NULL; // freed by XtDestroyApplicationContext()
3337 #   endif
3338     }
3339 #  endif
3340 # endif
3341 # if defined(FEAT_X11)
3342     if (x11_display != NULL
3343 #  ifdef FEAT_XCLIPBOARD
3344 	    && x11_display != xterm_dpy
3345 #  endif
3346 	    )
3347 	XCloseDisplay(x11_display);
3348 # endif
3349 # if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
3350     VIM_CLEAR(signal_stack);
3351 # endif
3352 # ifdef FEAT_TITLE
3353     vim_free(oldtitle);
3354     vim_free(oldicon);
3355 # endif
3356 }
3357 #endif
3358 
3359 /*
3360  * Output a newline when exiting.
3361  * Make sure the newline goes to the same stream as the text.
3362  */
3363     static void
exit_scroll(void)3364 exit_scroll(void)
3365 {
3366     if (silent_mode)
3367 	return;
3368     if (newline_on_exit || msg_didout)
3369     {
3370 	if (msg_use_printf())
3371 	{
3372 	    if (info_message)
3373 		mch_msg("\n");
3374 	    else
3375 		mch_errmsg("\r\n");
3376 	}
3377 	else
3378 	    out_char('\n');
3379     }
3380     else if (!is_not_a_term())
3381     {
3382 	restore_cterm_colors();		// get original colors back
3383 	msg_clr_eos_force();		// clear the rest of the display
3384 	windgoto((int)Rows - 1, 0);	// may have moved the cursor
3385     }
3386 }
3387 
3388 #ifdef USE_GCOV_FLUSH
3389 extern void __gcov_flush();
3390 #endif
3391 
3392     void
mch_exit(int r)3393 mch_exit(int r)
3394 {
3395     exiting = TRUE;
3396 
3397 #if defined(FEAT_X11) && defined(FEAT_CLIPBOARD)
3398     x11_export_final_selection();
3399 #endif
3400 
3401 #ifdef FEAT_GUI
3402     if (!gui.in_use)
3403 #endif
3404     {
3405 	settmode(TMODE_COOK);
3406 #ifdef FEAT_TITLE
3407 	if (!is_not_a_term())
3408 	{
3409 	    // restore xterm title and icon name
3410 	    mch_restore_title(SAVE_RESTORE_BOTH);
3411 	    term_pop_title(SAVE_RESTORE_BOTH);
3412 	}
3413 #endif
3414 	/*
3415 	 * When t_ti is not empty but it doesn't cause swapping terminal
3416 	 * pages, need to output a newline when msg_didout is set.  But when
3417 	 * t_ti does swap pages it should not go to the shell page.  Do this
3418 	 * before stoptermcap().
3419 	 */
3420 	if (swapping_screen() && !newline_on_exit)
3421 	    exit_scroll();
3422 
3423 	// Stop termcap: May need to check for T_CRV response, which
3424 	// requires RAW mode.
3425 	stoptermcap();
3426 
3427 	/*
3428 	 * A newline is only required after a message in the alternate screen.
3429 	 * This is set to TRUE by wait_return().
3430 	 */
3431 	if (!swapping_screen() || newline_on_exit)
3432 	    exit_scroll();
3433 
3434 	// Cursor may have been switched off without calling starttermcap()
3435 	// when doing "vim -u vimrc" and vimrc contains ":q".
3436 	if (full_screen)
3437 	    cursor_on();
3438     }
3439     out_flush();
3440     ml_close_all(TRUE);		// remove all memfiles
3441 
3442 #ifdef USE_GCOV_FLUSH
3443     // Flush coverage info before possibly being killed by a deadly signal.
3444     __gcov_flush();
3445 #endif
3446 
3447     may_core_dump();
3448 #ifdef FEAT_GUI
3449     if (gui.in_use)
3450 	gui_exit(r);
3451 #endif
3452 
3453 #ifdef MACOS_CONVERT
3454     mac_conv_cleanup();
3455 #endif
3456 
3457 #ifdef __QNX__
3458     // A core dump won't be created if the signal handler
3459     // doesn't return, so we can't call exit()
3460     if (deadly_signal != 0)
3461 	return;
3462 #endif
3463 
3464 #ifdef FEAT_NETBEANS_INTG
3465     netbeans_send_disconnect();
3466 #endif
3467 
3468 #ifdef EXITFREE
3469     free_all_mem();
3470 #endif
3471 
3472     exit(r);
3473 }
3474 
3475     static void
may_core_dump(void)3476 may_core_dump(void)
3477 {
3478     if (deadly_signal != 0)
3479     {
3480 	signal(deadly_signal, SIG_DFL);
3481 	kill(getpid(), deadly_signal);	// Die using the signal we caught
3482     }
3483 }
3484 
3485 #ifndef VMS
3486 
3487 /*
3488  * Get the file descriptor to use for tty operations.
3489  */
3490     static int
get_tty_fd(int fd)3491 get_tty_fd(int fd)
3492 {
3493     int		tty_fd = fd;
3494 
3495 #if defined(HAVE_SVR4_PTYS) && defined(SUN_SYSTEM)
3496     // On SunOS: Get the terminal parameters from "fd", or the slave device of
3497     // "fd" when it is a master device.
3498     if (mch_isatty(fd) > 1)
3499     {
3500 	char *name;
3501 
3502 	name = ptsname(fd);
3503 	if (name == NULL)
3504 	    return -1;
3505 
3506 	tty_fd = open(name, O_RDONLY | O_NOCTTY | O_EXTRA, 0);
3507 	if (tty_fd < 0)
3508 	    return -1;
3509     }
3510 #endif
3511     return tty_fd;
3512 }
3513 
3514     static int
mch_tcgetattr(int fd,void * term)3515 mch_tcgetattr(int fd, void *term)
3516 {
3517     int		tty_fd;
3518     int		retval = -1;
3519 
3520     tty_fd = get_tty_fd(fd);
3521     if (tty_fd >= 0)
3522     {
3523 #ifdef NEW_TTY_SYSTEM
3524 # ifdef HAVE_TERMIOS_H
3525 	retval = tcgetattr(tty_fd, (struct termios *)term);
3526 # else
3527 	retval = ioctl(tty_fd, TCGETA, (struct termio *)term);
3528 # endif
3529 #else
3530 	// for "old" tty systems
3531 	retval = ioctl(tty_fd, TIOCGETP, (struct sgttyb *)term);
3532 #endif
3533 	if (tty_fd != fd)
3534 	    close(tty_fd);
3535     }
3536     return retval;
3537 }
3538 
3539     void
mch_settmode(tmode_T tmode)3540 mch_settmode(tmode_T tmode)
3541 {
3542     static int first = TRUE;
3543 
3544 #ifdef NEW_TTY_SYSTEM
3545 # ifdef HAVE_TERMIOS_H
3546     static struct termios told;
3547 	   struct termios tnew;
3548 # else
3549     static struct termio told;
3550 	   struct termio tnew;
3551 # endif
3552 
3553     if (first)
3554     {
3555 	first = FALSE;
3556 	mch_tcgetattr(read_cmd_fd, &told);
3557     }
3558 
3559     tnew = told;
3560     if (tmode == TMODE_RAW)
3561     {
3562 	// ~ICRNL enables typing ^V^M
3563 	// ~IXON disables CTRL-S stopping output, so that it can be mapped.
3564 	tnew.c_iflag &= ~(ICRNL | IXON);
3565 	tnew.c_lflag &= ~(ICANON | ECHO | ISIG | ECHOE
3566 # if defined(IEXTEN)
3567 		    | IEXTEN	    // IEXTEN enables typing ^V on SOLARIS
3568 # endif
3569 				);
3570 # ifdef ONLCR
3571 	// Don't map NL -> CR NL, we do it ourselves.
3572 	// Also disable expanding tabs if possible.
3573 #  ifdef XTABS
3574 	tnew.c_oflag &= ~(ONLCR | XTABS);
3575 #  else
3576 #   ifdef TAB3
3577 	tnew.c_oflag &= ~(ONLCR | TAB3);
3578 #   else
3579 	tnew.c_oflag &= ~ONLCR;
3580 #   endif
3581 #  endif
3582 # endif
3583 	tnew.c_cc[VMIN] = 1;		// return after 1 char
3584 	tnew.c_cc[VTIME] = 0;		// don't wait
3585     }
3586     else if (tmode == TMODE_SLEEP)
3587     {
3588 	// Also reset ICANON here, otherwise on Solaris select() won't see
3589 	// typeahead characters.
3590 	tnew.c_lflag &= ~(ICANON | ECHO);
3591 	tnew.c_cc[VMIN] = 1;		// return after 1 char
3592 	tnew.c_cc[VTIME] = 0;		// don't wait
3593     }
3594 
3595 # if defined(HAVE_TERMIOS_H)
3596     {
3597 	int	n = 10;
3598 
3599 	// A signal may cause tcsetattr() to fail (e.g., SIGCONT).  Retry a
3600 	// few times.
3601 	while (tcsetattr(read_cmd_fd, TCSANOW, &tnew) == -1
3602 						   && errno == EINTR && n > 0)
3603 	    --n;
3604     }
3605 # else
3606     ioctl(read_cmd_fd, TCSETA, &tnew);
3607 # endif
3608 
3609 #else
3610     /*
3611      * for "old" tty systems
3612      */
3613 # ifndef TIOCSETN
3614 #  define TIOCSETN TIOCSETP	// for hpux 9.0
3615 # endif
3616     static struct sgttyb ttybold;
3617 	   struct sgttyb ttybnew;
3618 
3619     if (first)
3620     {
3621 	first = FALSE;
3622 	mch_tcgetattr(read_cmd_fd, &ttybold);
3623     }
3624 
3625     ttybnew = ttybold;
3626     if (tmode == TMODE_RAW)
3627     {
3628 	ttybnew.sg_flags &= ~(CRMOD | ECHO);
3629 	ttybnew.sg_flags |= RAW;
3630     }
3631     else if (tmode == TMODE_SLEEP)
3632 	ttybnew.sg_flags &= ~(ECHO);
3633     ioctl(read_cmd_fd, TIOCSETN, &ttybnew);
3634 #endif
3635     mch_cur_tmode = tmode;
3636 }
3637 
3638 /*
3639  * Try to get the code for "t_kb" from the stty setting
3640  *
3641  * Even if termcap claims a backspace key, the user's setting *should*
3642  * prevail.  stty knows more about reality than termcap does, and if
3643  * somebody's usual erase key is DEL (which, for most BSD users, it will
3644  * be), they're going to get really annoyed if their erase key starts
3645  * doing forward deletes for no reason. (Eric Fischer)
3646  */
3647     void
get_stty(void)3648 get_stty(void)
3649 {
3650     ttyinfo_T	info;
3651     char_u	buf[2];
3652     char_u	*p;
3653 
3654     if (get_tty_info(read_cmd_fd, &info) == OK)
3655     {
3656 	intr_char = info.interrupt;
3657 	buf[0] = info.backspace;
3658 	buf[1] = NUL;
3659 	add_termcode((char_u *)"kb", buf, FALSE);
3660 
3661 	// If <BS> and <DEL> are now the same, redefine <DEL>.
3662 	p = find_termcode((char_u *)"kD");
3663 	if (p != NULL && p[0] == buf[0] && p[1] == buf[1])
3664 	    do_fixdel(NULL);
3665     }
3666 }
3667 
3668 /*
3669  * Obtain the characters that Backspace and Enter produce on "fd".
3670  * Returns OK or FAIL.
3671  */
3672     int
get_tty_info(int fd,ttyinfo_T * info)3673 get_tty_info(int fd, ttyinfo_T *info)
3674 {
3675 #ifdef NEW_TTY_SYSTEM
3676 # ifdef HAVE_TERMIOS_H
3677     struct termios keys;
3678 # else
3679     struct termio keys;
3680 # endif
3681 
3682     if (mch_tcgetattr(fd, &keys) != -1)
3683     {
3684 	info->backspace = keys.c_cc[VERASE];
3685 	info->interrupt = keys.c_cc[VINTR];
3686 	if (keys.c_iflag & ICRNL)
3687 	    info->enter = NL;
3688 	else
3689 	    info->enter = CAR;
3690 	if (keys.c_oflag & ONLCR)
3691 	    info->nl_does_cr = TRUE;
3692 	else
3693 	    info->nl_does_cr = FALSE;
3694 	return OK;
3695     }
3696 #else
3697     // for "old" tty systems
3698     struct sgttyb keys;
3699 
3700     if (mch_tcgetattr(fd, &keys) != -1)
3701     {
3702 	info->backspace = keys.sg_erase;
3703 	info->interrupt = keys.sg_kill;
3704 	info->enter = CAR;
3705 	info->nl_does_cr = TRUE;
3706 	return OK;
3707     }
3708 #endif
3709     return FAIL;
3710 }
3711 
3712 #endif // VMS
3713 
3714 static int	mouse_ison = FALSE;
3715 
3716 /*
3717  * Set mouse clicks on or off.
3718  */
3719     void
mch_setmouse(int on)3720 mch_setmouse(int on)
3721 {
3722 #ifdef FEAT_BEVAL_TERM
3723     static int	bevalterm_ison = FALSE;
3724 #endif
3725     int		xterm_mouse_vers;
3726 
3727 #if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
3728     if (!on)
3729 	// Make sure not tracing mouse movements.  Important when a button-down
3730 	// was received but no release yet.
3731 	stop_xterm_trace();
3732 #endif
3733 
3734     if (on == mouse_ison
3735 #ifdef FEAT_BEVAL_TERM
3736 	    && p_bevalterm == bevalterm_ison
3737 #endif
3738 	    )
3739 	// return quickly if nothing to do
3740 	return;
3741 
3742     xterm_mouse_vers = use_xterm_mouse();
3743 
3744 #ifdef FEAT_MOUSE_URXVT
3745     if (ttym_flags == TTYM_URXVT)
3746     {
3747 	out_str_nf((char_u *)
3748 		   (on
3749 		   ? IF_EB("\033[?1015h", ESC_STR "[?1015h")
3750 		   : IF_EB("\033[?1015l", ESC_STR "[?1015l")));
3751 	mouse_ison = on;
3752     }
3753 #endif
3754 
3755     if (ttym_flags == TTYM_SGR)
3756     {
3757 	// SGR mode supports columns above 223
3758 	out_str_nf((char_u *)
3759 		   (on
3760 		   ? IF_EB("\033[?1006h", ESC_STR "[?1006h")
3761 		   : IF_EB("\033[?1006l", ESC_STR "[?1006l")));
3762 	mouse_ison = on;
3763     }
3764 
3765 #ifdef FEAT_BEVAL_TERM
3766     if (bevalterm_ison != (p_bevalterm && on))
3767     {
3768 	bevalterm_ison = (p_bevalterm && on);
3769 	if (xterm_mouse_vers > 1 && !bevalterm_ison)
3770 	    // disable mouse movement events, enabling is below
3771 	    out_str_nf((char_u *)
3772 			(IF_EB("\033[?1003l", ESC_STR "[?1003l")));
3773     }
3774 #endif
3775 
3776     if (xterm_mouse_vers > 0)
3777     {
3778 	if (on)	// enable mouse events, use mouse tracking if available
3779 	    out_str_nf((char_u *)
3780 		       (xterm_mouse_vers > 1
3781 			? (
3782 #ifdef FEAT_BEVAL_TERM
3783 			    bevalterm_ison
3784 			       ? IF_EB("\033[?1003h", ESC_STR "[?1003h") :
3785 #endif
3786 			      IF_EB("\033[?1002h", ESC_STR "[?1002h"))
3787 			: IF_EB("\033[?1000h", ESC_STR "[?1000h")));
3788 	else	// disable mouse events, could probably always send the same
3789 	    out_str_nf((char_u *)
3790 		       (xterm_mouse_vers > 1
3791 			? IF_EB("\033[?1002l", ESC_STR "[?1002l")
3792 			: IF_EB("\033[?1000l", ESC_STR "[?1000l")));
3793 	mouse_ison = on;
3794     }
3795 
3796 #ifdef FEAT_MOUSE_DEC
3797     else if (ttym_flags == TTYM_DEC)
3798     {
3799 	if (on)	// enable mouse events
3800 	    out_str_nf((char_u *)"\033[1;2'z\033[1;3'{");
3801 	else	// disable mouse events
3802 	    out_str_nf((char_u *)"\033['z");
3803 	mouse_ison = on;
3804     }
3805 #endif
3806 
3807 #ifdef FEAT_MOUSE_GPM
3808     else
3809     {
3810 	if (on)
3811 	{
3812 	    if (gpm_open())
3813 		mouse_ison = TRUE;
3814 	}
3815 	else
3816 	{
3817 	    gpm_close();
3818 	    mouse_ison = FALSE;
3819 	}
3820     }
3821 #endif
3822 
3823 #ifdef FEAT_SYSMOUSE
3824     else
3825     {
3826 	if (on)
3827 	{
3828 	    if (sysmouse_open() == OK)
3829 		mouse_ison = TRUE;
3830 	}
3831 	else
3832 	{
3833 	    sysmouse_close();
3834 	    mouse_ison = FALSE;
3835 	}
3836     }
3837 #endif
3838 
3839 #ifdef FEAT_MOUSE_JSB
3840     else
3841     {
3842 	if (on)
3843 	{
3844 	    // D - Enable Mouse up/down messages
3845 	    // L - Enable Left Button Reporting
3846 	    // M - Enable Middle Button Reporting
3847 	    // R - Enable Right Button Reporting
3848 	    // K - Enable SHIFT and CTRL key Reporting
3849 	    // + - Enable Advanced messaging of mouse moves and up/down messages
3850 	    // Q - Quiet No Ack
3851 	    // # - Numeric value of mouse pointer required
3852 	    //	  0 = Multiview 2000 cursor, used as standard
3853 	    //	  1 = Windows Arrow
3854 	    //	  2 = Windows I Beam
3855 	    //	  3 = Windows Hour Glass
3856 	    //	  4 = Windows Cross Hair
3857 	    //	  5 = Windows UP Arrow
3858 # ifdef JSBTERM_MOUSE_NONADVANCED
3859 	    // Disables full feedback of pointer movements
3860 	    out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK1Q\033\\",
3861 					 ESC_STR "[0~ZwLMRK1Q" ESC_STR "\\"));
3862 # else
3863 	    out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK+1Q\033\\",
3864 					ESC_STR "[0~ZwLMRK+1Q" ESC_STR "\\"));
3865 # endif
3866 	    mouse_ison = TRUE;
3867 	}
3868 	else
3869 	{
3870 	    out_str_nf((char_u *)IF_EB("\033[0~ZwQ\033\\",
3871 					      ESC_STR "[0~ZwQ" ESC_STR "\\"));
3872 	    mouse_ison = FALSE;
3873 	}
3874     }
3875 #endif
3876 #ifdef FEAT_MOUSE_PTERM
3877     else
3878     {
3879 	// 1 = button press, 6 = release, 7 = drag, 1h...9l = right button
3880 	if (on)
3881 	    out_str_nf("\033[>1h\033[>6h\033[>7h\033[>1h\033[>9l");
3882 	else
3883 	    out_str_nf("\033[>1l\033[>6l\033[>7l\033[>1l\033[>9h");
3884 	mouse_ison = on;
3885     }
3886 #endif
3887 }
3888 
3889 #if defined(FEAT_BEVAL_TERM) || defined(PROTO)
3890 /*
3891  * Called when 'balloonevalterm' changed.
3892  */
3893     void
mch_bevalterm_changed(void)3894 mch_bevalterm_changed(void)
3895 {
3896     mch_setmouse(mouse_ison);
3897 }
3898 #endif
3899 
3900 /*
3901  * Set the mouse termcode, depending on the 'term' and 'ttymouse' options.
3902  */
3903     void
check_mouse_termcode(void)3904 check_mouse_termcode(void)
3905 {
3906 # ifdef FEAT_MOUSE_XTERM
3907     if (use_xterm_mouse()
3908 # ifdef FEAT_MOUSE_URXVT
3909 	    && use_xterm_mouse() != 3
3910 # endif
3911 #  ifdef FEAT_GUI
3912 	    && !gui.in_use
3913 #  endif
3914 	    )
3915     {
3916 	set_mouse_termcode(KS_MOUSE, (char_u *)(term_is_8bit(T_NAME)
3917 		    ? IF_EB("\233M", CSI_STR "M")
3918 		    : IF_EB("\033[M", ESC_STR "[M")));
3919 	if (*p_mouse != NUL)
3920 	{
3921 	    // force mouse off and maybe on to send possibly new mouse
3922 	    // activation sequence to the xterm, with(out) drag tracing.
3923 	    mch_setmouse(FALSE);
3924 	    setmouse();
3925 	}
3926     }
3927     else
3928 	del_mouse_termcode(KS_MOUSE);
3929 # endif
3930 
3931 # ifdef FEAT_MOUSE_GPM
3932     if (!use_xterm_mouse()
3933 #  ifdef FEAT_GUI
3934 	    && !gui.in_use
3935 #  endif
3936 	    )
3937 	set_mouse_termcode(KS_GPM_MOUSE,
3938 				      (char_u *)IF_EB("\033MG", ESC_STR "MG"));
3939     else
3940 	del_mouse_termcode(KS_GPM_MOUSE);
3941 # endif
3942 
3943 # ifdef FEAT_SYSMOUSE
3944     if (!use_xterm_mouse()
3945 #  ifdef FEAT_GUI
3946 	    && !gui.in_use
3947 #  endif
3948 	    )
3949 	set_mouse_termcode(KS_MOUSE, (char_u *)IF_EB("\033MS", ESC_STR "MS"));
3950 # endif
3951 
3952 # ifdef FEAT_MOUSE_JSB
3953     // Conflicts with xterm mouse: "\033[" and "\033[M" ???
3954     if (!use_xterm_mouse()
3955 #  ifdef FEAT_GUI
3956 	    && !gui.in_use
3957 #  endif
3958 	    )
3959 	set_mouse_termcode(KS_JSBTERM_MOUSE,
3960 			       (char_u *)IF_EB("\033[0~zw", ESC_STR "[0~zw"));
3961     else
3962 	del_mouse_termcode(KS_JSBTERM_MOUSE);
3963 # endif
3964 
3965 # ifdef FEAT_MOUSE_NET
3966     // There is no conflict, but one may type "ESC }" from Insert mode.  Don't
3967     // define it in the GUI or when using an xterm.
3968     if (!use_xterm_mouse()
3969 #  ifdef FEAT_GUI
3970 	    && !gui.in_use
3971 #  endif
3972 	    )
3973 	set_mouse_termcode(KS_NETTERM_MOUSE,
3974 				       (char_u *)IF_EB("\033}", ESC_STR "}"));
3975     else
3976 	del_mouse_termcode(KS_NETTERM_MOUSE);
3977 # endif
3978 
3979 # ifdef FEAT_MOUSE_DEC
3980     // Conflicts with xterm mouse: "\033[" and "\033[M"
3981     if (!use_xterm_mouse()
3982 #  ifdef FEAT_GUI
3983 	    && !gui.in_use
3984 #  endif
3985 	    )
3986 	set_mouse_termcode(KS_DEC_MOUSE, (char_u *)(term_is_8bit(T_NAME)
3987 		     ? IF_EB("\233", CSI_STR) : IF_EB("\033[", ESC_STR "[")));
3988     else
3989 	del_mouse_termcode(KS_DEC_MOUSE);
3990 # endif
3991 # ifdef FEAT_MOUSE_PTERM
3992     // same conflict as the dec mouse
3993     if (!use_xterm_mouse()
3994 #  ifdef FEAT_GUI
3995 	    && !gui.in_use
3996 #  endif
3997 	    )
3998 	set_mouse_termcode(KS_PTERM_MOUSE,
3999 				      (char_u *) IF_EB("\033[", ESC_STR "["));
4000     else
4001 	del_mouse_termcode(KS_PTERM_MOUSE);
4002 # endif
4003 # ifdef FEAT_MOUSE_URXVT
4004     if (use_xterm_mouse() == 3
4005 #  ifdef FEAT_GUI
4006 	    && !gui.in_use
4007 #  endif
4008 	    )
4009     {
4010 	set_mouse_termcode(KS_URXVT_MOUSE, (char_u *)(term_is_8bit(T_NAME)
4011 		    ? IF_EB("\233*M", CSI_STR "*M")
4012 		    : IF_EB("\033[*M", ESC_STR "[*M")));
4013 
4014 	if (*p_mouse != NUL)
4015 	{
4016 	    mch_setmouse(FALSE);
4017 	    setmouse();
4018 	}
4019     }
4020     else
4021 	del_mouse_termcode(KS_URXVT_MOUSE);
4022 # endif
4023     if (use_xterm_mouse() == 4
4024 # ifdef FEAT_GUI
4025 	    && !gui.in_use
4026 # endif
4027 	    )
4028     {
4029 	set_mouse_termcode(KS_SGR_MOUSE, (char_u *)(term_is_8bit(T_NAME)
4030 		    ? IF_EB("\233<*M", CSI_STR "<*M")
4031 		    : IF_EB("\033[<*M", ESC_STR "[<*M")));
4032 
4033 	set_mouse_termcode(KS_SGR_MOUSE_RELEASE, (char_u *)(term_is_8bit(T_NAME)
4034 		    ? IF_EB("\233<*m", CSI_STR "<*m")
4035 		    : IF_EB("\033[<*m", ESC_STR "[<*m")));
4036 
4037 	if (*p_mouse != NUL)
4038 	{
4039 	    mch_setmouse(FALSE);
4040 	    setmouse();
4041 	}
4042     }
4043     else
4044     {
4045 	del_mouse_termcode(KS_SGR_MOUSE);
4046 	del_mouse_termcode(KS_SGR_MOUSE_RELEASE);
4047     }
4048 }
4049 
4050 #ifndef VMS
4051 
4052 /*
4053  * Try to get the current window size:
4054  * 1. with an ioctl(), most accurate method
4055  * 2. from the environment variables LINES and COLUMNS
4056  * 3. from the termcap
4057  * 4. keep using the old values
4058  * Return OK when size could be determined, FAIL otherwise.
4059  */
4060     int
mch_get_shellsize(void)4061 mch_get_shellsize(void)
4062 {
4063     long	rows = 0;
4064     long	columns = 0;
4065     char_u	*p;
4066 
4067     /*
4068      * 1. try using an ioctl. It is the most accurate method.
4069      *
4070      * Try using TIOCGWINSZ first, some systems that have it also define
4071      * TIOCGSIZE but don't have a struct ttysize.
4072      */
4073 # ifdef TIOCGWINSZ
4074     {
4075 	struct winsize	ws;
4076 	int fd = 1;
4077 
4078 	// When stdout is not a tty, use stdin for the ioctl().
4079 	if (!isatty(fd) && isatty(read_cmd_fd))
4080 	    fd = read_cmd_fd;
4081 	if (ioctl(fd, TIOCGWINSZ, &ws) == 0)
4082 	{
4083 	    columns = ws.ws_col;
4084 	    rows = ws.ws_row;
4085 	}
4086     }
4087 # else // TIOCGWINSZ
4088 #  ifdef TIOCGSIZE
4089     {
4090 	struct ttysize	ts;
4091 	int fd = 1;
4092 
4093 	// When stdout is not a tty, use stdin for the ioctl().
4094 	if (!isatty(fd) && isatty(read_cmd_fd))
4095 	    fd = read_cmd_fd;
4096 	if (ioctl(fd, TIOCGSIZE, &ts) == 0)
4097 	{
4098 	    columns = ts.ts_cols;
4099 	    rows = ts.ts_lines;
4100 	}
4101     }
4102 #  endif // TIOCGSIZE
4103 # endif // TIOCGWINSZ
4104 
4105     /*
4106      * 2. get size from environment
4107      *    When being POSIX compliant ('|' flag in 'cpoptions') this overrules
4108      *    the ioctl() values!
4109      */
4110     if (columns == 0 || rows == 0 || vim_strchr(p_cpo, CPO_TSIZE) != NULL)
4111     {
4112 	if ((p = (char_u *)getenv("LINES")))
4113 	    rows = atoi((char *)p);
4114 	if ((p = (char_u *)getenv("COLUMNS")))
4115 	    columns = atoi((char *)p);
4116     }
4117 
4118 #ifdef HAVE_TGETENT
4119     /*
4120      * 3. try reading "co" and "li" entries from termcap
4121      */
4122     if (columns == 0 || rows == 0)
4123 	getlinecol(&columns, &rows);
4124 #endif
4125 
4126     /*
4127      * 4. If everything fails, use the old values
4128      */
4129     if (columns <= 0 || rows <= 0)
4130 	return FAIL;
4131 
4132     Rows = rows;
4133     Columns = columns;
4134     limit_screen_size();
4135     return OK;
4136 }
4137 
4138 #if defined(FEAT_TERMINAL) || defined(PROTO)
4139 /*
4140  * Report the windows size "rows" and "cols" to tty "fd".
4141  */
4142     int
mch_report_winsize(int fd,int rows,int cols)4143 mch_report_winsize(int fd, int rows, int cols)
4144 {
4145     int		tty_fd;
4146     int		retval = -1;
4147 
4148     tty_fd = get_tty_fd(fd);
4149     if (tty_fd >= 0)
4150     {
4151 # if defined(TIOCSWINSZ)
4152 	struct winsize ws;
4153 
4154 	ws.ws_col = cols;
4155 	ws.ws_row = rows;
4156 	ws.ws_xpixel = cols * 5;
4157 	ws.ws_ypixel = rows * 10;
4158 	retval = ioctl(tty_fd, TIOCSWINSZ, &ws);
4159 	ch_log(NULL, "ioctl(TIOCSWINSZ) %s",
4160 					  retval == 0 ? "success" : "failed");
4161 # elif defined(TIOCSSIZE)
4162 	struct ttysize ts;
4163 
4164 	ts.ts_cols = cols;
4165 	ts.ts_lines = rows;
4166 	retval = ioctl(tty_fd, TIOCSSIZE, &ts);
4167 	ch_log(NULL, "ioctl(TIOCSSIZE) %s",
4168 					  retval == 0 ? "success" : "failed");
4169 # endif
4170 	if (tty_fd != fd)
4171 	    close(tty_fd);
4172     }
4173     return retval == 0 ? OK : FAIL;
4174 }
4175 #endif
4176 
4177 /*
4178  * Try to set the window size to Rows and Columns.
4179  */
4180     void
mch_set_shellsize(void)4181 mch_set_shellsize(void)
4182 {
4183     if (*T_CWS)
4184     {
4185 	/*
4186 	 * NOTE: if you get an error here that term_set_winsize() is
4187 	 * undefined, check the output of configure.  It could probably not
4188 	 * find a ncurses, termcap or termlib library.
4189 	 */
4190 	term_set_winsize((int)Rows, (int)Columns);
4191 	out_flush();
4192 	screen_start();			// don't know where cursor is now
4193     }
4194 }
4195 
4196 #endif // VMS
4197 
4198 /*
4199  * Rows and/or Columns has changed.
4200  */
4201     void
mch_new_shellsize(void)4202 mch_new_shellsize(void)
4203 {
4204     // Nothing to do.
4205 }
4206 
4207 /*
4208  * Wait for process "child" to end.
4209  * Return "child" if it exited properly, <= 0 on error.
4210  */
4211     static pid_t
wait4pid(pid_t child,waitstatus * status)4212 wait4pid(pid_t child, waitstatus *status)
4213 {
4214     pid_t wait_pid = 0;
4215     long delay_msec = 1;
4216 
4217     while (wait_pid != child)
4218     {
4219 	// When compiled with Python threads are probably used, in which case
4220 	// wait() sometimes hangs for no obvious reason.  Use waitpid()
4221 	// instead and loop (like the GUI). Also needed for other interfaces,
4222 	// they might call system().
4223 # ifdef __NeXT__
4224 	wait_pid = wait4(child, status, WNOHANG, (struct rusage *)0);
4225 # else
4226 	wait_pid = waitpid(child, status, WNOHANG);
4227 # endif
4228 	if (wait_pid == 0)
4229 	{
4230 	    // Wait for 1 to 10 msec before trying again.
4231 	    mch_delay(delay_msec, MCH_DELAY_IGNOREINPUT | MCH_DELAY_SETTMODE);
4232 	    if (++delay_msec > 10)
4233 		delay_msec = 10;
4234 	    continue;
4235 	}
4236 	if (wait_pid <= 0
4237 # ifdef ECHILD
4238 		&& errno == ECHILD
4239 # endif
4240 	   )
4241 	    break;
4242     }
4243     return wait_pid;
4244 }
4245 
4246 #if !defined(USE_SYSTEM) || defined(FEAT_JOB_CHANNEL)
4247 /*
4248  * Set the environment for a child process.
4249  */
4250     static void
set_child_environment(long rows,long columns,char * term,int is_terminal UNUSED)4251 set_child_environment(
4252 	long	rows,
4253 	long	columns,
4254 	char	*term,
4255 	int	is_terminal UNUSED)
4256 {
4257 # ifdef HAVE_SETENV
4258     char	envbuf[50];
4259 # else
4260     static char	envbuf_Term[30];
4261     static char	envbuf_Rows[20];
4262     static char	envbuf_Lines[20];
4263     static char	envbuf_Columns[20];
4264     static char	envbuf_Colors[20];
4265 #  ifdef FEAT_TERMINAL
4266     static char	envbuf_Version[20];
4267 #  endif
4268 #  ifdef FEAT_CLIENTSERVER
4269     static char	envbuf_Servername[60];
4270 #  endif
4271 # endif
4272 
4273 # ifdef HAVE_SETENV
4274     setenv("TERM", term, 1);
4275     sprintf((char *)envbuf, "%ld", rows);
4276     setenv("ROWS", (char *)envbuf, 1);
4277     sprintf((char *)envbuf, "%ld", rows);
4278     setenv("LINES", (char *)envbuf, 1);
4279     sprintf((char *)envbuf, "%ld", columns);
4280     setenv("COLUMNS", (char *)envbuf, 1);
4281     sprintf((char *)envbuf, "%d", t_colors);
4282     setenv("COLORS", (char *)envbuf, 1);
4283 #  ifdef FEAT_TERMINAL
4284     if (is_terminal)
4285     {
4286 	sprintf((char *)envbuf, "%ld",  (long)get_vim_var_nr(VV_VERSION));
4287 	setenv("VIM_TERMINAL", (char *)envbuf, 1);
4288     }
4289 #  endif
4290 #  ifdef FEAT_CLIENTSERVER
4291     setenv("VIM_SERVERNAME", serverName == NULL ? "" : (char *)serverName, 1);
4292 #  endif
4293 # else
4294     /*
4295      * Putenv does not copy the string, it has to remain valid.
4296      * Use a static array to avoid losing allocated memory.
4297      * This won't work well when running multiple children...
4298      */
4299     vim_snprintf(envbuf_Term, sizeof(envbuf_Term), "TERM=%s", term);
4300     putenv(envbuf_Term);
4301     vim_snprintf(envbuf_Rows, sizeof(envbuf_Rows), "ROWS=%ld", rows);
4302     putenv(envbuf_Rows);
4303     vim_snprintf(envbuf_Lines, sizeof(envbuf_Lines), "LINES=%ld", rows);
4304     putenv(envbuf_Lines);
4305     vim_snprintf(envbuf_Columns, sizeof(envbuf_Columns),
4306 						       "COLUMNS=%ld", columns);
4307     putenv(envbuf_Columns);
4308     vim_snprintf(envbuf_Colors, sizeof(envbuf_Colors), "COLORS=%ld", t_colors);
4309     putenv(envbuf_Colors);
4310 #  ifdef FEAT_TERMINAL
4311     if (is_terminal)
4312     {
4313 	vim_snprintf(envbuf_Version, sizeof(envbuf_Version),
4314 			 "VIM_TERMINAL=%ld", (long)get_vim_var_nr(VV_VERSION));
4315 	putenv(envbuf_Version);
4316     }
4317 #  endif
4318 #  ifdef FEAT_CLIENTSERVER
4319     vim_snprintf(envbuf_Servername, sizeof(envbuf_Servername),
4320 	    "VIM_SERVERNAME=%s", serverName == NULL ? "" : (char *)serverName);
4321     putenv(envbuf_Servername);
4322 #  endif
4323 # endif
4324 }
4325 
4326     static void
set_default_child_environment(int is_terminal)4327 set_default_child_environment(int is_terminal)
4328 {
4329     set_child_environment(Rows, Columns, "dumb", is_terminal);
4330 }
4331 #endif
4332 
4333 #if defined(FEAT_GUI) || defined(FEAT_JOB_CHANNEL)
4334 /*
4335  * Open a PTY, with FD for the master and slave side.
4336  * When failing "pty_master_fd" and "pty_slave_fd" are -1.
4337  * When successful both file descriptors are stored and the allocated pty name
4338  * is stored in both "*name1" and "*name2".
4339  */
4340     static void
open_pty(int * pty_master_fd,int * pty_slave_fd,char_u ** name1,char_u ** name2)4341 open_pty(int *pty_master_fd, int *pty_slave_fd, char_u **name1, char_u **name2)
4342 {
4343     char	*tty_name;
4344 
4345     if (name1 != NULL)
4346 	*name1 = NULL;
4347     if (name2 != NULL)
4348 	*name2 = NULL;
4349 
4350     *pty_master_fd = mch_openpty(&tty_name);	    // open pty
4351     if (*pty_master_fd >= 0)
4352     {
4353 	// Leaving out O_NOCTTY may lead to waitpid() always returning
4354 	// 0 on Mac OS X 10.7 thereby causing freezes. Let's assume
4355 	// adding O_NOCTTY always works when defined.
4356 #ifdef O_NOCTTY
4357 	*pty_slave_fd = open(tty_name, O_RDWR | O_NOCTTY | O_EXTRA, 0);
4358 #else
4359 	*pty_slave_fd = open(tty_name, O_RDWR | O_EXTRA, 0);
4360 #endif
4361 	if (*pty_slave_fd < 0)
4362 	{
4363 	    close(*pty_master_fd);
4364 	    *pty_master_fd = -1;
4365 	}
4366 	else
4367 	{
4368 	    if (name1 != NULL)
4369 		*name1 = vim_strsave((char_u *)tty_name);
4370 	    if (name2 != NULL)
4371 		*name2 = vim_strsave((char_u *)tty_name);
4372 	}
4373     }
4374 }
4375 #endif
4376 
4377 /*
4378  * Send SIGINT to a child process if "c" is an interrupt character.
4379  */
4380     static void
may_send_sigint(int c UNUSED,pid_t pid UNUSED,pid_t wpid UNUSED)4381 may_send_sigint(int c UNUSED, pid_t pid UNUSED, pid_t wpid UNUSED)
4382 {
4383 # ifdef SIGINT
4384     if (c == Ctrl_C || c == intr_char)
4385     {
4386 #  ifdef HAVE_SETSID
4387 	kill(-pid, SIGINT);
4388 #  else
4389 	kill(0, SIGINT);
4390 #  endif
4391 	if (wpid > 0)
4392 	    kill(wpid, SIGINT);
4393     }
4394 # endif
4395 }
4396 
4397 #if !defined(USE_SYSTEM) || defined(FEAT_TERMINAL) || defined(PROTO)
4398 
4399 /*
4400  * Parse "cmd" and return the result in "argvp" which is an allocated array of
4401  * pointers, the last one is NULL.
4402  * The "sh_tofree" and "shcf_tofree" must be later freed by the caller.
4403  */
4404     int
unix_build_argv(char_u * cmd,char *** argvp,char_u ** sh_tofree,char_u ** shcf_tofree)4405 unix_build_argv(
4406 	char_u *cmd,
4407 	char ***argvp,
4408 	char_u **sh_tofree,
4409 	char_u **shcf_tofree)
4410 {
4411     char	**argv = NULL;
4412     int		argc;
4413 
4414     *sh_tofree = vim_strsave(p_sh);
4415     if (*sh_tofree == NULL)		// out of memory
4416 	return FAIL;
4417 
4418     if (mch_parse_cmd(*sh_tofree, TRUE, &argv, &argc) == FAIL)
4419 	return FAIL;
4420     *argvp = argv;
4421 
4422     if (cmd != NULL)
4423     {
4424 	char_u	*s;
4425 	char_u	*p;
4426 
4427 	if (extra_shell_arg != NULL)
4428 	    argv[argc++] = (char *)extra_shell_arg;
4429 
4430 	// Break 'shellcmdflag' into white separated parts.  This doesn't
4431 	// handle quoted strings, they are very unlikely to appear.
4432 	*shcf_tofree = alloc(STRLEN(p_shcf) + 1);
4433 	if (*shcf_tofree == NULL)    // out of memory
4434 	    return FAIL;
4435 	s = *shcf_tofree;
4436 	p = p_shcf;
4437 	while (*p != NUL)
4438 	{
4439 	    argv[argc++] = (char *)s;
4440 	    while (*p && *p != ' ' && *p != TAB)
4441 		*s++ = *p++;
4442 	    *s++ = NUL;
4443 	    p = skipwhite(p);
4444 	}
4445 
4446 	argv[argc++] = (char *)cmd;
4447     }
4448     argv[argc] = NULL;
4449     return OK;
4450 }
4451 #endif
4452 
4453 #if defined(FEAT_GUI) && defined(FEAT_TERMINAL)
4454 /*
4455  * Use a terminal window to run a shell command in.
4456  */
4457     static int
mch_call_shell_terminal(char_u * cmd,int options UNUSED)4458 mch_call_shell_terminal(
4459     char_u	*cmd,
4460     int		options UNUSED)	// SHELL_*, see vim.h
4461 {
4462     jobopt_T	opt;
4463     char	**argv = NULL;
4464     char_u	*tofree1 = NULL;
4465     char_u	*tofree2 = NULL;
4466     int		retval = -1;
4467     buf_T	*buf;
4468     job_T	*job;
4469     aco_save_T	aco;
4470     oparg_T	oa;		// operator arguments
4471 
4472     if (unix_build_argv(cmd, &argv, &tofree1, &tofree2) == FAIL)
4473 	goto theend;
4474 
4475     init_job_options(&opt);
4476     ch_log(NULL, "starting terminal for system command '%s'", cmd);
4477     buf = term_start(NULL, argv, &opt, TERM_START_SYSTEM);
4478     if (buf == NULL)
4479 	goto theend;
4480 
4481     job = term_getjob(buf->b_term);
4482     ++job->jv_refcount;
4483 
4484     // Find a window to make "buf" curbuf.
4485     aucmd_prepbuf(&aco, buf);
4486 
4487     clear_oparg(&oa);
4488     while (term_use_loop())
4489     {
4490 	if (oa.op_type == OP_NOP && oa.regname == NUL && !VIsual_active)
4491 	{
4492 	    // If terminal_loop() returns OK we got a key that is handled
4493 	    // in Normal model. We don't do redrawing anyway.
4494 	    if (terminal_loop(TRUE) == OK)
4495 		normal_cmd(&oa, TRUE);
4496 	}
4497 	else
4498 	    normal_cmd(&oa, TRUE);
4499     }
4500     retval = job->jv_exitval;
4501     ch_log(NULL, "system command finished");
4502 
4503     job_unref(job);
4504 
4505     // restore curwin/curbuf and a few other things
4506     aucmd_restbuf(&aco);
4507 
4508     wait_return(TRUE);
4509     do_buffer(DOBUF_WIPE, DOBUF_FIRST, FORWARD, buf->b_fnum, TRUE);
4510 
4511 theend:
4512     vim_free(argv);
4513     vim_free(tofree1);
4514     vim_free(tofree2);
4515     return retval;
4516 }
4517 #endif
4518 
4519 #ifdef USE_SYSTEM
4520 /*
4521  * Use system() to start the shell: simple but slow.
4522  */
4523     static int
mch_call_shell_system(char_u * cmd,int options)4524 mch_call_shell_system(
4525     char_u	*cmd,
4526     int		options)	// SHELL_*, see vim.h
4527 {
4528 #ifdef VMS
4529     char	*ifn = NULL;
4530     char	*ofn = NULL;
4531 #endif
4532     tmode_T	tmode = cur_tmode;
4533     char_u	*newcmd;	// only needed for unix
4534     int		x;
4535 
4536     out_flush();
4537 
4538     if (options & SHELL_COOKED)
4539 	settmode(TMODE_COOK);	    // set to normal mode
4540 
4541 # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
4542     save_clipboard();
4543     loose_clipboard();
4544 # endif
4545 
4546     if (cmd == NULL)
4547 	x = system((char *)p_sh);
4548     else
4549     {
4550 # ifdef VMS
4551 	if (ofn = strchr((char *)cmd, '>'))
4552 	    *ofn++ = '\0';
4553 	if (ifn = strchr((char *)cmd, '<'))
4554 	{
4555 	    char *p;
4556 
4557 	    *ifn++ = '\0';
4558 	    p = strchr(ifn,' '); // chop off any trailing spaces
4559 	    if (p)
4560 		*p = '\0';
4561 	}
4562 	if (ofn)
4563 	    x = vms_sys((char *)cmd, ofn, ifn);
4564 	else
4565 	    x = system((char *)cmd);
4566 # else
4567 	newcmd = alloc(STRLEN(p_sh)
4568 		+ (extra_shell_arg == NULL ? 0 : STRLEN(extra_shell_arg))
4569 		+ STRLEN(p_shcf) + STRLEN(cmd) + 4);
4570 	if (newcmd == NULL)
4571 	    x = 0;
4572 	else
4573 	{
4574 	    sprintf((char *)newcmd, "%s %s %s %s", p_sh,
4575 		    extra_shell_arg == NULL ? "" : (char *)extra_shell_arg,
4576 		    (char *)p_shcf,
4577 		    (char *)cmd);
4578 	    x = system((char *)newcmd);
4579 	    vim_free(newcmd);
4580 	}
4581 # endif
4582     }
4583 # ifdef VMS
4584     x = vms_sys_status(x);
4585 # endif
4586     if (emsg_silent)
4587 	;
4588     else if (x == 127)
4589 	msg_puts(_("\nCannot execute shell sh\n"));
4590     else if (x && !(options & SHELL_SILENT))
4591     {
4592 	msg_puts(_("\nshell returned "));
4593 	msg_outnum((long)x);
4594 	msg_putchar('\n');
4595     }
4596 
4597     if (tmode == TMODE_RAW)
4598     {
4599 	// The shell may have messed with the mode, always set it.
4600 	cur_tmode = TMODE_UNKNOWN;
4601 	settmode(TMODE_RAW);	// set to raw mode
4602     }
4603 # ifdef FEAT_TITLE
4604     resettitle();
4605 # endif
4606 # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
4607     restore_clipboard();
4608 # endif
4609     return x;
4610 }
4611 
4612 #else // USE_SYSTEM
4613 
4614 # define EXEC_FAILED 122    // Exit code when shell didn't execute.  Don't use
4615 			    // 127, some shells use that already
4616 # define OPEN_NULL_FAILED 123 // Exit code if /dev/null can't be opened
4617 
4618 /*
4619  * Don't use system(), use fork()/exec().
4620  */
4621     static int
mch_call_shell_fork(char_u * cmd,int options)4622 mch_call_shell_fork(
4623     char_u	*cmd,
4624     int		options)	// SHELL_*, see vim.h
4625 {
4626     tmode_T	tmode = cur_tmode;
4627     pid_t	pid;
4628     pid_t	wpid = 0;
4629     pid_t	wait_pid = 0;
4630 # ifdef HAVE_UNION_WAIT
4631     union wait	status;
4632 # else
4633     int		status = -1;
4634 # endif
4635     int		retval = -1;
4636     char	**argv = NULL;
4637     char_u	*tofree1 = NULL;
4638     char_u	*tofree2 = NULL;
4639     int		i;
4640     int		pty_master_fd = -1;	    // for pty's
4641 # ifdef FEAT_GUI
4642     int		pty_slave_fd = -1;
4643 # endif
4644     int		fd_toshell[2];		// for pipes
4645     int		fd_fromshell[2];
4646     int		pipe_error = FALSE;
4647     int		did_settmode = FALSE;	// settmode(TMODE_RAW) called
4648 
4649     out_flush();
4650     if (options & SHELL_COOKED)
4651 	settmode(TMODE_COOK);		// set to normal mode
4652     if (tmode == TMODE_RAW)
4653 	// The shell may have messed with the mode, always set it later.
4654 	cur_tmode = TMODE_UNKNOWN;
4655 
4656     if (unix_build_argv(cmd, &argv, &tofree1, &tofree2) == FAIL)
4657 	goto error;
4658 
4659     /*
4660      * For the GUI, when writing the output into the buffer and when reading
4661      * input from the buffer: Try using a pseudo-tty to get the stdin/stdout
4662      * of the executed command into the Vim window.  Or use a pipe.
4663      */
4664     if ((options & (SHELL_READ|SHELL_WRITE))
4665 # ifdef FEAT_GUI
4666 	    || (gui.in_use && show_shell_mess)
4667 # endif
4668 		    )
4669     {
4670 # ifdef FEAT_GUI
4671 	/*
4672 	 * Try to open a master pty.
4673 	 * If this works, open the slave pty.
4674 	 * If the slave can't be opened, close the master pty.
4675 	 */
4676 	if (p_guipty && !(options & (SHELL_READ|SHELL_WRITE)))
4677 	    open_pty(&pty_master_fd, &pty_slave_fd, NULL, NULL);
4678 	/*
4679 	 * If not opening a pty or it didn't work, try using pipes.
4680 	 */
4681 	if (pty_master_fd < 0)
4682 # endif
4683 	{
4684 	    pipe_error = (pipe(fd_toshell) < 0);
4685 	    if (!pipe_error)			    // pipe create OK
4686 	    {
4687 		pipe_error = (pipe(fd_fromshell) < 0);
4688 		if (pipe_error)			    // pipe create failed
4689 		{
4690 		    close(fd_toshell[0]);
4691 		    close(fd_toshell[1]);
4692 		}
4693 	    }
4694 	    if (pipe_error)
4695 	    {
4696 		msg_puts(_("\nCannot create pipes\n"));
4697 		out_flush();
4698 	    }
4699 	}
4700     }
4701 
4702     if (!pipe_error)			// pty or pipe opened or not used
4703     {
4704 	SIGSET_DECL(curset)
4705 	BLOCK_SIGNALS(&curset);
4706 	pid = fork();	// maybe we should use vfork()
4707 	if (pid == -1)
4708 	{
4709 	    UNBLOCK_SIGNALS(&curset);
4710 
4711 	    msg_puts(_("\nCannot fork\n"));
4712 	    if ((options & (SHELL_READ|SHELL_WRITE))
4713 # ifdef FEAT_GUI
4714 		|| (gui.in_use && show_shell_mess)
4715 # endif
4716 		    )
4717 	    {
4718 # ifdef FEAT_GUI
4719 		if (pty_master_fd >= 0)		// close the pseudo tty
4720 		{
4721 		    close(pty_master_fd);
4722 		    close(pty_slave_fd);
4723 		}
4724 		else				// close the pipes
4725 # endif
4726 		{
4727 		    close(fd_toshell[0]);
4728 		    close(fd_toshell[1]);
4729 		    close(fd_fromshell[0]);
4730 		    close(fd_fromshell[1]);
4731 		}
4732 	    }
4733 	}
4734 	else if (pid == 0)	// child
4735 	{
4736 	    reset_signals();		// handle signals normally
4737 	    UNBLOCK_SIGNALS(&curset);
4738 
4739 # ifdef FEAT_JOB_CHANNEL
4740 	    if (ch_log_active())
4741 	    {
4742 		ch_log(NULL, "closing channel log in the child process");
4743 		ch_logfile((char_u *)"", (char_u *)"");
4744 	    }
4745 # endif
4746 
4747 	    if (!show_shell_mess || (options & SHELL_EXPAND))
4748 	    {
4749 		int fd;
4750 
4751 		/*
4752 		 * Don't want to show any message from the shell.  Can't just
4753 		 * close stdout and stderr though, because some systems will
4754 		 * break if you try to write to them after that, so we must
4755 		 * use dup() to replace them with something else -- webb
4756 		 * Connect stdin to /dev/null too, so ":n `cat`" doesn't hang,
4757 		 * waiting for input.
4758 		 */
4759 		fd = open("/dev/null", O_RDWR | O_EXTRA, 0);
4760 		fclose(stdin);
4761 		fclose(stdout);
4762 		fclose(stderr);
4763 
4764 		/*
4765 		 * If any of these open()'s and dup()'s fail, we just continue
4766 		 * anyway.  It's not fatal, and on most systems it will make
4767 		 * no difference at all.  On a few it will cause the execvp()
4768 		 * to exit with a non-zero status even when the completion
4769 		 * could be done, which is nothing too serious.  If the open()
4770 		 * or dup() failed we'd just do the same thing ourselves
4771 		 * anyway -- webb
4772 		 */
4773 		if (fd >= 0)
4774 		{
4775 		    vim_ignored = dup(fd); // To replace stdin  (fd 0)
4776 		    vim_ignored = dup(fd); // To replace stdout (fd 1)
4777 		    vim_ignored = dup(fd); // To replace stderr (fd 2)
4778 
4779 		    // Don't need this now that we've duplicated it
4780 		    close(fd);
4781 		}
4782 	    }
4783 	    else if ((options & (SHELL_READ|SHELL_WRITE))
4784 # ifdef FEAT_GUI
4785 		    || gui.in_use
4786 # endif
4787 		    )
4788 	    {
4789 
4790 # ifdef HAVE_SETSID
4791 		// Create our own process group, so that the child and all its
4792 		// children can be kill()ed.  Don't do this when using pipes,
4793 		// because stdin is not a tty, we would lose /dev/tty.
4794 		if (p_stmp)
4795 		{
4796 		    (void)setsid();
4797 #  if defined(SIGHUP)
4798 		    // When doing "!xterm&" and 'shell' is bash: the shell
4799 		    // will exit and send SIGHUP to all processes in its
4800 		    // group, killing the just started process.  Ignore SIGHUP
4801 		    // to avoid that. (suggested by Simon Schubert)
4802 		    signal(SIGHUP, SIG_IGN);
4803 #  endif
4804 		}
4805 # endif
4806 # ifdef FEAT_GUI
4807 		if (pty_slave_fd >= 0)
4808 		{
4809 		    // push stream discipline modules
4810 		    if (options & SHELL_COOKED)
4811 			setup_slavepty(pty_slave_fd);
4812 #  ifdef TIOCSCTTY
4813 		    // Try to become controlling tty (probably doesn't work,
4814 		    // unless run by root)
4815 		    ioctl(pty_slave_fd, TIOCSCTTY, (char *)NULL);
4816 #  endif
4817 		}
4818 # endif
4819 		set_default_child_environment(FALSE);
4820 
4821 		/*
4822 		 * stderr is only redirected when using the GUI, so that a
4823 		 * program like gpg can still access the terminal to get a
4824 		 * passphrase using stderr.
4825 		 */
4826 # ifdef FEAT_GUI
4827 		if (pty_master_fd >= 0)
4828 		{
4829 		    close(pty_master_fd);   // close master side of pty
4830 
4831 		    // set up stdin/stdout/stderr for the child
4832 		    close(0);
4833 		    vim_ignored = dup(pty_slave_fd);
4834 		    close(1);
4835 		    vim_ignored = dup(pty_slave_fd);
4836 		    if (gui.in_use)
4837 		    {
4838 			close(2);
4839 			vim_ignored = dup(pty_slave_fd);
4840 		    }
4841 
4842 		    close(pty_slave_fd);    // has been dupped, close it now
4843 		}
4844 		else
4845 # endif
4846 		{
4847 		    // set up stdin for the child
4848 		    close(fd_toshell[1]);
4849 		    close(0);
4850 		    vim_ignored = dup(fd_toshell[0]);
4851 		    close(fd_toshell[0]);
4852 
4853 		    // set up stdout for the child
4854 		    close(fd_fromshell[0]);
4855 		    close(1);
4856 		    vim_ignored = dup(fd_fromshell[1]);
4857 		    close(fd_fromshell[1]);
4858 
4859 # ifdef FEAT_GUI
4860 		    if (gui.in_use)
4861 		    {
4862 			// set up stderr for the child
4863 			close(2);
4864 			vim_ignored = dup(1);
4865 		    }
4866 # endif
4867 		}
4868 	    }
4869 
4870 	    /*
4871 	     * There is no type cast for the argv, because the type may be
4872 	     * different on different machines. This may cause a warning
4873 	     * message with strict compilers, don't worry about it.
4874 	     * Call _exit() instead of exit() to avoid closing the connection
4875 	     * to the X server (esp. with GTK, which uses atexit()).
4876 	     */
4877 	    execvp(argv[0], argv);
4878 	    _exit(EXEC_FAILED);	    // exec failed, return failure code
4879 	}
4880 	else			// parent
4881 	{
4882 	    /*
4883 	     * While child is running, ignore terminating signals.
4884 	     * Do catch CTRL-C, so that "got_int" is set.
4885 	     */
4886 	    catch_signals(SIG_IGN, SIG_ERR);
4887 	    catch_int_signal();
4888 	    UNBLOCK_SIGNALS(&curset);
4889 # ifdef FEAT_JOB_CHANNEL
4890 	    ++dont_check_job_ended;
4891 # endif
4892 	    /*
4893 	     * For the GUI we redirect stdin, stdout and stderr to our window.
4894 	     * This is also used to pipe stdin/stdout to/from the external
4895 	     * command.
4896 	     */
4897 	    if ((options & (SHELL_READ|SHELL_WRITE))
4898 # ifdef FEAT_GUI
4899 		    || (gui.in_use && show_shell_mess)
4900 # endif
4901 	       )
4902 	    {
4903 # define BUFLEN 100		// length for buffer, pseudo tty limit is 128
4904 		char_u	    buffer[BUFLEN + 1];
4905 		int	    buffer_off = 0;	// valid bytes in buffer[]
4906 		char_u	    ta_buf[BUFLEN + 1];	// TypeAHead
4907 		int	    ta_len = 0;		// valid bytes in ta_buf[]
4908 		int	    len;
4909 		int	    p_more_save;
4910 		int	    old_State;
4911 		int	    c;
4912 		int	    toshell_fd;
4913 		int	    fromshell_fd;
4914 		garray_T    ga;
4915 		int	    noread_cnt;
4916 # ifdef ELAPSED_FUNC
4917 		elapsed_T   start_tv;
4918 # endif
4919 
4920 # ifdef FEAT_GUI
4921 		if (pty_master_fd >= 0)
4922 		{
4923 		    fromshell_fd = pty_master_fd;
4924 		    toshell_fd = dup(pty_master_fd);
4925 		}
4926 		else
4927 # endif
4928 		{
4929 		    close(fd_toshell[0]);
4930 		    close(fd_fromshell[1]);
4931 		    toshell_fd = fd_toshell[1];
4932 		    fromshell_fd = fd_fromshell[0];
4933 		}
4934 
4935 		/*
4936 		 * Write to the child if there are typed characters.
4937 		 * Read from the child if there are characters available.
4938 		 *   Repeat the reading a few times if more characters are
4939 		 *   available. Need to check for typed keys now and then, but
4940 		 *   not too often (delays when no chars are available).
4941 		 * This loop is quit if no characters can be read from the pty
4942 		 * (WaitForChar detected special condition), or there are no
4943 		 * characters available and the child has exited.
4944 		 * Only check if the child has exited when there is no more
4945 		 * output. The child may exit before all the output has
4946 		 * been printed.
4947 		 *
4948 		 * Currently this busy loops!
4949 		 * This can probably dead-lock when the write blocks!
4950 		 */
4951 		p_more_save = p_more;
4952 		p_more = FALSE;
4953 		old_State = State;
4954 		State = EXTERNCMD;	// don't redraw at window resize
4955 
4956 		if ((options & SHELL_WRITE) && toshell_fd >= 0)
4957 		{
4958 		    // Fork a process that will write the lines to the
4959 		    // external program.
4960 		    if ((wpid = fork()) == -1)
4961 		    {
4962 			msg_puts(_("\nCannot fork\n"));
4963 		    }
4964 		    else if (wpid == 0) // child
4965 		    {
4966 			linenr_T    lnum = curbuf->b_op_start.lnum;
4967 			int	    written = 0;
4968 			char_u	    *lp = ml_get(lnum);
4969 			size_t	    l;
4970 
4971 			close(fromshell_fd);
4972 			for (;;)
4973 			{
4974 			    l = STRLEN(lp + written);
4975 			    if (l == 0)
4976 				len = 0;
4977 			    else if (lp[written] == NL)
4978 				// NL -> NUL translation
4979 				len = write(toshell_fd, "", (size_t)1);
4980 			    else
4981 			    {
4982 				char_u	*s = vim_strchr(lp + written, NL);
4983 
4984 				len = write(toshell_fd, (char *)lp + written,
4985 					   s == NULL ? l
4986 					      : (size_t)(s - (lp + written)));
4987 			    }
4988 			    if (len == (int)l)
4989 			    {
4990 				// Finished a line, add a NL, unless this line
4991 				// should not have one.
4992 				if (lnum != curbuf->b_op_end.lnum
4993 					|| (!curbuf->b_p_bin
4994 					    && curbuf->b_p_fixeol)
4995 					|| (lnum != curbuf->b_no_eol_lnum
4996 					    && (lnum !=
4997 						    curbuf->b_ml.ml_line_count
4998 						    || curbuf->b_p_eol)))
4999 				    vim_ignored = write(toshell_fd, "\n",
5000 								   (size_t)1);
5001 				++lnum;
5002 				if (lnum > curbuf->b_op_end.lnum)
5003 				{
5004 				    // finished all the lines, close pipe
5005 				    close(toshell_fd);
5006 				    toshell_fd = -1;
5007 				    break;
5008 				}
5009 				lp = ml_get(lnum);
5010 				written = 0;
5011 			    }
5012 			    else if (len > 0)
5013 				written += len;
5014 			}
5015 			_exit(0);
5016 		    }
5017 		    else // parent
5018 		    {
5019 			close(toshell_fd);
5020 			toshell_fd = -1;
5021 		    }
5022 		}
5023 
5024 		if (options & SHELL_READ)
5025 		    ga_init2(&ga, 1, BUFLEN);
5026 
5027 		noread_cnt = 0;
5028 # ifdef ELAPSED_FUNC
5029 		ELAPSED_INIT(start_tv);
5030 # endif
5031 		for (;;)
5032 		{
5033 		    /*
5034 		     * Check if keys have been typed, write them to the child
5035 		     * if there are any.
5036 		     * Don't do this if we are expanding wild cards (would eat
5037 		     * typeahead).
5038 		     * Don't do this when filtering and terminal is in cooked
5039 		     * mode, the shell command will handle the I/O.  Avoids
5040 		     * that a typed password is echoed for ssh or gpg command.
5041 		     * Don't get characters when the child has already
5042 		     * finished (wait_pid == 0).
5043 		     * Don't read characters unless we didn't get output for a
5044 		     * while (noread_cnt > 4), avoids that ":r !ls" eats
5045 		     * typeahead.
5046 		     */
5047 		    len = 0;
5048 		    if (!(options & SHELL_EXPAND)
5049 			    && ((options &
5050 					 (SHELL_READ|SHELL_WRITE|SHELL_COOKED))
5051 				      != (SHELL_READ|SHELL_WRITE|SHELL_COOKED)
5052 # ifdef FEAT_GUI
5053 						    || gui.in_use
5054 # endif
5055 						    )
5056 			    && wait_pid == 0
5057 			    && (ta_len > 0 || noread_cnt > 4))
5058 		    {
5059 		      if (ta_len == 0)
5060 		      {
5061 			  // Get extra characters when we don't have any.
5062 			  // Reset the counter and timer.
5063 			  noread_cnt = 0;
5064 # ifdef ELAPSED_FUNC
5065 			  ELAPSED_INIT(start_tv);
5066 # endif
5067 			  len = ui_inchar(ta_buf, BUFLEN, 10L, 0);
5068 		      }
5069 		      if (ta_len > 0 || len > 0)
5070 		      {
5071 			/*
5072 			 * For pipes:
5073 			 * Check for CTRL-C: send interrupt signal to child.
5074 			 * Check for CTRL-D: EOF, close pipe to child.
5075 			 */
5076 			if (len == 1 && (pty_master_fd < 0 || cmd != NULL))
5077 			{
5078 			    /*
5079 			     * Send SIGINT to the child's group or all
5080 			     * processes in our group.
5081 			     */
5082 			    may_send_sigint(ta_buf[ta_len], pid, wpid);
5083 
5084 			    if (pty_master_fd < 0 && toshell_fd >= 0
5085 					       && ta_buf[ta_len] == Ctrl_D)
5086 			    {
5087 				close(toshell_fd);
5088 				toshell_fd = -1;
5089 			    }
5090 			}
5091 
5092 			term_replace_bs_del_keycode(ta_buf, ta_len, len);
5093 
5094 			/*
5095 			 * For pipes: echo the typed characters.
5096 			 * For a pty this does not seem to work.
5097 			 */
5098 			if (pty_master_fd < 0)
5099 			{
5100 			    for (i = ta_len; i < ta_len + len; ++i)
5101 			    {
5102 				if (ta_buf[i] == '\n' || ta_buf[i] == '\b')
5103 				    msg_putchar(ta_buf[i]);
5104 				else if (has_mbyte)
5105 				{
5106 				    int l = (*mb_ptr2len)(ta_buf + i);
5107 
5108 				    msg_outtrans_len(ta_buf + i, l);
5109 				    i += l - 1;
5110 				}
5111 				else
5112 				    msg_outtrans_len(ta_buf + i, 1);
5113 			    }
5114 			    windgoto(msg_row, msg_col);
5115 			    out_flush();
5116 			}
5117 
5118 			ta_len += len;
5119 
5120 			/*
5121 			 * Write the characters to the child, unless EOF has
5122 			 * been typed for pipes.  Write one character at a
5123 			 * time, to avoid losing too much typeahead.
5124 			 * When writing buffer lines, drop the typed
5125 			 * characters (only check for CTRL-C).
5126 			 */
5127 			if (options & SHELL_WRITE)
5128 			    ta_len = 0;
5129 			else if (toshell_fd >= 0)
5130 			{
5131 			    len = write(toshell_fd, (char *)ta_buf, (size_t)1);
5132 			    if (len > 0)
5133 			    {
5134 				ta_len -= len;
5135 				mch_memmove(ta_buf, ta_buf + len, ta_len);
5136 			    }
5137 			}
5138 		      }
5139 		    }
5140 
5141 		    if (got_int)
5142 		    {
5143 			// CTRL-C sends a signal to the child, we ignore it
5144 			// ourselves
5145 #  ifdef HAVE_SETSID
5146 			kill(-pid, SIGINT);
5147 #  else
5148 			kill(0, SIGINT);
5149 #  endif
5150 			if (wpid > 0)
5151 			    kill(wpid, SIGINT);
5152 			got_int = FALSE;
5153 		    }
5154 
5155 		    /*
5156 		     * Check if the child has any characters to be printed.
5157 		     * Read them and write them to our window.	Repeat this as
5158 		     * long as there is something to do, avoid the 10ms wait
5159 		     * for mch_inchar(), or sending typeahead characters to
5160 		     * the external process.
5161 		     * TODO: This should handle escape sequences, compatible
5162 		     * to some terminal (vt52?).
5163 		     */
5164 		    ++noread_cnt;
5165 		    while (RealWaitForChar(fromshell_fd, 10L, NULL, NULL))
5166 		    {
5167 			len = read_eintr(fromshell_fd, buffer
5168 				+ buffer_off, (size_t)(BUFLEN - buffer_off)
5169 				);
5170 			if (len <= 0)		    // end of file or error
5171 			    goto finished;
5172 
5173 			noread_cnt = 0;
5174 			if (options & SHELL_READ)
5175 			{
5176 			    // Do NUL -> NL translation, append NL separated
5177 			    // lines to the current buffer.
5178 			    for (i = 0; i < len; ++i)
5179 			    {
5180 				if (buffer[i] == NL)
5181 				    append_ga_line(&ga);
5182 				else if (buffer[i] == NUL)
5183 				    ga_append(&ga, NL);
5184 				else
5185 				    ga_append(&ga, buffer[i]);
5186 			    }
5187 			}
5188 			else if (has_mbyte)
5189 			{
5190 			    int		l;
5191 			    char_u	*p;
5192 
5193 			    len += buffer_off;
5194 			    buffer[len] = NUL;
5195 
5196 			    // Check if the last character in buffer[] is
5197 			    // incomplete, keep these bytes for the next
5198 			    // round.
5199 			    for (p = buffer; p < buffer + len; p += l)
5200 			    {
5201 				l = MB_CPTR2LEN(p);
5202 				if (l == 0)
5203 				    l = 1;  // NUL byte?
5204 				else if (MB_BYTE2LEN(*p) != l)
5205 				    break;
5206 			    }
5207 			    if (p == buffer)	// no complete character
5208 			    {
5209 				// avoid getting stuck at an illegal byte
5210 				if (len >= 12)
5211 				    ++p;
5212 				else
5213 				{
5214 				    buffer_off = len;
5215 				    continue;
5216 				}
5217 			    }
5218 			    c = *p;
5219 			    *p = NUL;
5220 			    msg_puts((char *)buffer);
5221 			    if (p < buffer + len)
5222 			    {
5223 				*p = c;
5224 				buffer_off = (buffer + len) - p;
5225 				mch_memmove(buffer, p, buffer_off);
5226 				continue;
5227 			    }
5228 			    buffer_off = 0;
5229 			}
5230 			else
5231 			{
5232 			    buffer[len] = NUL;
5233 			    msg_puts((char *)buffer);
5234 			}
5235 
5236 			windgoto(msg_row, msg_col);
5237 			cursor_on();
5238 			out_flush();
5239 			if (got_int)
5240 			    break;
5241 
5242 # ifdef ELAPSED_FUNC
5243 			if (wait_pid == 0)
5244 			{
5245 			    long	msec = ELAPSED_FUNC(start_tv);
5246 
5247 			    // Avoid that we keep looping here without
5248 			    // checking for a CTRL-C for a long time.  Don't
5249 			    // break out too often to avoid losing typeahead.
5250 			    if (msec > 2000)
5251 			    {
5252 				noread_cnt = 5;
5253 				break;
5254 			    }
5255 			}
5256 # endif
5257 		    }
5258 
5259 		    // If we already detected the child has finished, continue
5260 		    // reading output for a short while.  Some text may be
5261 		    // buffered.
5262 		    if (wait_pid == pid)
5263 		    {
5264 			if (noread_cnt < 5)
5265 			    continue;
5266 			break;
5267 		    }
5268 
5269 		    /*
5270 		     * Check if the child still exists, before checking for
5271 		     * typed characters (otherwise we would lose typeahead).
5272 		     */
5273 # ifdef __NeXT__
5274 		    wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *)0);
5275 # else
5276 		    wait_pid = waitpid(pid, &status, WNOHANG);
5277 # endif
5278 		    if ((wait_pid == (pid_t)-1 && errno == ECHILD)
5279 			    || (wait_pid == pid && WIFEXITED(status)))
5280 		    {
5281 			// Don't break the loop yet, try reading more
5282 			// characters from "fromshell_fd" first.  When using
5283 			// pipes there might still be something to read and
5284 			// then we'll break the loop at the "break" above.
5285 			wait_pid = pid;
5286 		    }
5287 		    else
5288 			wait_pid = 0;
5289 
5290 # if defined(FEAT_XCLIPBOARD) && defined(FEAT_X11)
5291 		    // Handle any X events, e.g. serving the clipboard.
5292 		    clip_update();
5293 # endif
5294 		}
5295 finished:
5296 		p_more = p_more_save;
5297 		if (options & SHELL_READ)
5298 		{
5299 		    if (ga.ga_len > 0)
5300 		    {
5301 			append_ga_line(&ga);
5302 			// remember that the NL was missing
5303 			curbuf->b_no_eol_lnum = curwin->w_cursor.lnum;
5304 		    }
5305 		    else
5306 			curbuf->b_no_eol_lnum = 0;
5307 		    ga_clear(&ga);
5308 		}
5309 
5310 		/*
5311 		 * Give all typeahead that wasn't used back to ui_inchar().
5312 		 */
5313 		if (ta_len)
5314 		    ui_inchar_undo(ta_buf, ta_len);
5315 		State = old_State;
5316 		if (toshell_fd >= 0)
5317 		    close(toshell_fd);
5318 		close(fromshell_fd);
5319 	    }
5320 # if defined(FEAT_XCLIPBOARD) && defined(FEAT_X11)
5321 	    else
5322 	    {
5323 		long delay_msec = 1;
5324 
5325 		if (tmode == TMODE_RAW)
5326 		    // possibly disables modifyOtherKeys, so that the system
5327 		    // can recognize CTRL-C
5328 		    out_str(T_CTE);
5329 
5330 		/*
5331 		 * Similar to the loop above, but only handle X events, no
5332 		 * I/O.
5333 		 */
5334 		for (;;)
5335 		{
5336 		    if (got_int)
5337 		    {
5338 			// CTRL-C sends a signal to the child, we ignore it
5339 			// ourselves
5340 #  ifdef HAVE_SETSID
5341 			kill(-pid, SIGINT);
5342 #  else
5343 			kill(0, SIGINT);
5344 #  endif
5345 			got_int = FALSE;
5346 		    }
5347 # ifdef __NeXT__
5348 		    wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *)0);
5349 # else
5350 		    wait_pid = waitpid(pid, &status, WNOHANG);
5351 # endif
5352 		    if ((wait_pid == (pid_t)-1 && errno == ECHILD)
5353 			    || (wait_pid == pid && WIFEXITED(status)))
5354 		    {
5355 			wait_pid = pid;
5356 			break;
5357 		    }
5358 
5359 		    // Handle any X events, e.g. serving the clipboard.
5360 		    clip_update();
5361 
5362 		    // Wait for 1 to 10 msec. 1 is faster but gives the child
5363 		    // less time, gradually wait longer.
5364 		    mch_delay(delay_msec,
5365 				   MCH_DELAY_IGNOREINPUT | MCH_DELAY_SETTMODE);
5366 		    if (++delay_msec > 10)
5367 			delay_msec = 10;
5368 		}
5369 
5370 		if (tmode == TMODE_RAW)
5371 		    // possibly enables modifyOtherKeys again
5372 		    out_str(T_CTI);
5373 	    }
5374 # endif
5375 
5376 	    /*
5377 	     * Wait until our child has exited.
5378 	     * Ignore wait() returning pids of other children and returning
5379 	     * because of some signal like SIGWINCH.
5380 	     * Don't wait if wait_pid was already set above, indicating the
5381 	     * child already exited.
5382 	     */
5383 	    if (wait_pid != pid)
5384 		wait_pid = wait4pid(pid, &status);
5385 
5386 # ifdef FEAT_GUI
5387 	    // Close slave side of pty.  Only do this after the child has
5388 	    // exited, otherwise the child may hang when it tries to write on
5389 	    // the pty.
5390 	    if (pty_master_fd >= 0)
5391 		close(pty_slave_fd);
5392 # endif
5393 
5394 	    // Make sure the child that writes to the external program is
5395 	    // dead.
5396 	    if (wpid > 0)
5397 	    {
5398 		kill(wpid, SIGKILL);
5399 		wait4pid(wpid, NULL);
5400 	    }
5401 
5402 # ifdef FEAT_JOB_CHANNEL
5403 	    --dont_check_job_ended;
5404 # endif
5405 
5406 	    /*
5407 	     * Set to raw mode right now, otherwise a CTRL-C after
5408 	     * catch_signals() will kill Vim.
5409 	     */
5410 	    if (tmode == TMODE_RAW)
5411 		settmode(TMODE_RAW);
5412 	    did_settmode = TRUE;
5413 	    set_signals();
5414 
5415 	    if (WIFEXITED(status))
5416 	    {
5417 		// LINTED avoid "bitwise operation on signed value"
5418 		retval = WEXITSTATUS(status);
5419 		if (retval != 0 && !emsg_silent)
5420 		{
5421 		    if (retval == EXEC_FAILED)
5422 		    {
5423 			msg_puts(_("\nCannot execute shell "));
5424 			msg_outtrans(p_sh);
5425 			msg_putchar('\n');
5426 		    }
5427 		    else if (!(options & SHELL_SILENT))
5428 		    {
5429 			msg_puts(_("\nshell returned "));
5430 			msg_outnum((long)retval);
5431 			msg_putchar('\n');
5432 		    }
5433 		}
5434 	    }
5435 	    else
5436 		msg_puts(_("\nCommand terminated\n"));
5437 	}
5438     }
5439 
5440 error:
5441     if (!did_settmode)
5442 	if (tmode == TMODE_RAW)
5443 	    settmode(TMODE_RAW);	// set to raw mode
5444 # ifdef FEAT_TITLE
5445     resettitle();
5446 # endif
5447     vim_free(argv);
5448     vim_free(tofree1);
5449     vim_free(tofree2);
5450 
5451     return retval;
5452 }
5453 #endif // USE_SYSTEM
5454 
5455     int
mch_call_shell(char_u * cmd,int options)5456 mch_call_shell(
5457     char_u	*cmd,
5458     int		options)	// SHELL_*, see vim.h
5459 {
5460 #if defined(FEAT_GUI) && defined(FEAT_TERMINAL)
5461     if (gui.in_use && vim_strchr(p_go, GO_TERMINAL) != NULL)
5462 	return mch_call_shell_terminal(cmd, options);
5463 #endif
5464 #ifdef USE_SYSTEM
5465     return mch_call_shell_system(cmd, options);
5466 #else
5467     return mch_call_shell_fork(cmd, options);
5468 #endif
5469 }
5470 
5471 #if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
5472     void
mch_job_start(char ** argv,job_T * job,jobopt_T * options,int is_terminal)5473 mch_job_start(char **argv, job_T *job, jobopt_T *options, int is_terminal)
5474 {
5475     pid_t	pid;
5476     int		fd_in[2] = {-1, -1};	// for stdin
5477     int		fd_out[2] = {-1, -1};	// for stdout
5478     int		fd_err[2] = {-1, -1};	// for stderr
5479     int		pty_master_fd = -1;
5480     int		pty_slave_fd = -1;
5481     channel_T	*channel = NULL;
5482     int		use_null_for_in = options->jo_io[PART_IN] == JIO_NULL;
5483     int		use_null_for_out = options->jo_io[PART_OUT] == JIO_NULL;
5484     int		use_null_for_err = options->jo_io[PART_ERR] == JIO_NULL;
5485     int		use_file_for_in = options->jo_io[PART_IN] == JIO_FILE;
5486     int		use_file_for_out = options->jo_io[PART_OUT] == JIO_FILE;
5487     int		use_file_for_err = options->jo_io[PART_ERR] == JIO_FILE;
5488     int		use_buffer_for_in = options->jo_io[PART_IN] == JIO_BUFFER;
5489     int		use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
5490     SIGSET_DECL(curset)
5491 
5492     if (use_out_for_err && use_null_for_out)
5493 	use_null_for_err = TRUE;
5494 
5495     // default is to fail
5496     job->jv_status = JOB_FAILED;
5497 
5498     if (options->jo_pty
5499 	    && (!(use_file_for_in || use_null_for_in)
5500 		|| !(use_file_for_out || use_null_for_out)
5501 		|| !(use_out_for_err || use_file_for_err || use_null_for_err)))
5502 	open_pty(&pty_master_fd, &pty_slave_fd,
5503 					    &job->jv_tty_out, &job->jv_tty_in);
5504 
5505     // TODO: without the channel feature connect the child to /dev/null?
5506     // Open pipes for stdin, stdout, stderr.
5507     if (use_file_for_in)
5508     {
5509 	char_u *fname = options->jo_io_name[PART_IN];
5510 
5511 	fd_in[0] = mch_open((char *)fname, O_RDONLY, 0);
5512 	if (fd_in[0] < 0)
5513 	{
5514 	    semsg(_(e_notopen), fname);
5515 	    goto failed;
5516 	}
5517     }
5518     else
5519 	// When writing buffer lines to the input don't use the pty, so that
5520 	// the pipe can be closed when all lines were written.
5521 	if (!use_null_for_in && (pty_master_fd < 0 || use_buffer_for_in)
5522 							    && pipe(fd_in) < 0)
5523 	    goto failed;
5524 
5525     if (use_file_for_out)
5526     {
5527 	char_u *fname = options->jo_io_name[PART_OUT];
5528 
5529 	fd_out[1] = mch_open((char *)fname, O_WRONLY | O_CREAT | O_TRUNC, 0644);
5530 	if (fd_out[1] < 0)
5531 	{
5532 	    semsg(_(e_notopen), fname);
5533 	    goto failed;
5534 	}
5535     }
5536     else if (!use_null_for_out && pty_master_fd < 0 && pipe(fd_out) < 0)
5537 	goto failed;
5538 
5539     if (use_file_for_err)
5540     {
5541 	char_u *fname = options->jo_io_name[PART_ERR];
5542 
5543 	fd_err[1] = mch_open((char *)fname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
5544 	if (fd_err[1] < 0)
5545 	{
5546 	    semsg(_(e_notopen), fname);
5547 	    goto failed;
5548 	}
5549     }
5550     else if (!use_out_for_err && !use_null_for_err
5551 				      && pty_master_fd < 0 && pipe(fd_err) < 0)
5552 	goto failed;
5553 
5554     if (!use_null_for_in || !use_null_for_out || !use_null_for_err)
5555     {
5556 	if (options->jo_set & JO_CHANNEL)
5557 	{
5558 	    channel = options->jo_channel;
5559 	    if (channel != NULL)
5560 		++channel->ch_refcount;
5561 	}
5562 	else
5563 	    channel = add_channel();
5564 	if (channel == NULL)
5565 	    goto failed;
5566 	if (job->jv_tty_out != NULL)
5567 	    ch_log(channel, "using pty %s on fd %d",
5568 					       job->jv_tty_out, pty_master_fd);
5569     }
5570 
5571     BLOCK_SIGNALS(&curset);
5572     pid = fork();	// maybe we should use vfork()
5573     if (pid == -1)
5574     {
5575 	// failed to fork
5576 	UNBLOCK_SIGNALS(&curset);
5577 	goto failed;
5578     }
5579     if (pid == 0)
5580     {
5581 	int	null_fd = -1;
5582 	int	stderr_works = TRUE;
5583 
5584 	// child
5585 	reset_signals();		// handle signals normally
5586 	UNBLOCK_SIGNALS(&curset);
5587 
5588 # ifdef FEAT_JOB_CHANNEL
5589 	if (ch_log_active())
5590 	    // close the log file in the child
5591 	    ch_logfile((char_u *)"", (char_u *)"");
5592 # endif
5593 
5594 # ifdef HAVE_SETSID
5595 	// Create our own process group, so that the child and all its
5596 	// children can be kill()ed.  Don't do this when using pipes,
5597 	// because stdin is not a tty, we would lose /dev/tty.
5598 	(void)setsid();
5599 # endif
5600 
5601 # ifdef FEAT_TERMINAL
5602 	if (options->jo_term_rows > 0)
5603 	{
5604 	    char *term = (char *)T_NAME;
5605 
5606 #ifdef FEAT_GUI
5607 	    if (term_is_gui(T_NAME))
5608 		// In the GUI 'term' is not what we want, use $TERM.
5609 		term = getenv("TERM");
5610 #endif
5611 	    // Use 'term' or $TERM if it starts with "xterm", otherwise fall
5612 	    // back to "xterm" or "xterm-color".
5613 	    if (term == NULL || *term == NUL || STRNCMP(term, "xterm", 5) != 0)
5614 	    {
5615 		if (t_colors >= 256)
5616 		    // TODO: should we check this name is supported?
5617 		    term = "xterm-256color";
5618 		else if (t_colors > 16)
5619 		    term = "xterm-color";
5620 		else
5621 		    term = "xterm";
5622 	    }
5623 	    set_child_environment(
5624 		    (long)options->jo_term_rows,
5625 		    (long)options->jo_term_cols,
5626 		    term,
5627 		    is_terminal);
5628 	}
5629 	else
5630 # endif
5631 	    set_default_child_environment(is_terminal);
5632 
5633 	if (options->jo_env != NULL)
5634 	{
5635 	    dict_T	*dict = options->jo_env;
5636 	    hashitem_T	*hi;
5637 	    int		todo = (int)dict->dv_hashtab.ht_used;
5638 
5639 	    for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi)
5640 		if (!HASHITEM_EMPTY(hi))
5641 		{
5642 		    typval_T *item = &dict_lookup(hi)->di_tv;
5643 
5644 		    vim_setenv((char_u*)hi->hi_key, tv_get_string(item));
5645 		    --todo;
5646 		}
5647 	}
5648 
5649 	if (use_null_for_in || use_null_for_out || use_null_for_err)
5650 	{
5651 	    null_fd = open("/dev/null", O_RDWR | O_EXTRA, 0);
5652 	    if (null_fd < 0)
5653 	    {
5654 		perror("opening /dev/null failed");
5655 		_exit(OPEN_NULL_FAILED);
5656 	    }
5657 	}
5658 
5659 	if (pty_slave_fd >= 0)
5660 	{
5661 	    // push stream discipline modules
5662 	    setup_slavepty(pty_slave_fd);
5663 #  ifdef TIOCSCTTY
5664 	    // Try to become controlling tty (probably doesn't work,
5665 	    // unless run by root)
5666 	    ioctl(pty_slave_fd, TIOCSCTTY, (char *)NULL);
5667 #  endif
5668 	}
5669 
5670 	// set up stdin for the child
5671 	close(0);
5672 	if (use_null_for_in && null_fd >= 0)
5673 	    vim_ignored = dup(null_fd);
5674 	else if (fd_in[0] < 0)
5675 	    vim_ignored = dup(pty_slave_fd);
5676 	else
5677 	    vim_ignored = dup(fd_in[0]);
5678 
5679 	// set up stderr for the child
5680 	close(2);
5681 	if (use_null_for_err && null_fd >= 0)
5682 	{
5683 	    vim_ignored = dup(null_fd);
5684 	    stderr_works = FALSE;
5685 	}
5686 	else if (use_out_for_err)
5687 	    vim_ignored = dup(fd_out[1]);
5688 	else if (fd_err[1] < 0)
5689 	    vim_ignored = dup(pty_slave_fd);
5690 	else
5691 	    vim_ignored = dup(fd_err[1]);
5692 
5693 	// set up stdout for the child
5694 	close(1);
5695 	if (use_null_for_out && null_fd >= 0)
5696 	    vim_ignored = dup(null_fd);
5697 	else if (fd_out[1] < 0)
5698 	    vim_ignored = dup(pty_slave_fd);
5699 	else
5700 	    vim_ignored = dup(fd_out[1]);
5701 
5702 	if (fd_in[0] >= 0)
5703 	    close(fd_in[0]);
5704 	if (fd_in[1] >= 0)
5705 	    close(fd_in[1]);
5706 	if (fd_out[0] >= 0)
5707 	    close(fd_out[0]);
5708 	if (fd_out[1] >= 0)
5709 	    close(fd_out[1]);
5710 	if (fd_err[0] >= 0)
5711 	    close(fd_err[0]);
5712 	if (fd_err[1] >= 0)
5713 	    close(fd_err[1]);
5714 	if (pty_master_fd >= 0)
5715 	{
5716 	    close(pty_master_fd); // not used in the child
5717 	    close(pty_slave_fd);  // was duped above
5718 	}
5719 
5720 	if (null_fd >= 0)
5721 	    close(null_fd);
5722 
5723 	if (options->jo_cwd != NULL && mch_chdir((char *)options->jo_cwd) != 0)
5724 	    _exit(EXEC_FAILED);
5725 
5726 	// See above for type of argv.
5727 	execvp(argv[0], argv);
5728 
5729 	if (stderr_works)
5730 	    perror("executing job failed");
5731 # ifdef EXITFREE
5732 	// calling free_all_mem() here causes problems. Ignore valgrind
5733 	// reporting possibly leaked memory.
5734 # endif
5735 	_exit(EXEC_FAILED);	    // exec failed, return failure code
5736     }
5737 
5738     // parent
5739     UNBLOCK_SIGNALS(&curset);
5740 
5741     job->jv_pid = pid;
5742     job->jv_status = JOB_STARTED;
5743     job->jv_channel = channel;  // ch_refcount was set above
5744 
5745     if (pty_master_fd >= 0)
5746 	close(pty_slave_fd); // not used in the parent
5747     // close child stdin, stdout and stderr
5748     if (fd_in[0] >= 0)
5749 	close(fd_in[0]);
5750     if (fd_out[1] >= 0)
5751 	close(fd_out[1]);
5752     if (fd_err[1] >= 0)
5753 	close(fd_err[1]);
5754     if (channel != NULL)
5755     {
5756 	int in_fd = INVALID_FD;
5757 	int out_fd = INVALID_FD;
5758 	int err_fd = INVALID_FD;
5759 
5760 	if (!(use_file_for_in || use_null_for_in))
5761 	    in_fd = fd_in[1] >= 0 ? fd_in[1] : pty_master_fd;
5762 
5763 	if (!(use_file_for_out || use_null_for_out))
5764 	    out_fd = fd_out[0] >= 0 ? fd_out[0] : pty_master_fd;
5765 
5766 	// When using pty_master_fd only set it for stdout, do not duplicate
5767 	// it for stderr, it only needs to be read once.
5768 	if (!(use_out_for_err || use_file_for_err || use_null_for_err))
5769 	{
5770 	    if (fd_err[0] >= 0)
5771 		err_fd = fd_err[0];
5772 	    else if (out_fd != pty_master_fd)
5773 		err_fd = pty_master_fd;
5774 	}
5775 
5776 	channel_set_pipes(channel, in_fd, out_fd, err_fd);
5777 	channel_set_job(channel, job, options);
5778     }
5779     else
5780     {
5781 	if (fd_in[1] >= 0)
5782 	    close(fd_in[1]);
5783 	if (fd_out[0] >= 0)
5784 	    close(fd_out[0]);
5785 	if (fd_err[0] >= 0)
5786 	    close(fd_err[0]);
5787 	if (pty_master_fd >= 0)
5788 	    close(pty_master_fd);
5789     }
5790 
5791     // success!
5792     return;
5793 
5794 failed:
5795     channel_unref(channel);
5796     if (fd_in[0] >= 0)
5797 	close(fd_in[0]);
5798     if (fd_in[1] >= 0)
5799 	close(fd_in[1]);
5800     if (fd_out[0] >= 0)
5801 	close(fd_out[0]);
5802     if (fd_out[1] >= 0)
5803 	close(fd_out[1]);
5804     if (fd_err[0] >= 0)
5805 	close(fd_err[0]);
5806     if (fd_err[1] >= 0)
5807 	close(fd_err[1]);
5808     if (pty_master_fd >= 0)
5809 	close(pty_master_fd);
5810     if (pty_slave_fd >= 0)
5811 	close(pty_slave_fd);
5812 }
5813 
5814     static char_u *
get_signal_name(int sig)5815 get_signal_name(int sig)
5816 {
5817     int		i;
5818     char_u	numbuf[NUMBUFLEN];
5819 
5820     if (sig == SIGKILL)
5821 	return vim_strsave((char_u *)"kill");
5822 
5823     for (i = 0; signal_info[i].sig != -1; i++)
5824 	if (sig == signal_info[i].sig)
5825 	    return strlow_save((char_u *)signal_info[i].name);
5826 
5827     vim_snprintf((char *)numbuf, NUMBUFLEN, "%d", sig);
5828     return vim_strsave(numbuf);
5829 }
5830 
5831     char *
mch_job_status(job_T * job)5832 mch_job_status(job_T *job)
5833 {
5834 # ifdef HAVE_UNION_WAIT
5835     union wait	status;
5836 # else
5837     int		status = -1;
5838 # endif
5839     pid_t	wait_pid = 0;
5840 
5841 # ifdef __NeXT__
5842     wait_pid = wait4(job->jv_pid, &status, WNOHANG, (struct rusage *)0);
5843 # else
5844     wait_pid = waitpid(job->jv_pid, &status, WNOHANG);
5845 # endif
5846     if (wait_pid == -1)
5847     {
5848 	// process must have exited
5849 	if (job->jv_status < JOB_ENDED)
5850 	    ch_log(job->jv_channel, "Job no longer exists: %s",
5851 							      strerror(errno));
5852 	goto return_dead;
5853     }
5854     if (wait_pid == 0)
5855 	return "run";
5856     if (WIFEXITED(status))
5857     {
5858 	// LINTED avoid "bitwise operation on signed value"
5859 	job->jv_exitval = WEXITSTATUS(status);
5860 	if (job->jv_status < JOB_ENDED)
5861 	    ch_log(job->jv_channel, "Job exited with %d", job->jv_exitval);
5862 	goto return_dead;
5863     }
5864     if (WIFSIGNALED(status))
5865     {
5866 	job->jv_exitval = -1;
5867 	job->jv_termsig = get_signal_name(WTERMSIG(status));
5868 	if (job->jv_status < JOB_ENDED && job->jv_termsig != NULL)
5869 	    ch_log(job->jv_channel, "Job terminated by signal \"%s\"",
5870 							      job->jv_termsig);
5871 	goto return_dead;
5872     }
5873     return "run";
5874 
5875 return_dead:
5876     if (job->jv_status < JOB_ENDED)
5877 	job->jv_status = JOB_ENDED;
5878     return "dead";
5879 }
5880 
5881     job_T *
mch_detect_ended_job(job_T * job_list)5882 mch_detect_ended_job(job_T *job_list)
5883 {
5884 # ifdef HAVE_UNION_WAIT
5885     union wait	status;
5886 # else
5887     int		status = -1;
5888 # endif
5889     pid_t	wait_pid = 0;
5890     job_T	*job;
5891 
5892 # ifndef USE_SYSTEM
5893     // Do not do this when waiting for a shell command to finish, we would get
5894     // the exit value here (and discard it), the exit value obtained there
5895     // would then be wrong.
5896     if (dont_check_job_ended > 0)
5897 	return NULL;
5898 # endif
5899 
5900 # ifdef __NeXT__
5901     wait_pid = wait4(-1, &status, WNOHANG, (struct rusage *)0);
5902 # else
5903     wait_pid = waitpid(-1, &status, WNOHANG);
5904 # endif
5905     if (wait_pid <= 0)
5906 	// no process ended
5907 	return NULL;
5908     for (job = job_list; job != NULL; job = job->jv_next)
5909     {
5910 	if (job->jv_pid == wait_pid)
5911 	{
5912 	    if (WIFEXITED(status))
5913 		// LINTED avoid "bitwise operation on signed value"
5914 		job->jv_exitval = WEXITSTATUS(status);
5915 	    else if (WIFSIGNALED(status))
5916 	    {
5917 		job->jv_exitval = -1;
5918 		job->jv_termsig = get_signal_name(WTERMSIG(status));
5919 	    }
5920 	    if (job->jv_status < JOB_ENDED)
5921 	    {
5922 		ch_log(job->jv_channel, "Job ended");
5923 		job->jv_status = JOB_ENDED;
5924 	    }
5925 	    return job;
5926 	}
5927     }
5928     return NULL;
5929 }
5930 
5931 /*
5932  * Send a (deadly) signal to "job".
5933  * Return FAIL if "how" is not a valid name.
5934  */
5935     int
mch_signal_job(job_T * job,char_u * how)5936 mch_signal_job(job_T *job, char_u *how)
5937 {
5938     int	    sig = -1;
5939 
5940     if (*how == NUL || STRCMP(how, "term") == 0)
5941 	sig = SIGTERM;
5942     else if (STRCMP(how, "hup") == 0)
5943 	sig = SIGHUP;
5944     else if (STRCMP(how, "quit") == 0)
5945 	sig = SIGQUIT;
5946     else if (STRCMP(how, "int") == 0)
5947 	sig = SIGINT;
5948     else if (STRCMP(how, "kill") == 0)
5949 	sig = SIGKILL;
5950 #ifdef SIGWINCH
5951     else if (STRCMP(how, "winch") == 0)
5952 	sig = SIGWINCH;
5953 #endif
5954     else if (isdigit(*how))
5955 	sig = atoi((char *)how);
5956     else
5957 	return FAIL;
5958 
5959     // Never kill ourselves!
5960     if (job->jv_pid != 0)
5961     {
5962 	// TODO: have an option to only kill the process, not the group?
5963 	kill(-job->jv_pid, sig);
5964 	kill(job->jv_pid, sig);
5965     }
5966 
5967     return OK;
5968 }
5969 
5970 /*
5971  * Clear the data related to "job".
5972  */
5973     void
mch_clear_job(job_T * job)5974 mch_clear_job(job_T *job)
5975 {
5976     // call waitpid because child process may become zombie
5977 # ifdef __NeXT__
5978     (void)wait4(job->jv_pid, NULL, WNOHANG, (struct rusage *)0);
5979 # else
5980     (void)waitpid(job->jv_pid, NULL, WNOHANG);
5981 # endif
5982 }
5983 #endif
5984 
5985 #if defined(FEAT_TERMINAL) || defined(PROTO)
5986     int
mch_create_pty_channel(job_T * job,jobopt_T * options)5987 mch_create_pty_channel(job_T *job, jobopt_T *options)
5988 {
5989     int		pty_master_fd = -1;
5990     int		pty_slave_fd = -1;
5991     channel_T	*channel;
5992 
5993     open_pty(&pty_master_fd, &pty_slave_fd, &job->jv_tty_out, &job->jv_tty_in);
5994     if (pty_master_fd < 0 || pty_slave_fd < 0)
5995 	return FAIL;
5996     close(pty_slave_fd);
5997 
5998     channel = add_channel();
5999     if (channel == NULL)
6000     {
6001 	close(pty_master_fd);
6002 	return FAIL;
6003     }
6004     if (job->jv_tty_out != NULL)
6005 	ch_log(channel, "using pty %s on fd %d",
6006 					       job->jv_tty_out, pty_master_fd);
6007     job->jv_channel = channel;  // ch_refcount was set by add_channel()
6008     channel->ch_keep_open = TRUE;
6009 
6010     // Only set the pty_master_fd for stdout, do not duplicate it for stderr,
6011     // it only needs to be read once.
6012     channel_set_pipes(channel, pty_master_fd, pty_master_fd, INVALID_FD);
6013     channel_set_job(channel, job, options);
6014     return OK;
6015 }
6016 #endif
6017 
6018 /*
6019  * Check for CTRL-C typed by reading all available characters.
6020  * In cooked mode we should get SIGINT, no need to check.
6021  */
6022     void
mch_breakcheck(int force)6023 mch_breakcheck(int force)
6024 {
6025     if ((mch_cur_tmode == TMODE_RAW || force)
6026 			       && RealWaitForChar(read_cmd_fd, 0L, NULL, NULL))
6027 	fill_input_buf(FALSE);
6028 }
6029 
6030 /*
6031  * Wait "msec" msec until a character is available from the mouse, keyboard,
6032  * from inbuf[].
6033  * "msec" == -1 will block forever.
6034  * Invokes timer callbacks when needed.
6035  * When "ignore_input" is TRUE even check for pending input when input is
6036  * already available.
6037  * "interrupted" (if not NULL) is set to TRUE when no character is available
6038  * but something else needs to be done.
6039  * Returns TRUE when a character is available.
6040  * When a GUI is being used, this will never get called -- webb
6041  */
6042     static int
WaitForChar(long msec,int * interrupted,int ignore_input)6043 WaitForChar(long msec, int *interrupted, int ignore_input)
6044 {
6045 #ifdef FEAT_TIMERS
6046     return ui_wait_for_chars_or_timer(
6047 		    msec, WaitForCharOrMouse, interrupted, ignore_input) == OK;
6048 #else
6049     return WaitForCharOrMouse(msec, interrupted, ignore_input);
6050 #endif
6051 }
6052 
6053 /*
6054  * Wait "msec" msec until a character is available from the mouse or keyboard
6055  * or from inbuf[].
6056  * "msec" == -1 will block forever.
6057  * for "ignore_input" see WaitForCharOr().
6058  * "interrupted" (if not NULL) is set to TRUE when no character is available
6059  * but something else needs to be done.
6060  * When a GUI is being used, this will never get called -- webb
6061  */
6062     static int
WaitForCharOrMouse(long msec,int * interrupted,int ignore_input)6063 WaitForCharOrMouse(long msec, int *interrupted, int ignore_input)
6064 {
6065 #ifdef FEAT_MOUSE_GPM
6066     int		gpm_process_wanted;
6067 #endif
6068 #ifdef FEAT_XCLIPBOARD
6069     int		rest;
6070 #endif
6071     int		avail;
6072 
6073     if (!ignore_input && input_available())	    // something in inbuf[]
6074 	return 1;
6075 
6076 #if defined(FEAT_MOUSE_DEC)
6077     // May need to query the mouse position.
6078     if (WantQueryMouse)
6079     {
6080 	WantQueryMouse = FALSE;
6081 	if (!no_query_mouse_for_testing)
6082 	    mch_write((char_u *)IF_EB("\033[1'|", ESC_STR "[1'|"), 5);
6083     }
6084 #endif
6085 
6086     /*
6087      * For FEAT_MOUSE_GPM and FEAT_XCLIPBOARD we loop here to process mouse
6088      * events.  This is a bit complicated, because they might both be defined.
6089      */
6090 #if defined(FEAT_MOUSE_GPM) || defined(FEAT_XCLIPBOARD)
6091 # ifdef FEAT_XCLIPBOARD
6092     rest = 0;
6093     if (do_xterm_trace())
6094 	rest = msec;
6095 # endif
6096     do
6097     {
6098 # ifdef FEAT_XCLIPBOARD
6099 	if (rest != 0)
6100 	{
6101 	    msec = XT_TRACE_DELAY;
6102 	    if (rest >= 0 && rest < XT_TRACE_DELAY)
6103 		msec = rest;
6104 	    if (rest >= 0)
6105 		rest -= msec;
6106 	}
6107 # endif
6108 # ifdef FEAT_SOUND_CANBERRA
6109 	// Invoke any pending sound callbacks.
6110 	if (has_sound_callback_in_queue())
6111 	    invoke_sound_callback();
6112 # endif
6113 # ifdef FEAT_MOUSE_GPM
6114 	gpm_process_wanted = 0;
6115 	avail = RealWaitForChar(read_cmd_fd, msec,
6116 					     &gpm_process_wanted, interrupted);
6117 	if (!avail && !gpm_process_wanted)
6118 # else
6119 	avail = RealWaitForChar(read_cmd_fd, msec, NULL, interrupted);
6120 	if (!avail)
6121 # endif
6122 	{
6123 	    if (!ignore_input && input_available())
6124 		return 1;
6125 # ifdef FEAT_XCLIPBOARD
6126 	    if (rest == 0 || !do_xterm_trace())
6127 # endif
6128 		break;
6129 	}
6130     }
6131     while (FALSE
6132 # ifdef FEAT_MOUSE_GPM
6133 	   || (gpm_process_wanted && mch_gpm_process() == 0)
6134 # endif
6135 # ifdef FEAT_XCLIPBOARD
6136 	   || (!avail && rest != 0)
6137 # endif
6138 	  )
6139 	;
6140 
6141 #else
6142     avail = RealWaitForChar(read_cmd_fd, msec, NULL, interrupted);
6143 #endif
6144     return avail;
6145 }
6146 
6147 #ifndef VMS
6148 /*
6149  * Wait "msec" msec until a character is available from file descriptor "fd".
6150  * "msec" == 0 will check for characters once.
6151  * "msec" == -1 will block until a character is available.
6152  * When a GUI is being used, this will not be used for input -- webb
6153  * Or when a Linux GPM mouse event is waiting.
6154  * Or when a clientserver message is on the queue.
6155  * "interrupted" (if not NULL) is set to TRUE when no character is available
6156  * but something else needs to be done.
6157  */
6158     static int
RealWaitForChar(int fd,long msec,int * check_for_gpm UNUSED,int * interrupted)6159 RealWaitForChar(int fd, long msec, int *check_for_gpm UNUSED, int *interrupted)
6160 {
6161     int		ret;
6162     int		result;
6163 #if defined(FEAT_XCLIPBOARD) || defined(USE_XSMP) || defined(FEAT_MZSCHEME)
6164     static int	busy = FALSE;
6165 
6166     // May retry getting characters after an event was handled.
6167 # define MAY_LOOP
6168 
6169 # ifdef ELAPSED_FUNC
6170     // Remember at what time we started, so that we know how much longer we
6171     // should wait after being interrupted.
6172     long	start_msec = msec;
6173     elapsed_T	start_tv;
6174 
6175     if (msec > 0)
6176 	ELAPSED_INIT(start_tv);
6177 # endif
6178 
6179     // Handle being called recursively.  This may happen for the session
6180     // manager stuff, it may save the file, which does a breakcheck.
6181     if (busy)
6182 	return 0;
6183 #endif
6184 
6185 #ifdef MAY_LOOP
6186     for (;;)
6187 #endif
6188     {
6189 #ifdef MAY_LOOP
6190 	int		finished = TRUE; // default is to 'loop' just once
6191 # ifdef FEAT_MZSCHEME
6192 	int		mzquantum_used = FALSE;
6193 # endif
6194 #endif
6195 #ifndef HAVE_SELECT
6196 			// each channel may use in, out and err
6197 	struct pollfd   fds[6 + 3 * MAX_OPEN_CHANNELS];
6198 	int		nfd;
6199 # ifdef FEAT_XCLIPBOARD
6200 	int		xterm_idx = -1;
6201 # endif
6202 # ifdef FEAT_MOUSE_GPM
6203 	int		gpm_idx = -1;
6204 # endif
6205 # ifdef USE_XSMP
6206 	int		xsmp_idx = -1;
6207 # endif
6208 	int		towait = (int)msec;
6209 
6210 # ifdef FEAT_MZSCHEME
6211 	mzvim_check_threads();
6212 	if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
6213 	{
6214 	    towait = (int)p_mzq;    // don't wait longer than 'mzquantum'
6215 	    mzquantum_used = TRUE;
6216 	}
6217 # endif
6218 	fds[0].fd = fd;
6219 	fds[0].events = POLLIN;
6220 	nfd = 1;
6221 
6222 # ifdef FEAT_XCLIPBOARD
6223 	may_restore_clipboard();
6224 	if (xterm_Shell != (Widget)0)
6225 	{
6226 	    xterm_idx = nfd;
6227 	    fds[nfd].fd = ConnectionNumber(xterm_dpy);
6228 	    fds[nfd].events = POLLIN;
6229 	    nfd++;
6230 	}
6231 # endif
6232 # ifdef FEAT_MOUSE_GPM
6233 	if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
6234 	{
6235 	    gpm_idx = nfd;
6236 	    fds[nfd].fd = gpm_fd;
6237 	    fds[nfd].events = POLLIN;
6238 	    nfd++;
6239 	}
6240 # endif
6241 # ifdef USE_XSMP
6242 	if (xsmp_icefd != -1)
6243 	{
6244 	    xsmp_idx = nfd;
6245 	    fds[nfd].fd = xsmp_icefd;
6246 	    fds[nfd].events = POLLIN;
6247 	    nfd++;
6248 	}
6249 # endif
6250 #ifdef FEAT_JOB_CHANNEL
6251 	nfd = channel_poll_setup(nfd, &fds, &towait);
6252 #endif
6253 	if (interrupted != NULL)
6254 	    *interrupted = FALSE;
6255 
6256 	ret = poll(fds, nfd, towait);
6257 
6258 	result = ret > 0 && (fds[0].revents & POLLIN);
6259 	if (result == 0 && interrupted != NULL && ret > 0)
6260 	    *interrupted = TRUE;
6261 
6262 # ifdef FEAT_MZSCHEME
6263 	if (ret == 0 && mzquantum_used)
6264 	    // MzThreads scheduling is required and timeout occurred
6265 	    finished = FALSE;
6266 # endif
6267 
6268 # ifdef FEAT_XCLIPBOARD
6269 	if (xterm_Shell != (Widget)0 && (fds[xterm_idx].revents & POLLIN))
6270 	{
6271 	    xterm_update();      // Maybe we should hand out clipboard
6272 	    if (--ret == 0 && !input_available())
6273 		// Try again
6274 		finished = FALSE;
6275 	}
6276 # endif
6277 # ifdef FEAT_MOUSE_GPM
6278 	if (gpm_idx >= 0 && (fds[gpm_idx].revents & POLLIN))
6279 	    *check_for_gpm = 1;
6280 # endif
6281 # ifdef USE_XSMP
6282 	if (xsmp_idx >= 0 && (fds[xsmp_idx].revents & (POLLIN | POLLHUP)))
6283 	{
6284 	    if (fds[xsmp_idx].revents & POLLIN)
6285 	    {
6286 		busy = TRUE;
6287 		xsmp_handle_requests();
6288 		busy = FALSE;
6289 	    }
6290 	    else if (fds[xsmp_idx].revents & POLLHUP)
6291 	    {
6292 		if (p_verbose > 0)
6293 		    verb_msg(_("XSMP lost ICE connection"));
6294 		xsmp_close();
6295 	    }
6296 	    if (--ret == 0)
6297 		finished = FALSE;	// Try again
6298 	}
6299 # endif
6300 #ifdef FEAT_JOB_CHANNEL
6301 	// also call when ret == 0, we may be polling a keep-open channel
6302 	if (ret >= 0)
6303 	    channel_poll_check(ret, &fds);
6304 #endif
6305 
6306 #else // HAVE_SELECT
6307 
6308 	struct timeval  tv;
6309 	struct timeval	*tvp;
6310 	// These are static because they can take 8 Kbyte each and cause the
6311 	// signal stack to run out with -O3.
6312 	static fd_set	rfds, wfds, efds;
6313 	int		maxfd;
6314 	long		towait = msec;
6315 
6316 # ifdef FEAT_MZSCHEME
6317 	mzvim_check_threads();
6318 	if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
6319 	{
6320 	    towait = p_mzq;	// don't wait longer than 'mzquantum'
6321 	    mzquantum_used = TRUE;
6322 	}
6323 # endif
6324 
6325 	if (towait >= 0)
6326 	{
6327 	    tv.tv_sec = towait / 1000;
6328 	    tv.tv_usec = (towait % 1000) * (1000000/1000);
6329 	    tvp = &tv;
6330 	}
6331 	else
6332 	    tvp = NULL;
6333 
6334 	/*
6335 	 * Select on ready for reading and exceptional condition (end of file).
6336 	 */
6337 select_eintr:
6338 	FD_ZERO(&rfds);
6339 	FD_ZERO(&wfds);
6340 	FD_ZERO(&efds);
6341 	FD_SET(fd, &rfds);
6342 # if !defined(__QNX__) && !defined(__CYGWIN32__)
6343 	// For QNX select() always returns 1 if this is set.  Why?
6344 	FD_SET(fd, &efds);
6345 # endif
6346 	maxfd = fd;
6347 
6348 # ifdef FEAT_XCLIPBOARD
6349 	may_restore_clipboard();
6350 	if (xterm_Shell != (Widget)0)
6351 	{
6352 	    FD_SET(ConnectionNumber(xterm_dpy), &rfds);
6353 	    if (maxfd < ConnectionNumber(xterm_dpy))
6354 		maxfd = ConnectionNumber(xterm_dpy);
6355 
6356 	    // An event may have already been read but not handled.  In
6357 	    // particularly, XFlush may cause this.
6358 	    xterm_update();
6359 	}
6360 # endif
6361 # ifdef FEAT_MOUSE_GPM
6362 	if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
6363 	{
6364 	    FD_SET(gpm_fd, &rfds);
6365 	    FD_SET(gpm_fd, &efds);
6366 	    if (maxfd < gpm_fd)
6367 		maxfd = gpm_fd;
6368 	}
6369 # endif
6370 # ifdef USE_XSMP
6371 	if (xsmp_icefd != -1)
6372 	{
6373 	    FD_SET(xsmp_icefd, &rfds);
6374 	    FD_SET(xsmp_icefd, &efds);
6375 	    if (maxfd < xsmp_icefd)
6376 		maxfd = xsmp_icefd;
6377 	}
6378 # endif
6379 # ifdef FEAT_JOB_CHANNEL
6380 	maxfd = channel_select_setup(maxfd, &rfds, &wfds, &tv, &tvp);
6381 # endif
6382 	if (interrupted != NULL)
6383 	    *interrupted = FALSE;
6384 
6385 	ret = select(maxfd + 1, SELECT_TYPE_ARG234 &rfds,
6386 		      SELECT_TYPE_ARG234 &wfds, SELECT_TYPE_ARG234 &efds, tvp);
6387 	result = ret > 0 && FD_ISSET(fd, &rfds);
6388 	if (result)
6389 	    --ret;
6390 	else if (interrupted != NULL && ret > 0)
6391 	    *interrupted = TRUE;
6392 
6393 # ifdef EINTR
6394 	if (ret == -1 && errno == EINTR)
6395 	{
6396 	    // Check whether window has been resized, EINTR may be caused by
6397 	    // SIGWINCH.
6398 	    if (do_resize)
6399 		handle_resize();
6400 
6401 	    // Interrupted by a signal, need to try again.  We ignore msec
6402 	    // here, because we do want to check even after a timeout if
6403 	    // characters are available.  Needed for reading output of an
6404 	    // external command after the process has finished.
6405 	    goto select_eintr;
6406 	}
6407 # endif
6408 # ifdef __TANDEM
6409 	if (ret == -1 && errno == ENOTSUP)
6410 	{
6411 	    FD_ZERO(&rfds);
6412 	    FD_ZERO(&efds);
6413 	    ret = 0;
6414 	}
6415 # endif
6416 # ifdef FEAT_MZSCHEME
6417 	if (ret == 0 && mzquantum_used)
6418 	    // loop if MzThreads must be scheduled and timeout occurred
6419 	    finished = FALSE;
6420 # endif
6421 
6422 # ifdef FEAT_XCLIPBOARD
6423 	if (ret > 0 && xterm_Shell != (Widget)0
6424 		&& FD_ISSET(ConnectionNumber(xterm_dpy), &rfds))
6425 	{
6426 	    xterm_update();	      // Maybe we should hand out clipboard
6427 	    // continue looping when we only got the X event and the input
6428 	    // buffer is empty
6429 	    if (--ret == 0 && !input_available())
6430 	    {
6431 		// Try again
6432 		finished = FALSE;
6433 	    }
6434 	}
6435 # endif
6436 # ifdef FEAT_MOUSE_GPM
6437 	if (ret > 0 && gpm_flag && check_for_gpm != NULL && gpm_fd >= 0)
6438 	{
6439 	    if (FD_ISSET(gpm_fd, &efds))
6440 		gpm_close();
6441 	    else if (FD_ISSET(gpm_fd, &rfds))
6442 		*check_for_gpm = 1;
6443 	}
6444 # endif
6445 # ifdef USE_XSMP
6446 	if (ret > 0 && xsmp_icefd != -1)
6447 	{
6448 	    if (FD_ISSET(xsmp_icefd, &efds))
6449 	    {
6450 		if (p_verbose > 0)
6451 		    verb_msg(_("XSMP lost ICE connection"));
6452 		xsmp_close();
6453 		if (--ret == 0)
6454 		    finished = FALSE;   // keep going if event was only one
6455 	    }
6456 	    else if (FD_ISSET(xsmp_icefd, &rfds))
6457 	    {
6458 		busy = TRUE;
6459 		xsmp_handle_requests();
6460 		busy = FALSE;
6461 		if (--ret == 0)
6462 		    finished = FALSE;   // keep going if event was only one
6463 	    }
6464 	}
6465 # endif
6466 #ifdef FEAT_JOB_CHANNEL
6467 	// also call when ret == 0, we may be polling a keep-open channel
6468 	if (ret >= 0)
6469 	    ret = channel_select_check(ret, &rfds, &wfds);
6470 #endif
6471 
6472 #endif // HAVE_SELECT
6473 
6474 #ifdef MAY_LOOP
6475 	if (finished || msec == 0)
6476 	    break;
6477 
6478 # ifdef FEAT_CLIENTSERVER
6479 	if (server_waiting())
6480 	    break;
6481 # endif
6482 
6483 	// We're going to loop around again, find out for how long
6484 	if (msec > 0)
6485 	{
6486 # ifdef ELAPSED_FUNC
6487 	    // Compute remaining wait time.
6488 	    msec = start_msec - ELAPSED_FUNC(start_tv);
6489 # else
6490 	    // Guess we got interrupted halfway.
6491 	    msec = msec / 2;
6492 # endif
6493 	    if (msec <= 0)
6494 		break;	// waited long enough
6495 	}
6496 #endif
6497     }
6498 
6499     return result;
6500 }
6501 
6502 /*
6503  * Expand a path into all matching files and/or directories.  Handles "*",
6504  * "?", "[a-z]", "**", etc.
6505  * "path" has backslashes before chars that are not to be expanded.
6506  * Returns the number of matches found.
6507  */
6508     int
mch_expandpath(garray_T * gap,char_u * path,int flags)6509 mch_expandpath(
6510     garray_T	*gap,
6511     char_u	*path,
6512     int		flags)		// EW_* flags
6513 {
6514     return unix_expandpath(gap, path, 0, flags, FALSE);
6515 }
6516 
6517 /*
6518  * mch_expand_wildcards() - this code does wild-card pattern matching using
6519  * the shell
6520  *
6521  * return OK for success, FAIL for error (you may lose some memory) and put
6522  * an error message in *file.
6523  *
6524  * num_pat is number of input patterns
6525  * pat is array of pointers to input patterns
6526  * num_file is pointer to number of matched file names
6527  * file is pointer to array of pointers to matched file names
6528  */
6529 
6530 #ifndef SEEK_SET
6531 # define SEEK_SET 0
6532 #endif
6533 #ifndef SEEK_END
6534 # define SEEK_END 2
6535 #endif
6536 
6537 #define SHELL_SPECIAL (char_u *)"\t \"&'$;<>()\\|"
6538 
6539     int
mch_expand_wildcards(int num_pat,char_u ** pat,int * num_file,char_u *** file,int flags)6540 mch_expand_wildcards(
6541     int		   num_pat,
6542     char_u	 **pat,
6543     int		  *num_file,
6544     char_u	***file,
6545     int		   flags)	// EW_* flags
6546 {
6547     int		i;
6548     size_t	len;
6549     long	llen;
6550     char_u	*p;
6551     int		dir;
6552 
6553     /*
6554      * This is the non-OS/2 implementation (really Unix).
6555      */
6556     int		j;
6557     char_u	*tempname;
6558     char_u	*command;
6559     FILE	*fd;
6560     char_u	*buffer;
6561 #define STYLE_ECHO	0	// use "echo", the default
6562 #define STYLE_GLOB	1	// use "glob", for csh
6563 #define STYLE_VIMGLOB	2	// use "vimglob", for Posix sh
6564 #define STYLE_PRINT	3	// use "print -N", for zsh
6565 #define STYLE_BT	4	// `cmd` expansion, execute the pattern
6566 				// directly
6567     int		shell_style = STYLE_ECHO;
6568     int		check_spaces;
6569     static int	did_find_nul = FALSE;
6570     int		ampersand = FALSE;
6571 		// vimglob() function to define for Posix shell
6572     static char *sh_vimglob_func = "vimglob() { while [ $# -ge 1 ]; do echo \"$1\"; shift; done }; vimglob >";
6573 
6574     *num_file = 0;	// default: no files found
6575     *file = NULL;
6576 
6577     /*
6578      * If there are no wildcards, just copy the names to allocated memory.
6579      * Saves a lot of time, because we don't have to start a new shell.
6580      */
6581     if (!have_wildcard(num_pat, pat))
6582 	return save_patterns(num_pat, pat, num_file, file);
6583 
6584 # ifdef HAVE_SANDBOX
6585     // Don't allow any shell command in the sandbox.
6586     if (sandbox != 0 && check_secure())
6587 	return FAIL;
6588 # endif
6589 
6590     /*
6591      * Don't allow the use of backticks in secure and restricted mode.
6592      */
6593     if (secure || restricted)
6594 	for (i = 0; i < num_pat; ++i)
6595 	    if (vim_strchr(pat[i], '`') != NULL
6596 		    && (check_restricted() || check_secure()))
6597 		return FAIL;
6598 
6599     /*
6600      * get a name for the temp file
6601      */
6602     if ((tempname = vim_tempname('o', FALSE)) == NULL)
6603     {
6604 	emsg(_(e_notmp));
6605 	return FAIL;
6606     }
6607 
6608     /*
6609      * Let the shell expand the patterns and write the result into the temp
6610      * file.
6611      * STYLE_BT:	NL separated
6612      *	    If expanding `cmd` execute it directly.
6613      * STYLE_GLOB:	NUL separated
6614      *	    If we use *csh, "glob" will work better than "echo".
6615      * STYLE_PRINT:	NL or NUL separated
6616      *	    If we use *zsh, "print -N" will work better than "glob".
6617      * STYLE_VIMGLOB:	NL separated
6618      *	    If we use *sh*, we define "vimglob()".
6619      * STYLE_ECHO:	space separated.
6620      *	    A shell we don't know, stay safe and use "echo".
6621      */
6622     if (num_pat == 1 && *pat[0] == '`'
6623 	    && (len = STRLEN(pat[0])) > 2
6624 	    && *(pat[0] + len - 1) == '`')
6625 	shell_style = STYLE_BT;
6626     else if ((len = STRLEN(p_sh)) >= 3)
6627     {
6628 	if (STRCMP(p_sh + len - 3, "csh") == 0)
6629 	    shell_style = STYLE_GLOB;
6630 	else if (STRCMP(p_sh + len - 3, "zsh") == 0)
6631 	    shell_style = STYLE_PRINT;
6632     }
6633     if (shell_style == STYLE_ECHO && strstr((char *)gettail(p_sh),
6634 								"sh") != NULL)
6635 	shell_style = STYLE_VIMGLOB;
6636 
6637     // Compute the length of the command.  We need 2 extra bytes: for the
6638     // optional '&' and for the NUL.
6639     // Worst case: "unset nonomatch; print -N >" plus two is 29
6640     len = STRLEN(tempname) + 29;
6641     if (shell_style == STYLE_VIMGLOB)
6642 	len += STRLEN(sh_vimglob_func);
6643 
6644     for (i = 0; i < num_pat; ++i)
6645     {
6646 	// Count the length of the patterns in the same way as they are put in
6647 	// "command" below.
6648 #ifdef USE_SYSTEM
6649 	len += STRLEN(pat[i]) + 3;	// add space and two quotes
6650 #else
6651 	++len;				// add space
6652 	for (j = 0; pat[i][j] != NUL; ++j)
6653 	{
6654 	    if (vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL)
6655 		++len;		// may add a backslash
6656 	    ++len;
6657 	}
6658 #endif
6659     }
6660     command = alloc(len);
6661     if (command == NULL)
6662     {
6663 	// out of memory
6664 	vim_free(tempname);
6665 	return FAIL;
6666     }
6667 
6668     /*
6669      * Build the shell command:
6670      * - Set $nonomatch depending on EW_NOTFOUND (hopefully the shell
6671      *	 recognizes this).
6672      * - Add the shell command to print the expanded names.
6673      * - Add the temp file name.
6674      * - Add the file name patterns.
6675      */
6676     if (shell_style == STYLE_BT)
6677     {
6678 	// change `command; command& ` to (command; command )
6679 	STRCPY(command, "(");
6680 	STRCAT(command, pat[0] + 1);		// exclude first backtick
6681 	p = command + STRLEN(command) - 1;
6682 	*p-- = ')';				// remove last backtick
6683 	while (p > command && VIM_ISWHITE(*p))
6684 	    --p;
6685 	if (*p == '&')				// remove trailing '&'
6686 	{
6687 	    ampersand = TRUE;
6688 	    *p = ' ';
6689 	}
6690 	STRCAT(command, ">");
6691     }
6692     else
6693     {
6694 	STRCPY(command, "");
6695 	if (shell_style == STYLE_GLOB)
6696 	{
6697 	    // Assume the nonomatch option is valid only for csh like shells,
6698 	    // otherwise, this may set the positional parameters for the shell,
6699 	    // e.g. "$*".
6700 	    if (flags & EW_NOTFOUND)
6701 		STRCAT(command, "set nonomatch; ");
6702 	    else
6703 		STRCAT(command, "unset nonomatch; ");
6704 	}
6705 	if (shell_style == STYLE_GLOB)
6706 	    STRCAT(command, "glob >");
6707 	else if (shell_style == STYLE_PRINT)
6708 	    STRCAT(command, "print -N >");
6709 	else if (shell_style == STYLE_VIMGLOB)
6710 	    STRCAT(command, sh_vimglob_func);
6711 	else
6712 	    STRCAT(command, "echo >");
6713     }
6714 
6715     STRCAT(command, tempname);
6716 
6717     if (shell_style != STYLE_BT)
6718 	for (i = 0; i < num_pat; ++i)
6719 	{
6720 	    // When using system() always add extra quotes, because the shell
6721 	    // is started twice.  Otherwise put a backslash before special
6722 	    // characters, except inside ``.
6723 #ifdef USE_SYSTEM
6724 	    STRCAT(command, " \"");
6725 	    STRCAT(command, pat[i]);
6726 	    STRCAT(command, "\"");
6727 #else
6728 	    int intick = FALSE;
6729 
6730 	    p = command + STRLEN(command);
6731 	    *p++ = ' ';
6732 	    for (j = 0; pat[i][j] != NUL; ++j)
6733 	    {
6734 		if (pat[i][j] == '`')
6735 		    intick = !intick;
6736 		else if (pat[i][j] == '\\' && pat[i][j + 1] != NUL)
6737 		{
6738 		    // Remove a backslash, take char literally.  But keep
6739 		    // backslash inside backticks, before a special character
6740 		    // and before a backtick.
6741 		    if (intick
6742 			  || vim_strchr(SHELL_SPECIAL, pat[i][j + 1]) != NULL
6743 			  || pat[i][j + 1] == '`')
6744 			*p++ = '\\';
6745 		    ++j;
6746 		}
6747 		else if (!intick
6748 			 && ((flags & EW_KEEPDOLLAR) == 0 || pat[i][j] != '$')
6749 			      && vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL)
6750 		    // Put a backslash before a special character, but not
6751 		    // when inside ``. And not for $var when EW_KEEPDOLLAR is
6752 		    // set.
6753 		    *p++ = '\\';
6754 
6755 		// Copy one character.
6756 		*p++ = pat[i][j];
6757 	    }
6758 	    *p = NUL;
6759 #endif
6760 	}
6761     if (flags & EW_SILENT)
6762 	show_shell_mess = FALSE;
6763     if (ampersand)
6764 	STRCAT(command, "&");		// put the '&' after the redirection
6765 
6766     /*
6767      * Using zsh -G: If a pattern has no matches, it is just deleted from
6768      * the argument list, otherwise zsh gives an error message and doesn't
6769      * expand any other pattern.
6770      */
6771     if (shell_style == STYLE_PRINT)
6772 	extra_shell_arg = (char_u *)"-G";   // Use zsh NULL_GLOB option
6773 
6774     /*
6775      * If we use -f then shell variables set in .cshrc won't get expanded.
6776      * vi can do it, so we will too, but it is only necessary if there is a "$"
6777      * in one of the patterns, otherwise we can still use the fast option.
6778      */
6779     else if (shell_style == STYLE_GLOB && !have_dollars(num_pat, pat))
6780 	extra_shell_arg = (char_u *)"-f";	// Use csh fast option
6781 
6782     /*
6783      * execute the shell command
6784      */
6785     i = call_shell(command, SHELL_EXPAND | SHELL_SILENT);
6786 
6787     // When running in the background, give it some time to create the temp
6788     // file, but don't wait for it to finish.
6789     if (ampersand)
6790 	mch_delay(10L, MCH_DELAY_IGNOREINPUT);
6791 
6792     extra_shell_arg = NULL;		// cleanup
6793     show_shell_mess = TRUE;
6794     vim_free(command);
6795 
6796     if (i != 0)				// mch_call_shell() failed
6797     {
6798 	mch_remove(tempname);
6799 	vim_free(tempname);
6800 	/*
6801 	 * With interactive completion, the error message is not printed.
6802 	 * However with USE_SYSTEM, I don't know how to turn off error messages
6803 	 * from the shell, so screen may still get messed up -- webb.
6804 	 */
6805 #ifndef USE_SYSTEM
6806 	if (!(flags & EW_SILENT))
6807 #endif
6808 	{
6809 	    redraw_later_clear();	// probably messed up screen
6810 	    msg_putchar('\n');		// clear bottom line quickly
6811 	    cmdline_row = Rows - 1;	// continue on last line
6812 #ifdef USE_SYSTEM
6813 	    if (!(flags & EW_SILENT))
6814 #endif
6815 	    {
6816 		msg(_(e_wildexpand));
6817 		msg_start();		// don't overwrite this message
6818 	    }
6819 	}
6820 	// If a `cmd` expansion failed, don't list `cmd` as a match, even when
6821 	// EW_NOTFOUND is given
6822 	if (shell_style == STYLE_BT)
6823 	    return FAIL;
6824 	goto notfound;
6825     }
6826 
6827     /*
6828      * read the names from the file into memory
6829      */
6830     fd = fopen((char *)tempname, READBIN);
6831     if (fd == NULL)
6832     {
6833 	// Something went wrong, perhaps a file name with a special char.
6834 	if (!(flags & EW_SILENT))
6835 	{
6836 	    msg(_(e_wildexpand));
6837 	    msg_start();		// don't overwrite this message
6838 	}
6839 	vim_free(tempname);
6840 	goto notfound;
6841     }
6842     fseek(fd, 0L, SEEK_END);
6843     llen = ftell(fd);			// get size of temp file
6844     fseek(fd, 0L, SEEK_SET);
6845     if (llen < 0)
6846 	// just in case ftell() would fail
6847 	buffer = NULL;
6848     else
6849 	buffer = alloc(llen + 1);
6850     if (buffer == NULL)
6851     {
6852 	// out of memory
6853 	mch_remove(tempname);
6854 	vim_free(tempname);
6855 	fclose(fd);
6856 	return FAIL;
6857     }
6858     len = llen;
6859     i = fread((char *)buffer, 1, len, fd);
6860     fclose(fd);
6861     mch_remove(tempname);
6862     if (i != (int)len)
6863     {
6864 	// unexpected read error
6865 	semsg(_(e_notread), tempname);
6866 	vim_free(tempname);
6867 	vim_free(buffer);
6868 	return FAIL;
6869     }
6870     vim_free(tempname);
6871 
6872 # ifdef __CYGWIN__
6873     // Translate <CR><NL> into <NL>.  Caution, buffer may contain NUL.
6874     p = buffer;
6875     for (i = 0; i < (int)len; ++i)
6876 	if (!(buffer[i] == CAR && buffer[i + 1] == NL))
6877 	    *p++ = buffer[i];
6878     len = p - buffer;
6879 # endif
6880 
6881 
6882     // file names are separated with Space
6883     if (shell_style == STYLE_ECHO)
6884     {
6885 	buffer[len] = '\n';		// make sure the buffer ends in NL
6886 	p = buffer;
6887 	for (i = 0; *p != '\n'; ++i)	// count number of entries
6888 	{
6889 	    while (*p != ' ' && *p != '\n')
6890 		++p;
6891 	    p = skipwhite(p);		// skip to next entry
6892 	}
6893     }
6894     // file names are separated with NL
6895     else if (shell_style == STYLE_BT || shell_style == STYLE_VIMGLOB)
6896     {
6897 	buffer[len] = NUL;		// make sure the buffer ends in NUL
6898 	p = buffer;
6899 	for (i = 0; *p != NUL; ++i)	// count number of entries
6900 	{
6901 	    while (*p != '\n' && *p != NUL)
6902 		++p;
6903 	    if (*p != NUL)
6904 		++p;
6905 	    p = skipwhite(p);		// skip leading white space
6906 	}
6907     }
6908     // file names are separated with NUL
6909     else
6910     {
6911 	/*
6912 	 * Some versions of zsh use spaces instead of NULs to separate
6913 	 * results.  Only do this when there is no NUL before the end of the
6914 	 * buffer, otherwise we would never be able to use file names with
6915 	 * embedded spaces when zsh does use NULs.
6916 	 * When we found a NUL once, we know zsh is OK, set did_find_nul and
6917 	 * don't check for spaces again.
6918 	 */
6919 	check_spaces = FALSE;
6920 	if (shell_style == STYLE_PRINT && !did_find_nul)
6921 	{
6922 	    // If there is a NUL, set did_find_nul, else set check_spaces
6923 	    buffer[len] = NUL;
6924 	    if (len && (int)STRLEN(buffer) < (int)len)
6925 		did_find_nul = TRUE;
6926 	    else
6927 		check_spaces = TRUE;
6928 	}
6929 
6930 	/*
6931 	 * Make sure the buffer ends with a NUL.  For STYLE_PRINT there
6932 	 * already is one, for STYLE_GLOB it needs to be added.
6933 	 */
6934 	if (len && buffer[len - 1] == NUL)
6935 	    --len;
6936 	else
6937 	    buffer[len] = NUL;
6938 	i = 0;
6939 	for (p = buffer; p < buffer + len; ++p)
6940 	    if (*p == NUL || (*p == ' ' && check_spaces))   // count entry
6941 	    {
6942 		++i;
6943 		*p = NUL;
6944 	    }
6945 	if (len)
6946 	    ++i;			// count last entry
6947     }
6948     if (i == 0)
6949     {
6950 	/*
6951 	 * Can happen when using /bin/sh and typing ":e $NO_SUCH_VAR^I".
6952 	 * /bin/sh will happily expand it to nothing rather than returning an
6953 	 * error; and hey, it's good to check anyway -- webb.
6954 	 */
6955 	vim_free(buffer);
6956 	goto notfound;
6957     }
6958     *num_file = i;
6959     *file = ALLOC_MULT(char_u *, i);
6960     if (*file == NULL)
6961     {
6962 	// out of memory
6963 	vim_free(buffer);
6964 	return FAIL;
6965     }
6966 
6967     /*
6968      * Isolate the individual file names.
6969      */
6970     p = buffer;
6971     for (i = 0; i < *num_file; ++i)
6972     {
6973 	(*file)[i] = p;
6974 	// Space or NL separates
6975 	if (shell_style == STYLE_ECHO || shell_style == STYLE_BT
6976 					      || shell_style == STYLE_VIMGLOB)
6977 	{
6978 	    while (!(shell_style == STYLE_ECHO && *p == ' ')
6979 						   && *p != '\n' && *p != NUL)
6980 		++p;
6981 	    if (p == buffer + len)		// last entry
6982 		*p = NUL;
6983 	    else
6984 	    {
6985 		*p++ = NUL;
6986 		p = skipwhite(p);		// skip to next entry
6987 	    }
6988 	}
6989 	else		// NUL separates
6990 	{
6991 	    while (*p && p < buffer + len)	// skip entry
6992 		++p;
6993 	    ++p;				// skip NUL
6994 	}
6995     }
6996 
6997     /*
6998      * Move the file names to allocated memory.
6999      */
7000     for (j = 0, i = 0; i < *num_file; ++i)
7001     {
7002 	// Require the files to exist.	Helps when using /bin/sh
7003 	if (!(flags & EW_NOTFOUND) && mch_getperm((*file)[i]) < 0)
7004 	    continue;
7005 
7006 	// check if this entry should be included
7007 	dir = (mch_isdir((*file)[i]));
7008 	if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
7009 	    continue;
7010 
7011 	// Skip files that are not executable if we check for that.
7012 	if (!dir && (flags & EW_EXEC)
7013 		    && !mch_can_exe((*file)[i], NULL, !(flags & EW_SHELLCMD)))
7014 	    continue;
7015 
7016 	p = alloc(STRLEN((*file)[i]) + 1 + dir);
7017 	if (p)
7018 	{
7019 	    STRCPY(p, (*file)[i]);
7020 	    if (dir)
7021 		add_pathsep(p);	    // add '/' to a directory name
7022 	    (*file)[j++] = p;
7023 	}
7024     }
7025     vim_free(buffer);
7026     *num_file = j;
7027 
7028     if (*num_file == 0)	    // rejected all entries
7029     {
7030 	VIM_CLEAR(*file);
7031 	goto notfound;
7032     }
7033 
7034     return OK;
7035 
7036 notfound:
7037     if (flags & EW_NOTFOUND)
7038 	return save_patterns(num_pat, pat, num_file, file);
7039     return FAIL;
7040 }
7041 
7042 #endif // VMS
7043 
7044     static int
save_patterns(int num_pat,char_u ** pat,int * num_file,char_u *** file)7045 save_patterns(
7046     int		num_pat,
7047     char_u	**pat,
7048     int		*num_file,
7049     char_u	***file)
7050 {
7051     int		i;
7052     char_u	*s;
7053 
7054     *file = ALLOC_MULT(char_u *, num_pat);
7055     if (*file == NULL)
7056 	return FAIL;
7057     for (i = 0; i < num_pat; i++)
7058     {
7059 	s = vim_strsave(pat[i]);
7060 	if (s != NULL)
7061 	    // Be compatible with expand_filename(): halve the number of
7062 	    // backslashes.
7063 	    backslash_halve(s);
7064 	(*file)[i] = s;
7065     }
7066     *num_file = num_pat;
7067     return OK;
7068 }
7069 
7070 /*
7071  * Return TRUE if the string "p" contains a wildcard that mch_expandpath() can
7072  * expand.
7073  */
7074     int
mch_has_exp_wildcard(char_u * p)7075 mch_has_exp_wildcard(char_u *p)
7076 {
7077     for ( ; *p; MB_PTR_ADV(p))
7078     {
7079 	if (*p == '\\' && p[1] != NUL)
7080 	    ++p;
7081 	else
7082 	    if (vim_strchr((char_u *)
7083 #ifdef VMS
7084 				    "*?%"
7085 #else
7086 				    "*?[{'"
7087 #endif
7088 						, *p) != NULL)
7089 	    return TRUE;
7090     }
7091     return FALSE;
7092 }
7093 
7094 /*
7095  * Return TRUE if the string "p" contains a wildcard.
7096  * Don't recognize '~' at the end as a wildcard.
7097  */
7098     int
mch_has_wildcard(char_u * p)7099 mch_has_wildcard(char_u *p)
7100 {
7101     for ( ; *p; MB_PTR_ADV(p))
7102     {
7103 	if (*p == '\\' && p[1] != NUL)
7104 	    ++p;
7105 	else
7106 	    if (vim_strchr((char_u *)
7107 #ifdef VMS
7108 				    "*?%$"
7109 #else
7110 				    "*?[{`'$"
7111 #endif
7112 						, *p) != NULL
7113 		|| (*p == '~' && p[1] != NUL))
7114 	    return TRUE;
7115     }
7116     return FALSE;
7117 }
7118 
7119     static int
have_wildcard(int num,char_u ** file)7120 have_wildcard(int num, char_u **file)
7121 {
7122     int	    i;
7123 
7124     for (i = 0; i < num; i++)
7125 	if (mch_has_wildcard(file[i]))
7126 	    return 1;
7127     return 0;
7128 }
7129 
7130     static int
have_dollars(int num,char_u ** file)7131 have_dollars(int num, char_u **file)
7132 {
7133     int	    i;
7134 
7135     for (i = 0; i < num; i++)
7136 	if (vim_strchr(file[i], '$') != NULL)
7137 	    return TRUE;
7138     return FALSE;
7139 }
7140 
7141 #if !defined(HAVE_RENAME) || defined(PROTO)
7142 /*
7143  * Scaled-down version of rename(), which is missing in Xenix.
7144  * This version can only move regular files and will fail if the
7145  * destination exists.
7146  */
7147     int
mch_rename(const char * src,const char * dest)7148 mch_rename(const char *src, const char *dest)
7149 {
7150     struct stat	    st;
7151 
7152     if (stat(dest, &st) >= 0)	    // fail if destination exists
7153 	return -1;
7154     if (link(src, dest) != 0)	    // link file to new name
7155 	return -1;
7156     if (mch_remove(src) == 0)	    // delete link to old name
7157 	return 0;
7158     return -1;
7159 }
7160 #endif // !HAVE_RENAME
7161 
7162 #if defined(FEAT_MOUSE_GPM) || defined(PROTO)
7163 /*
7164  * Initializes connection with gpm (if it isn't already opened)
7165  * Return 1 if succeeded (or connection already opened), 0 if failed
7166  */
7167     static int
gpm_open(void)7168 gpm_open(void)
7169 {
7170     static Gpm_Connect gpm_connect; // Must it be kept till closing ?
7171 
7172     if (!gpm_flag)
7173     {
7174 	gpm_connect.eventMask = (GPM_UP | GPM_DRAG | GPM_DOWN);
7175 	gpm_connect.defaultMask = ~GPM_HARD;
7176 	// Default handling for mouse move
7177 	gpm_connect.minMod = 0; // Handle any modifier keys
7178 	gpm_connect.maxMod = 0xffff;
7179 	if (Gpm_Open(&gpm_connect, 0) > 0)
7180 	{
7181 	    // gpm library tries to handling TSTP causes
7182 	    // problems. Anyways, we close connection to Gpm whenever
7183 	    // we are going to suspend or starting an external process
7184 	    // so we shouldn't  have problem with this
7185 # ifdef SIGTSTP
7186 	    signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
7187 # endif
7188 	    return 1; // succeed
7189 	}
7190 	if (gpm_fd == -2)
7191 	    Gpm_Close(); // We don't want to talk to xterm via gpm
7192 	return 0;
7193     }
7194     return 1; // already open
7195 }
7196 
7197 /*
7198  * Returns TRUE if the GPM mouse is enabled.
7199  */
7200     int
gpm_enabled(void)7201 gpm_enabled(void)
7202 {
7203     return gpm_flag && gpm_fd >= 0;
7204 }
7205 
7206 /*
7207  * Closes connection to gpm
7208  */
7209     static void
gpm_close(void)7210 gpm_close(void)
7211 {
7212     if (gpm_enabled())
7213 	Gpm_Close();
7214 }
7215 
7216 /*
7217  * Reads gpm event and adds special keys to input buf. Returns length of
7218  * generated key sequence.
7219  * This function is styled after gui_send_mouse_event().
7220  */
7221     static int
mch_gpm_process(void)7222 mch_gpm_process(void)
7223 {
7224     int			button;
7225     static Gpm_Event	gpm_event;
7226     char_u		string[6];
7227     int_u		vim_modifiers;
7228     int			row,col;
7229     unsigned char	buttons_mask;
7230     unsigned char	gpm_modifiers;
7231     static unsigned char old_buttons = 0;
7232 
7233     Gpm_GetEvent(&gpm_event);
7234 
7235 #ifdef FEAT_GUI
7236     // Don't put events in the input queue now.
7237     if (hold_gui_events)
7238 	return 0;
7239 #endif
7240 
7241     row = gpm_event.y - 1;
7242     col = gpm_event.x - 1;
7243 
7244     string[0] = ESC; // Our termcode
7245     string[1] = 'M';
7246     string[2] = 'G';
7247     switch (GPM_BARE_EVENTS(gpm_event.type))
7248     {
7249 	case GPM_DRAG:
7250 	    string[3] = MOUSE_DRAG;
7251 	    break;
7252 	case GPM_DOWN:
7253 	    buttons_mask = gpm_event.buttons & ~old_buttons;
7254 	    old_buttons = gpm_event.buttons;
7255 	    switch (buttons_mask)
7256 	    {
7257 		case GPM_B_LEFT:
7258 		    button = MOUSE_LEFT;
7259 		    break;
7260 		case GPM_B_MIDDLE:
7261 		    button = MOUSE_MIDDLE;
7262 		    break;
7263 		case GPM_B_RIGHT:
7264 		    button = MOUSE_RIGHT;
7265 		    break;
7266 		default:
7267 		    return 0;
7268 		    // Don't know what to do. Can more than one button be
7269 		    // reported in one event?
7270 	    }
7271 	    string[3] = (char_u)(button | 0x20);
7272 	    SET_NUM_MOUSE_CLICKS(string[3], gpm_event.clicks + 1);
7273 	    break;
7274 	case GPM_UP:
7275 	    string[3] = MOUSE_RELEASE;
7276 	    old_buttons &= ~gpm_event.buttons;
7277 	    break;
7278 	default:
7279 	    return 0;
7280     }
7281     // This code is based on gui_x11_mouse_cb in gui_x11.c
7282     gpm_modifiers = gpm_event.modifiers;
7283     vim_modifiers = 0x0;
7284     // I ignore capslock stats. Aren't we all just hate capslock mixing with
7285     // Vim commands ? Besides, gpm_event.modifiers is unsigned char, and
7286     // K_CAPSSHIFT is defined 8, so it probably isn't even reported
7287     if (gpm_modifiers & ((1 << KG_SHIFT) | (1 << KG_SHIFTR) | (1 << KG_SHIFTL)))
7288 	vim_modifiers |= MOUSE_SHIFT;
7289 
7290     if (gpm_modifiers & ((1 << KG_CTRL) | (1 << KG_CTRLR) | (1 << KG_CTRLL)))
7291 	vim_modifiers |= MOUSE_CTRL;
7292     if (gpm_modifiers & ((1 << KG_ALT) | (1 << KG_ALTGR)))
7293 	vim_modifiers |= MOUSE_ALT;
7294     string[3] |= vim_modifiers;
7295     string[4] = (char_u)(col + ' ' + 1);
7296     string[5] = (char_u)(row + ' ' + 1);
7297     add_to_input_buf(string, 6);
7298     return 6;
7299 }
7300 #endif // FEAT_MOUSE_GPM
7301 
7302 #ifdef FEAT_SYSMOUSE
7303 /*
7304  * Initialize connection with sysmouse.
7305  * Let virtual console inform us with SIGUSR2 for pending sysmouse
7306  * output, any sysmouse output than will be processed via sig_sysmouse().
7307  * Return OK if succeeded, FAIL if failed.
7308  */
7309     static int
sysmouse_open(void)7310 sysmouse_open(void)
7311 {
7312     struct mouse_info   mouse;
7313 
7314     mouse.operation = MOUSE_MODE;
7315     mouse.u.mode.mode = 0;
7316     mouse.u.mode.signal = SIGUSR2;
7317     if (ioctl(1, CONS_MOUSECTL, &mouse) != -1)
7318     {
7319 	signal(SIGUSR2, (RETSIGTYPE (*)())sig_sysmouse);
7320 	mouse.operation = MOUSE_SHOW;
7321 	ioctl(1, CONS_MOUSECTL, &mouse);
7322 	return OK;
7323     }
7324     return FAIL;
7325 }
7326 
7327 /*
7328  * Stop processing SIGUSR2 signals, and also make sure that
7329  * virtual console do not send us any sysmouse related signal.
7330  */
7331     static void
sysmouse_close(void)7332 sysmouse_close(void)
7333 {
7334     struct mouse_info	mouse;
7335 
7336     signal(SIGUSR2, restricted ? SIG_IGN : SIG_DFL);
7337     mouse.operation = MOUSE_MODE;
7338     mouse.u.mode.mode = 0;
7339     mouse.u.mode.signal = 0;
7340     ioctl(1, CONS_MOUSECTL, &mouse);
7341 }
7342 
7343 /*
7344  * Gets info from sysmouse and adds special keys to input buf.
7345  */
7346     static RETSIGTYPE
SIGDEFARG(sigarg)7347 sig_sysmouse SIGDEFARG(sigarg)
7348 {
7349     struct mouse_info	mouse;
7350     struct video_info	video;
7351     char_u		string[6];
7352     int			row, col;
7353     int			button;
7354     int			buttons;
7355     static int		oldbuttons = 0;
7356 
7357 #ifdef FEAT_GUI
7358     // Don't put events in the input queue now.
7359     if (hold_gui_events)
7360 	return;
7361 #endif
7362 
7363     mouse.operation = MOUSE_GETINFO;
7364     if (ioctl(1, FBIO_GETMODE, &video.vi_mode) != -1
7365 	    && ioctl(1, FBIO_MODEINFO, &video) != -1
7366 	    && ioctl(1, CONS_MOUSECTL, &mouse) != -1
7367 	    && video.vi_cheight > 0 && video.vi_cwidth > 0)
7368     {
7369 	row = mouse.u.data.y / video.vi_cheight;
7370 	col = mouse.u.data.x / video.vi_cwidth;
7371 	buttons = mouse.u.data.buttons;
7372 	string[0] = ESC; // Our termcode
7373 	string[1] = 'M';
7374 	string[2] = 'S';
7375 	if (oldbuttons == buttons && buttons != 0)
7376 	{
7377 	    button = MOUSE_DRAG;
7378 	}
7379 	else
7380 	{
7381 	    switch (buttons)
7382 	    {
7383 		case 0:
7384 		    button = MOUSE_RELEASE;
7385 		    break;
7386 		case 1:
7387 		    button = MOUSE_LEFT;
7388 		    break;
7389 		case 2:
7390 		    button = MOUSE_MIDDLE;
7391 		    break;
7392 		case 4:
7393 		    button = MOUSE_RIGHT;
7394 		    break;
7395 		default:
7396 		    return;
7397 	    }
7398 	    oldbuttons = buttons;
7399 	}
7400 	string[3] = (char_u)(button);
7401 	string[4] = (char_u)(col + ' ' + 1);
7402 	string[5] = (char_u)(row + ' ' + 1);
7403 	add_to_input_buf(string, 6);
7404     }
7405     return;
7406 }
7407 #endif // FEAT_SYSMOUSE
7408 
7409 #if defined(FEAT_LIBCALL) || defined(PROTO)
7410 typedef char_u * (*STRPROCSTR)(char_u *);
7411 typedef char_u * (*INTPROCSTR)(int);
7412 typedef int (*STRPROCINT)(char_u *);
7413 typedef int (*INTPROCINT)(int);
7414 
7415 /*
7416  * Call a DLL routine which takes either a string or int param
7417  * and returns an allocated string.
7418  */
7419     int
mch_libcall(char_u * libname,char_u * funcname,char_u * argstring,int argint,char_u ** string_result,int * number_result)7420 mch_libcall(
7421     char_u	*libname,
7422     char_u	*funcname,
7423     char_u	*argstring,	// NULL when using a argint
7424     int		argint,
7425     char_u	**string_result, // NULL when using number_result
7426     int		*number_result)
7427 {
7428 # if defined(USE_DLOPEN)
7429     void	*hinstLib;
7430     char	*dlerr = NULL;
7431 # else
7432     shl_t	hinstLib;
7433 # endif
7434     STRPROCSTR	ProcAdd;
7435     INTPROCSTR	ProcAddI;
7436     char_u	*retval_str = NULL;
7437     int		retval_int = 0;
7438     int		success = FALSE;
7439 
7440     /*
7441      * Get a handle to the DLL module.
7442      */
7443 # if defined(USE_DLOPEN)
7444     // First clear any error, it's not cleared by the dlopen() call.
7445     (void)dlerror();
7446 
7447     hinstLib = dlopen((char *)libname, RTLD_LAZY
7448 #  ifdef RTLD_LOCAL
7449 	    | RTLD_LOCAL
7450 #  endif
7451 	    );
7452     if (hinstLib == NULL)
7453     {
7454 	// "dlerr" must be used before dlclose()
7455 	dlerr = (char *)dlerror();
7456 	if (dlerr != NULL)
7457 	    semsg(_("dlerror = \"%s\""), dlerr);
7458     }
7459 # else
7460     hinstLib = shl_load((const char*)libname, BIND_IMMEDIATE|BIND_VERBOSE, 0L);
7461 # endif
7462 
7463     // If the handle is valid, try to get the function address.
7464     if (hinstLib != NULL)
7465     {
7466 # ifdef USING_SETJMP
7467 	/*
7468 	 * Catch a crash when calling the library function.  For example when
7469 	 * using a number where a string pointer is expected.
7470 	 */
7471 	mch_startjmp();
7472 	if (SETJMP(lc_jump_env) != 0)
7473 	{
7474 	    success = FALSE;
7475 #  if defined(USE_DLOPEN)
7476 	    dlerr = NULL;
7477 #  endif
7478 	    mch_didjmp();
7479 	}
7480 	else
7481 # endif
7482 	{
7483 	    retval_str = NULL;
7484 	    retval_int = 0;
7485 
7486 	    if (argstring != NULL)
7487 	    {
7488 # if defined(USE_DLOPEN)
7489 		*(void **)(&ProcAdd) = dlsym(hinstLib, (const char *)funcname);
7490 		dlerr = (char *)dlerror();
7491 # else
7492 		if (shl_findsym(&hinstLib, (const char *)funcname,
7493 					TYPE_PROCEDURE, (void *)&ProcAdd) < 0)
7494 		    ProcAdd = NULL;
7495 # endif
7496 		if ((success = (ProcAdd != NULL
7497 # if defined(USE_DLOPEN)
7498 			    && dlerr == NULL
7499 # endif
7500 			    )))
7501 		{
7502 		    if (string_result == NULL)
7503 			retval_int = ((STRPROCINT)(void *)ProcAdd)(argstring);
7504 		    else
7505 			retval_str = (ProcAdd)(argstring);
7506 		}
7507 	    }
7508 	    else
7509 	    {
7510 # if defined(USE_DLOPEN)
7511 		*(void **)(&ProcAddI) = dlsym(hinstLib, (const char *)funcname);
7512 		dlerr = (char *)dlerror();
7513 # else
7514 		if (shl_findsym(&hinstLib, (const char *)funcname,
7515 				       TYPE_PROCEDURE, (void *)&ProcAddI) < 0)
7516 		    ProcAddI = NULL;
7517 # endif
7518 		if ((success = (ProcAddI != NULL
7519 # if defined(USE_DLOPEN)
7520 			    && dlerr == NULL
7521 # endif
7522 			    )))
7523 		{
7524 		    if (string_result == NULL)
7525 			retval_int = ((INTPROCINT)(void *)ProcAddI)(argint);
7526 		    else
7527 			retval_str = (ProcAddI)(argint);
7528 		}
7529 	    }
7530 
7531 	    // Save the string before we free the library.
7532 	    // Assume that a "1" or "-1" result is an illegal pointer.
7533 	    if (string_result == NULL)
7534 		*number_result = retval_int;
7535 	    else if (retval_str != NULL
7536 		    && retval_str != (char_u *)1
7537 		    && retval_str != (char_u *)-1)
7538 		*string_result = vim_strsave(retval_str);
7539 	}
7540 
7541 # ifdef USING_SETJMP
7542 	mch_endjmp();
7543 #  ifdef SIGHASARG
7544 	if (lc_signal != 0)
7545 	{
7546 	    int i;
7547 
7548 	    // try to find the name of this signal
7549 	    for (i = 0; signal_info[i].sig != -1; i++)
7550 		if (lc_signal == signal_info[i].sig)
7551 		    break;
7552 	    semsg("E368: got SIG%s in libcall()", signal_info[i].name);
7553 	}
7554 #  endif
7555 # endif
7556 
7557 # if defined(USE_DLOPEN)
7558 	// "dlerr" must be used before dlclose()
7559 	if (dlerr != NULL)
7560 	    semsg(_("dlerror = \"%s\""), dlerr);
7561 
7562 	// Free the DLL module.
7563 	(void)dlclose(hinstLib);
7564 # else
7565 	(void)shl_unload(hinstLib);
7566 # endif
7567     }
7568 
7569     if (!success)
7570     {
7571 	semsg(_(e_libcall), funcname);
7572 	return FAIL;
7573     }
7574 
7575     return OK;
7576 }
7577 #endif
7578 
7579 #if (defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) || defined(PROTO)
7580 static int	xterm_trace = -1;	// default: disabled
7581 static int	xterm_button;
7582 
7583 /*
7584  * Setup a dummy window for X selections in a terminal.
7585  */
7586     void
setup_term_clip(void)7587 setup_term_clip(void)
7588 {
7589     int		z = 0;
7590     char	*strp = "";
7591     Widget	AppShell;
7592 
7593     if (!x_connect_to_server())
7594 	return;
7595 
7596     open_app_context();
7597     if (app_context != NULL && xterm_Shell == (Widget)0)
7598     {
7599 	int (*oldhandler)();
7600 # if defined(USING_SETJMP)
7601 	int (*oldIOhandler)();
7602 # endif
7603 # ifdef ELAPSED_FUNC
7604 	elapsed_T start_tv;
7605 
7606 	if (p_verbose > 0)
7607 	    ELAPSED_INIT(start_tv);
7608 # endif
7609 
7610 	// Ignore X errors while opening the display
7611 	oldhandler = XSetErrorHandler(x_error_check);
7612 
7613 # if defined(USING_SETJMP)
7614 	// Ignore X IO errors while opening the display
7615 	oldIOhandler = XSetIOErrorHandler(x_IOerror_check);
7616 	mch_startjmp();
7617 	if (SETJMP(lc_jump_env) != 0)
7618 	{
7619 	    mch_didjmp();
7620 	    xterm_dpy = NULL;
7621 	}
7622 	else
7623 # endif
7624 	{
7625 	    xterm_dpy = XtOpenDisplay(app_context, xterm_display,
7626 		    "vim_xterm", "Vim_xterm", NULL, 0, &z, &strp);
7627 	    if (xterm_dpy != NULL)
7628 		xterm_dpy_retry_count = 0;
7629 # if defined(USING_SETJMP)
7630 	    mch_endjmp();
7631 # endif
7632 	}
7633 
7634 # if defined(USING_SETJMP)
7635 	// Now handle X IO errors normally.
7636 	(void)XSetIOErrorHandler(oldIOhandler);
7637 # endif
7638 	// Now handle X errors normally.
7639 	(void)XSetErrorHandler(oldhandler);
7640 
7641 	if (xterm_dpy == NULL)
7642 	{
7643 	    if (p_verbose > 0)
7644 		verb_msg(_("Opening the X display failed"));
7645 	    return;
7646 	}
7647 
7648 	// Catch terminating error of the X server connection.
7649 	(void)XSetIOErrorHandler(x_IOerror_handler);
7650 
7651 # ifdef ELAPSED_FUNC
7652 	if (p_verbose > 0)
7653 	{
7654 	    verbose_enter();
7655 	    xopen_message(ELAPSED_FUNC(start_tv));
7656 	    verbose_leave();
7657 	}
7658 # endif
7659 
7660 	// Create a Shell to make converters work.
7661 	AppShell = XtVaAppCreateShell("vim_xterm", "Vim_xterm",
7662 		applicationShellWidgetClass, xterm_dpy,
7663 		NULL);
7664 	if (AppShell == (Widget)0)
7665 	    return;
7666 	xterm_Shell = XtVaCreatePopupShell("VIM",
7667 		topLevelShellWidgetClass, AppShell,
7668 		XtNmappedWhenManaged, 0,
7669 		XtNwidth, 1,
7670 		XtNheight, 1,
7671 		NULL);
7672 	if (xterm_Shell == (Widget)0)
7673 	    return;
7674 
7675 	x11_setup_atoms(xterm_dpy);
7676 	x11_setup_selection(xterm_Shell);
7677 	if (x11_display == NULL)
7678 	    x11_display = xterm_dpy;
7679 
7680 	XtRealizeWidget(xterm_Shell);
7681 	XSync(xterm_dpy, False);
7682 	xterm_update();
7683     }
7684     if (xterm_Shell != (Widget)0)
7685     {
7686 	clip_init(TRUE);
7687 	if (x11_window == 0 && (strp = getenv("WINDOWID")) != NULL)
7688 	    x11_window = (Window)atol(strp);
7689 	// Check if $WINDOWID is valid.
7690 	if (test_x11_window(xterm_dpy) == FAIL)
7691 	    x11_window = 0;
7692 	if (x11_window != 0)
7693 	    xterm_trace = 0;
7694     }
7695 }
7696 
7697     void
start_xterm_trace(int button)7698 start_xterm_trace(int button)
7699 {
7700     if (x11_window == 0 || xterm_trace < 0 || xterm_Shell == (Widget)0)
7701 	return;
7702     xterm_trace = 1;
7703     xterm_button = button;
7704     do_xterm_trace();
7705 }
7706 
7707 
7708     void
stop_xterm_trace(void)7709 stop_xterm_trace(void)
7710 {
7711     if (xterm_trace < 0)
7712 	return;
7713     xterm_trace = 0;
7714 }
7715 
7716 /*
7717  * Query the xterm pointer and generate mouse termcodes if necessary
7718  * return TRUE if dragging is active, else FALSE
7719  */
7720     static int
do_xterm_trace(void)7721 do_xterm_trace(void)
7722 {
7723     Window		root, child;
7724     int			root_x, root_y;
7725     int			win_x, win_y;
7726     int			row, col;
7727     int_u		mask_return;
7728     char_u		buf[50];
7729     char_u		*strp;
7730     long		got_hints;
7731     static char_u	*mouse_code;
7732     static char_u	mouse_name[2] = {KS_MOUSE, KE_FILLER};
7733     static int		prev_row = 0, prev_col = 0;
7734     static XSizeHints	xterm_hints;
7735 
7736     if (xterm_trace <= 0)
7737 	return FALSE;
7738 
7739     if (xterm_trace == 1)
7740     {
7741 	// Get the hints just before tracking starts.  The font size might
7742 	// have changed recently.
7743 	if (!XGetWMNormalHints(xterm_dpy, x11_window, &xterm_hints, &got_hints)
7744 		|| !(got_hints & PResizeInc)
7745 		|| xterm_hints.width_inc <= 1
7746 		|| xterm_hints.height_inc <= 1)
7747 	{
7748 	    xterm_trace = -1;  // Not enough data -- disable tracing
7749 	    return FALSE;
7750 	}
7751 
7752 	// Rely on the same mouse code for the duration of this
7753 	mouse_code = find_termcode(mouse_name);
7754 	prev_row = mouse_row;
7755 	prev_col = mouse_col;
7756 	xterm_trace = 2;
7757 
7758 	// Find the offset of the chars, there might be a scrollbar on the
7759 	// left of the window and/or a menu on the top (eterm etc.)
7760 	XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
7761 		      &win_x, &win_y, &mask_return);
7762 	xterm_hints.y = win_y - (xterm_hints.height_inc * mouse_row)
7763 			      - (xterm_hints.height_inc / 2);
7764 	if (xterm_hints.y <= xterm_hints.height_inc / 2)
7765 	    xterm_hints.y = 2;
7766 	xterm_hints.x = win_x - (xterm_hints.width_inc * mouse_col)
7767 			      - (xterm_hints.width_inc / 2);
7768 	if (xterm_hints.x <= xterm_hints.width_inc / 2)
7769 	    xterm_hints.x = 2;
7770 	return TRUE;
7771     }
7772     if (mouse_code == NULL || STRLEN(mouse_code) > 45)
7773     {
7774 	xterm_trace = 0;
7775 	return FALSE;
7776     }
7777 
7778     XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
7779 		  &win_x, &win_y, &mask_return);
7780 
7781     row = check_row((win_y - xterm_hints.y) / xterm_hints.height_inc);
7782     col = check_col((win_x - xterm_hints.x) / xterm_hints.width_inc);
7783     if (row == prev_row && col == prev_col)
7784 	return TRUE;
7785 
7786     STRCPY(buf, mouse_code);
7787     strp = buf + STRLEN(buf);
7788     *strp++ = (xterm_button | MOUSE_DRAG) & ~0x20;
7789     *strp++ = (char_u)(col + ' ' + 1);
7790     *strp++ = (char_u)(row + ' ' + 1);
7791     *strp = 0;
7792     add_to_input_buf(buf, STRLEN(buf));
7793 
7794     prev_row = row;
7795     prev_col = col;
7796     return TRUE;
7797 }
7798 
7799 # if defined(FEAT_GUI) || defined(FEAT_XCLIPBOARD) || defined(PROTO)
7800 /*
7801  * Destroy the display, window and app_context.  Required for GTK.
7802  */
7803     void
clear_xterm_clip(void)7804 clear_xterm_clip(void)
7805 {
7806     if (xterm_Shell != (Widget)0)
7807     {
7808 	XtDestroyWidget(xterm_Shell);
7809 	xterm_Shell = (Widget)0;
7810     }
7811     if (xterm_dpy != NULL)
7812     {
7813 #  if 0
7814 	// Lesstif and Solaris crash here, lose some memory
7815 	XtCloseDisplay(xterm_dpy);
7816 #  endif
7817 	if (x11_display == xterm_dpy)
7818 	    x11_display = NULL;
7819 	xterm_dpy = NULL;
7820     }
7821 #  if 0
7822     if (app_context != (XtAppContext)NULL)
7823     {
7824 	// Lesstif and Solaris crash here, lose some memory
7825 	XtDestroyApplicationContext(app_context);
7826 	app_context = (XtAppContext)NULL;
7827     }
7828 #  endif
7829 }
7830 # endif
7831 
7832 /*
7833  * Catch up with GUI or X events.
7834  */
7835     static void
clip_update(void)7836 clip_update(void)
7837 {
7838 # ifdef FEAT_GUI
7839     if (gui.in_use)
7840 	gui_mch_update();
7841     else
7842 # endif
7843     if (xterm_Shell != (Widget)0)
7844 	xterm_update();
7845 }
7846 
7847 /*
7848  * Catch up with any queued X events.  This may put keyboard input into the
7849  * input buffer, call resize call-backs, trigger timers etc.  If there is
7850  * nothing in the X event queue (& no timers pending), then we return
7851  * immediately.
7852  */
7853     static void
xterm_update(void)7854 xterm_update(void)
7855 {
7856     XEvent event;
7857 
7858     for (;;)
7859     {
7860 	XtInputMask mask = XtAppPending(app_context);
7861 
7862 	if (mask == 0 || vim_is_input_buf_full())
7863 	    break;
7864 
7865 	if (mask & XtIMXEvent)
7866 	{
7867 	    // There is an event to process.
7868 	    XtAppNextEvent(app_context, &event);
7869 #ifdef FEAT_CLIENTSERVER
7870 	    {
7871 		XPropertyEvent *e = (XPropertyEvent *)&event;
7872 
7873 		if (e->type == PropertyNotify && e->window == commWindow
7874 		   && e->atom == commProperty && e->state == PropertyNewValue)
7875 		    serverEventProc(xterm_dpy, &event, 0);
7876 	    }
7877 #endif
7878 	    XtDispatchEvent(&event);
7879 	}
7880 	else
7881 	{
7882 	    // There is something else than an event to process.
7883 	    XtAppProcessEvent(app_context, mask);
7884 	}
7885     }
7886 }
7887 
7888     int
clip_xterm_own_selection(Clipboard_T * cbd)7889 clip_xterm_own_selection(Clipboard_T *cbd)
7890 {
7891     if (xterm_Shell != (Widget)0)
7892 	return clip_x11_own_selection(xterm_Shell, cbd);
7893     return FAIL;
7894 }
7895 
7896     void
clip_xterm_lose_selection(Clipboard_T * cbd)7897 clip_xterm_lose_selection(Clipboard_T *cbd)
7898 {
7899     if (xterm_Shell != (Widget)0)
7900 	clip_x11_lose_selection(xterm_Shell, cbd);
7901 }
7902 
7903     void
clip_xterm_request_selection(Clipboard_T * cbd)7904 clip_xterm_request_selection(Clipboard_T *cbd)
7905 {
7906     if (xterm_Shell != (Widget)0)
7907 	clip_x11_request_selection(xterm_Shell, xterm_dpy, cbd);
7908 }
7909 
7910     void
clip_xterm_set_selection(Clipboard_T * cbd)7911 clip_xterm_set_selection(Clipboard_T *cbd)
7912 {
7913     clip_x11_set_selection(cbd);
7914 }
7915 #endif
7916 
7917 
7918 #if defined(USE_XSMP) || defined(PROTO)
7919 /*
7920  * Code for X Session Management Protocol.
7921  */
7922 
7923 # if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
7924 /*
7925  * This is our chance to ask the user if they want to save,
7926  * or abort the logout
7927  */
7928     static void
xsmp_handle_interaction(SmcConn smc_conn,SmPointer client_data UNUSED)7929 xsmp_handle_interaction(SmcConn smc_conn, SmPointer client_data UNUSED)
7930 {
7931     int		save_cmod_flags;
7932     int		cancel_shutdown = False;
7933 
7934     save_cmod_flags = cmdmod.cmod_flags;
7935     cmdmod.cmod_flags |= CMOD_CONFIRM;
7936     if (check_changed_any(FALSE, FALSE))
7937 	// Mustn't logout
7938 	cancel_shutdown = True;
7939     cmdmod.cmod_flags = save_cmod_flags;
7940     setcursor();		// position cursor
7941     out_flush();
7942 
7943     // Done interaction
7944     SmcInteractDone(smc_conn, cancel_shutdown);
7945 
7946     // Finish off
7947     // Only end save-yourself here if we're not cancelling shutdown;
7948     // we'll get a cancelled callback later in which we'll end it.
7949     // Hopefully get around glitchy SMs (like GNOME-1)
7950     if (!cancel_shutdown)
7951     {
7952 	xsmp.save_yourself = False;
7953 	SmcSaveYourselfDone(smc_conn, True);
7954     }
7955 }
7956 # endif
7957 
7958 /*
7959  * Callback that starts save-yourself.
7960  */
7961     static void
xsmp_handle_save_yourself(SmcConn smc_conn,SmPointer client_data UNUSED,int save_type UNUSED,Bool shutdown,int interact_style UNUSED,Bool fast UNUSED)7962 xsmp_handle_save_yourself(
7963     SmcConn	smc_conn,
7964     SmPointer	client_data UNUSED,
7965     int		save_type UNUSED,
7966     Bool	shutdown,
7967     int		interact_style UNUSED,
7968     Bool	fast UNUSED)
7969 {
7970     // Handle already being in saveyourself
7971     if (xsmp.save_yourself)
7972 	SmcSaveYourselfDone(smc_conn, True);
7973     xsmp.save_yourself = True;
7974     xsmp.shutdown = shutdown;
7975 
7976     // First up, preserve all files
7977     out_flush();
7978     ml_sync_all(FALSE, FALSE);	// preserve all swap files
7979 
7980     if (p_verbose > 0)
7981 	verb_msg(_("XSMP handling save-yourself request"));
7982 
7983 # if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
7984     // Now see if we can ask about unsaved files
7985     if (shutdown && !fast && gui.in_use)
7986 	// Need to interact with user, but need SM's permission
7987 	SmcInteractRequest(smc_conn, SmDialogError,
7988 					xsmp_handle_interaction, client_data);
7989     else
7990 # endif
7991     {
7992 	// Can stop the cycle here
7993 	SmcSaveYourselfDone(smc_conn, True);
7994 	xsmp.save_yourself = False;
7995     }
7996 }
7997 
7998 
7999 /*
8000  * Callback to warn us of imminent death.
8001  */
8002     static void
xsmp_die(SmcConn smc_conn UNUSED,SmPointer client_data UNUSED)8003 xsmp_die(SmcConn smc_conn UNUSED, SmPointer client_data UNUSED)
8004 {
8005     xsmp_close();
8006 
8007     // quit quickly leaving swapfiles for modified buffers behind
8008     getout_preserve_modified(0);
8009 }
8010 
8011 
8012 /*
8013  * Callback to tell us that save-yourself has completed.
8014  */
8015     static void
xsmp_save_complete(SmcConn smc_conn UNUSED,SmPointer client_data UNUSED)8016 xsmp_save_complete(
8017     SmcConn	smc_conn UNUSED,
8018     SmPointer	client_data UNUSED)
8019 {
8020     xsmp.save_yourself = False;
8021 }
8022 
8023 
8024 /*
8025  * Callback to tell us that an instigated shutdown was cancelled
8026  * (maybe even by us)
8027  */
8028     static void
xsmp_shutdown_cancelled(SmcConn smc_conn,SmPointer client_data UNUSED)8029 xsmp_shutdown_cancelled(
8030     SmcConn	smc_conn,
8031     SmPointer	client_data UNUSED)
8032 {
8033     if (xsmp.save_yourself)
8034 	SmcSaveYourselfDone(smc_conn, True);
8035     xsmp.save_yourself = False;
8036     xsmp.shutdown = False;
8037 }
8038 
8039 
8040 /*
8041  * Callback to tell us that a new ICE connection has been established.
8042  */
8043     static void
xsmp_ice_connection(IceConn iceConn,IcePointer clientData UNUSED,Bool opening,IcePointer * watchData UNUSED)8044 xsmp_ice_connection(
8045     IceConn	iceConn,
8046     IcePointer	clientData UNUSED,
8047     Bool	opening,
8048     IcePointer	*watchData UNUSED)
8049 {
8050     // Intercept creation of ICE connection fd
8051     if (opening)
8052     {
8053 	xsmp_icefd = IceConnectionNumber(iceConn);
8054 	IceRemoveConnectionWatch(xsmp_ice_connection, NULL);
8055     }
8056 }
8057 
8058 
8059 // Handle any ICE processing that's required; return FAIL if SM lost
8060     int
xsmp_handle_requests(void)8061 xsmp_handle_requests(void)
8062 {
8063     Bool rep;
8064 
8065     if (IceProcessMessages(xsmp.iceconn, NULL, &rep)
8066 						 == IceProcessMessagesIOError)
8067     {
8068 	// Lost ICE
8069 	if (p_verbose > 0)
8070 	    verb_msg(_("XSMP lost ICE connection"));
8071 	xsmp_close();
8072 	return FAIL;
8073     }
8074     else
8075 	return OK;
8076 }
8077 
8078 static int dummy;
8079 
8080 // Set up X Session Management Protocol
8081     void
xsmp_init(void)8082 xsmp_init(void)
8083 {
8084     char		errorstring[80];
8085     SmcCallbacks	smcallbacks;
8086 #if 0
8087     SmPropValue		smname;
8088     SmProp		smnameprop;
8089     SmProp		*smprops[1];
8090 #endif
8091 
8092     if (p_verbose > 0)
8093 	verb_msg(_("XSMP opening connection"));
8094 
8095     xsmp.save_yourself = xsmp.shutdown = False;
8096 
8097     // Set up SM callbacks - must have all, even if they're not used
8098     smcallbacks.save_yourself.callback = xsmp_handle_save_yourself;
8099     smcallbacks.save_yourself.client_data = NULL;
8100     smcallbacks.die.callback = xsmp_die;
8101     smcallbacks.die.client_data = NULL;
8102     smcallbacks.save_complete.callback = xsmp_save_complete;
8103     smcallbacks.save_complete.client_data = NULL;
8104     smcallbacks.shutdown_cancelled.callback = xsmp_shutdown_cancelled;
8105     smcallbacks.shutdown_cancelled.client_data = NULL;
8106 
8107     // Set up a watch on ICE connection creations.  The "dummy" argument is
8108     // apparently required for FreeBSD (we get a BUS error when using NULL).
8109     if (IceAddConnectionWatch(xsmp_ice_connection, &dummy) == 0)
8110     {
8111 	if (p_verbose > 0)
8112 	    verb_msg(_("XSMP ICE connection watch failed"));
8113 	return;
8114     }
8115 
8116     // Create an SM connection
8117     xsmp.smcconn = SmcOpenConnection(
8118 	    NULL,
8119 	    NULL,
8120 	    SmProtoMajor,
8121 	    SmProtoMinor,
8122 	    SmcSaveYourselfProcMask | SmcDieProcMask
8123 		     | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask,
8124 	    &smcallbacks,
8125 	    NULL,
8126 	    &xsmp.clientid,
8127 	    sizeof(errorstring) - 1,
8128 	    errorstring);
8129     if (xsmp.smcconn == NULL)
8130     {
8131 	if (p_verbose > 0)
8132 	{
8133 	    char errorreport[132];
8134 
8135 	    // If the message is too long it might not be NUL terminated.  Add
8136 	    // a NUL at the end to make sure we don't go over the end.
8137 	    errorstring[sizeof(errorstring) - 1] = NUL;
8138 	    vim_snprintf(errorreport, sizeof(errorreport),
8139 			 _("XSMP SmcOpenConnection failed: %s"), errorstring);
8140 	    verb_msg(errorreport);
8141 	}
8142 	return;
8143     }
8144     xsmp.iceconn = SmcGetIceConnection(xsmp.smcconn);
8145 
8146 #if 0
8147     // ID ourselves
8148     smname.value = "vim";
8149     smname.length = 3;
8150     smnameprop.name = "SmProgram";
8151     smnameprop.type = "SmARRAY8";
8152     smnameprop.num_vals = 1;
8153     smnameprop.vals = &smname;
8154 
8155     smprops[0] = &smnameprop;
8156     SmcSetProperties(xsmp.smcconn, 1, smprops);
8157 #endif
8158 }
8159 
8160 
8161 // Shut down XSMP comms.
8162     void
xsmp_close(void)8163 xsmp_close(void)
8164 {
8165     if (xsmp_icefd != -1)
8166     {
8167 	SmcCloseConnection(xsmp.smcconn, 0, NULL);
8168 	if (xsmp.clientid != NULL)
8169 	    free(xsmp.clientid);
8170 	xsmp.clientid = NULL;
8171 	xsmp_icefd = -1;
8172     }
8173 }
8174 #endif // USE_XSMP
8175 
8176 
8177 #ifdef EBCDIC
8178 // Translate character to its CTRL- value
8179 char CtrlTable[] =
8180 {
8181 /* 00 - 5E */
8182 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8183 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8184 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8185 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8186 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8187 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8188 /* ^ */ 0x1E,
8189 /* - */ 0x1F,
8190 /* 61 - 6C */
8191 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8192 /* _ */ 0x1F,
8193 /* 6E - 80 */
8194 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8195 /* a */ 0x01,
8196 /* b */ 0x02,
8197 /* c */ 0x03,
8198 /* d */ 0x37,
8199 /* e */ 0x2D,
8200 /* f */ 0x2E,
8201 /* g */ 0x2F,
8202 /* h */ 0x16,
8203 /* i */ 0x05,
8204 /* 8A - 90 */
8205 	0, 0, 0, 0, 0, 0, 0,
8206 /* j */ 0x15,
8207 /* k */ 0x0B,
8208 /* l */ 0x0C,
8209 /* m */ 0x0D,
8210 /* n */ 0x0E,
8211 /* o */ 0x0F,
8212 /* p */ 0x10,
8213 /* q */ 0x11,
8214 /* r */ 0x12,
8215 /* 9A - A1 */
8216 	0, 0, 0, 0, 0, 0, 0, 0,
8217 /* s */ 0x13,
8218 /* t */ 0x3C,
8219 /* u */ 0x3D,
8220 /* v */ 0x32,
8221 /* w */ 0x26,
8222 /* x */ 0x18,
8223 /* y */ 0x19,
8224 /* z */ 0x3F,
8225 /* AA - AC */
8226 	0, 0, 0,
8227 /* [ */ 0x27,
8228 /* AE - BC */
8229 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8230 /* ] */ 0x1D,
8231 /* BE - C0 */ 0, 0, 0,
8232 /* A */ 0x01,
8233 /* B */ 0x02,
8234 /* C */ 0x03,
8235 /* D */ 0x37,
8236 /* E */ 0x2D,
8237 /* F */ 0x2E,
8238 /* G */ 0x2F,
8239 /* H */ 0x16,
8240 /* I */ 0x05,
8241 /* CA - D0 */ 0, 0, 0, 0, 0, 0, 0,
8242 /* J */ 0x15,
8243 /* K */ 0x0B,
8244 /* L */ 0x0C,
8245 /* M */ 0x0D,
8246 /* N */ 0x0E,
8247 /* O */ 0x0F,
8248 /* P */ 0x10,
8249 /* Q */ 0x11,
8250 /* R */ 0x12,
8251 /* DA - DF */ 0, 0, 0, 0, 0, 0,
8252 /* \ */ 0x1C,
8253 /* E1 */ 0,
8254 /* S */ 0x13,
8255 /* T */ 0x3C,
8256 /* U */ 0x3D,
8257 /* V */ 0x32,
8258 /* W */ 0x26,
8259 /* X */ 0x18,
8260 /* Y */ 0x19,
8261 /* Z */ 0x3F,
8262 /* EA - FF*/ 0, 0, 0, 0, 0, 0,
8263 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8264 };
8265 
8266 char MetaCharTable[]=
8267 {//   0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
8268       0,  0,  0,  0,'\\', 0,'F',  0,'W','M','N',  0,  0,  0,  0,  0,
8269       0,  0,  0,  0,']',  0,  0,'G',  0,  0,'R','O',  0,  0,  0,  0,
8270     '@','A','B','C','D','E',  0,  0,'H','I','J','K','L',  0,  0,  0,
8271     'P','Q',  0,'S','T','U','V',  0,'X','Y','Z','[',  0,  0,'^',  0
8272 };
8273 
8274 
8275 // TODO: Use characters NOT numbers!!!
8276 char CtrlCharTable[]=
8277 {//   0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
8278     124,193,194,195,  0,201,  0,  0,  0,  0,  0,210,211,212,213,214,
8279     215,216,217,226,  0,209,200,  0,231,232,  0,  0,224,189, 95,109,
8280       0,  0,  0,  0,  0,  0,230,173,  0,  0,  0,  0,  0,197,198,199,
8281       0,  0,229,  0,  0,  0,  0,196,  0,  0,  0,  0,227,228,  0,233,
8282 };
8283 
8284 
8285 #endif
8286