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