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