blob: 314a906d6135d0e5ca5e0babbd644e1edb73f6a4 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* 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 */
Bram Moolenaar311d9822007-02-27 15:48:28 +000028#if !defined(__APPLE__) && !defined(__TANDEM)
Bram Moolenaar071d4272004-06-13 20:20:40 +000029# define select select_declared_wrong
30#endif
31
32#include "vim.h"
33
Bram Moolenaar325b7a22004-07-05 15:58:32 +000034#ifdef FEAT_MZSCHEME
35# include "if_mzsch.h"
36#endif
37
Bram Moolenaar071d4272004-06-13 20:20:40 +000038#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
Bram Moolenaar588ebeb2008-05-07 17:09:24 +000044#ifdef HAVE_SELINUX
45# include <selinux/selinux.h>
46static int selinux_enabled = -1;
47#endif
48
Bram Moolenaar5bd32f42014-04-02 14:05:38 +020049#ifdef HAVE_SMACK
50# include <attr/xattr.h>
51# include <linux/xattr.h>
52# ifndef SMACK_LABEL_LEN
53# define SMACK_LABEL_LEN 1024
54# endif
55#endif
56
Bram Moolenaar071d4272004-06-13 20:20:40 +000057/*
58 * Use this prototype for select, some include files have a wrong prototype
59 */
Bram Moolenaar311d9822007-02-27 15:48:28 +000060#ifndef __TANDEM
61# undef select
62# ifdef __BEOS__
63# define select beos_select
64# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000065#endif
66
Bram Moolenaara2442432007-04-26 14:26:37 +000067#ifdef __CYGWIN__
68# ifndef WIN32
Bram Moolenaar0d1498e2008-06-29 12:00:49 +000069# include <cygwin/version.h>
70# include <sys/cygwin.h> /* for cygwin_conv_to_posix_path() and/or
71 * for cygwin_conv_path() */
Bram Moolenaar693e40c2013-02-26 14:56:42 +010072# ifdef FEAT_CYGWIN_WIN32_CLIPBOARD
73# define WIN32_LEAN_AND_MEAN
74# include <windows.h>
75# include "winclip.pro"
76# endif
Bram Moolenaara2442432007-04-26 14:26:37 +000077# endif
78#endif
79
Bram Moolenaar071d4272004-06-13 20:20:40 +000080#if defined(HAVE_SELECT)
81extern int select __ARGS((int, fd_set *, fd_set *, fd_set *, struct timeval *));
82#endif
83
84#ifdef FEAT_MOUSE_GPM
85# include <gpm.h>
86/* <linux/keyboard.h> contains defines conflicting with "keymap.h",
87 * I just copied relevant defines here. A cleaner solution would be to put gpm
88 * code into separate file and include there linux/keyboard.h
89 */
90/* #include <linux/keyboard.h> */
91# define KG_SHIFT 0
92# define KG_CTRL 2
93# define KG_ALT 3
94# define KG_ALTGR 1
95# define KG_SHIFTL 4
96# define KG_SHIFTR 5
97# define KG_CTRLL 6
98# define KG_CTRLR 7
99# define KG_CAPSSHIFT 8
100
101static void gpm_close __ARGS((void));
102static int gpm_open __ARGS((void));
103static int mch_gpm_process __ARGS((void));
104#endif
105
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000106#ifdef FEAT_SYSMOUSE
107# include <sys/consio.h>
108# include <sys/fbio.h>
109
110static int sysmouse_open __ARGS((void));
111static void sysmouse_close __ARGS((void));
112static RETSIGTYPE sig_sysmouse __ARGS(SIGPROTOARG);
113#endif
114
Bram Moolenaar071d4272004-06-13 20:20:40 +0000115/*
116 * end of autoconf section. To be extended...
117 */
118
119/* Are the following #ifdefs still required? And why? Is that for X11? */
120
121#if defined(ESIX) || defined(M_UNIX) && !defined(SCO)
122# ifdef SIGWINCH
123# undef SIGWINCH
124# endif
125# ifdef TIOCGWINSZ
126# undef TIOCGWINSZ
127# endif
128#endif
129
130#if defined(SIGWINDOW) && !defined(SIGWINCH) /* hpux 9.01 has it */
131# define SIGWINCH SIGWINDOW
132#endif
133
134#ifdef FEAT_X11
135# include <X11/Xlib.h>
136# include <X11/Xutil.h>
137# include <X11/Xatom.h>
138# ifdef FEAT_XCLIPBOARD
139# include <X11/Intrinsic.h>
140# include <X11/Shell.h>
141# include <X11/StringDefs.h>
142static Widget xterm_Shell = (Widget)0;
Bram Moolenaar090cfc12013-03-19 12:35:42 +0100143static void clip_update __ARGS((void));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000144static void xterm_update __ARGS((void));
145# endif
146
147# if defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE)
148Window x11_window = 0;
149# endif
150Display *x11_display = NULL;
151
152# ifdef FEAT_TITLE
153static int get_x11_windis __ARGS((void));
154static void set_x11_title __ARGS((char_u *));
155static void set_x11_icon __ARGS((char_u *));
156# endif
157#endif
158
159#ifdef FEAT_TITLE
160static int get_x11_title __ARGS((int));
161static int get_x11_icon __ARGS((int));
162
163static char_u *oldtitle = NULL;
164static int did_set_title = FALSE;
165static char_u *oldicon = NULL;
166static int did_set_icon = FALSE;
167#endif
168
169static void may_core_dump __ARGS((void));
170
Bram Moolenaar205b8862011-09-07 15:04:31 +0200171#ifdef HAVE_UNION_WAIT
172typedef union wait waitstatus;
173#else
174typedef int waitstatus;
175#endif
Bram Moolenaar9f118812011-09-08 23:24:14 +0200176static pid_t wait4pid __ARGS((pid_t, waitstatus *));
Bram Moolenaar205b8862011-09-07 15:04:31 +0200177
Bram Moolenaar071d4272004-06-13 20:20:40 +0000178static int WaitForChar __ARGS((long));
Bram Moolenaar4ffa0702013-12-11 17:12:37 +0100179#if defined(__BEOS__) || defined(VMS)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000180int RealWaitForChar __ARGS((int, long, int *));
181#else
182static int RealWaitForChar __ARGS((int, long, int *));
183#endif
184
185#ifdef FEAT_XCLIPBOARD
186static int do_xterm_trace __ARGS((void));
Bram Moolenaarcf851ce2005-06-16 21:52:47 +0000187# define XT_TRACE_DELAY 50 /* delay for xterm tracing */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000188#endif
189
190static void handle_resize __ARGS((void));
191
192#if defined(SIGWINCH)
193static RETSIGTYPE sig_winch __ARGS(SIGPROTOARG);
194#endif
195#if defined(SIGINT)
196static RETSIGTYPE catch_sigint __ARGS(SIGPROTOARG);
197#endif
198#if defined(SIGPWR)
199static RETSIGTYPE catch_sigpwr __ARGS(SIGPROTOARG);
200#endif
201#if defined(SIGALRM) && defined(FEAT_X11) \
202 && defined(FEAT_TITLE) && !defined(FEAT_GUI_GTK)
203# define SET_SIG_ALARM
204static RETSIGTYPE sig_alarm __ARGS(SIGPROTOARG);
Bram Moolenaar76243bd2009-03-02 01:47:02 +0000205/* volatile because it is used in signal handler sig_alarm(). */
206static volatile int sig_alarm_called;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000207#endif
208static RETSIGTYPE deathtrap __ARGS(SIGPROTOARG);
209
Bram Moolenaardf177f62005-02-22 08:39:57 +0000210static void catch_int_signal __ARGS((void));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000211static void set_signals __ARGS((void));
212static void catch_signals __ARGS((RETSIGTYPE (*func_deadly)(), RETSIGTYPE (*func_other)()));
213#ifndef __EMX__
214static int have_wildcard __ARGS((int, char_u **));
215static int have_dollars __ARGS((int, char_u **));
216#endif
217
Bram Moolenaar071d4272004-06-13 20:20:40 +0000218#ifndef __EMX__
219static int save_patterns __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file));
220#endif
221
222#ifndef SIG_ERR
Bram Moolenaar8f0b2d42009-05-16 14:41:10 +0000223# define SIG_ERR ((RETSIGTYPE (*)())-1)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000224#endif
225
Bram Moolenaar76243bd2009-03-02 01:47:02 +0000226/* volatile because it is used in signal handler sig_winch(). */
227static volatile int do_resize = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000228#ifndef __EMX__
229static char_u *extra_shell_arg = NULL;
230static int show_shell_mess = TRUE;
231#endif
Bram Moolenaar76243bd2009-03-02 01:47:02 +0000232/* volatile because it is used in signal handler deathtrap(). */
233static volatile int deadly_signal = 0; /* The signal we caught */
234/* volatile because it is used in signal handler deathtrap(). */
235static volatile int in_mch_delay = FALSE; /* sleeping in mch_delay() */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000236
237static int curr_tmode = TMODE_COOK; /* contains current terminal mode */
238
239#ifdef USE_XSMP
240typedef struct
241{
242 SmcConn smcconn; /* The SM connection ID */
243 IceConn iceconn; /* The ICE connection ID */
Bram Moolenaar67c53842010-05-22 18:28:27 +0200244 char *clientid; /* The client ID for the current smc session */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000245 Bool save_yourself; /* If we're in the middle of a save_yourself */
246 Bool shutdown; /* If we're in shutdown mode */
247} xsmp_config_T;
248
249static xsmp_config_T xsmp;
250#endif
251
252#ifdef SYS_SIGLIST_DECLARED
253/*
254 * I have seen
255 * extern char *_sys_siglist[NSIG];
256 * on Irix, Linux, NetBSD and Solaris. It contains a nice list of strings
257 * that describe the signals. That is nearly what we want here. But
258 * autoconf does only check for sys_siglist (without the underscore), I
259 * do not want to change everything today.... jw.
260 * This is why AC_DECL_SYS_SIGLIST is commented out in configure.in
261 */
262#endif
263
264static struct signalinfo
265{
266 int sig; /* Signal number, eg. SIGSEGV etc */
267 char *name; /* Signal name (not char_u!). */
268 char deadly; /* Catch as a deadly signal? */
269} signal_info[] =
270{
271#ifdef SIGHUP
272 {SIGHUP, "HUP", TRUE},
273#endif
274#ifdef SIGQUIT
275 {SIGQUIT, "QUIT", TRUE},
276#endif
277#ifdef SIGILL
278 {SIGILL, "ILL", TRUE},
279#endif
280#ifdef SIGTRAP
281 {SIGTRAP, "TRAP", TRUE},
282#endif
283#ifdef SIGABRT
284 {SIGABRT, "ABRT", TRUE},
285#endif
286#ifdef SIGEMT
287 {SIGEMT, "EMT", TRUE},
288#endif
289#ifdef SIGFPE
290 {SIGFPE, "FPE", TRUE},
291#endif
292#ifdef SIGBUS
293 {SIGBUS, "BUS", TRUE},
294#endif
Bram Moolenaar75676462013-01-30 14:55:42 +0100295#if defined(SIGSEGV) && !defined(FEAT_MZSCHEME)
296 /* MzScheme uses SEGV in its garbage collector */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000297 {SIGSEGV, "SEGV", TRUE},
298#endif
299#ifdef SIGSYS
300 {SIGSYS, "SYS", TRUE},
301#endif
302#ifdef SIGALRM
303 {SIGALRM, "ALRM", FALSE}, /* Perl's alarm() can trigger it */
304#endif
305#ifdef SIGTERM
306 {SIGTERM, "TERM", TRUE},
307#endif
Bram Moolenaarb292a2a2011-02-09 18:47:40 +0100308#if defined(SIGVTALRM) && !defined(FEAT_RUBY)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000309 {SIGVTALRM, "VTALRM", TRUE},
310#endif
Bram Moolenaar02f07e02008-03-12 12:17:28 +0000311#if defined(SIGPROF) && !defined(FEAT_MZSCHEME) && !defined(WE_ARE_PROFILING)
312 /* MzScheme uses SIGPROF for its own needs; On Linux with profiling
313 * this makes Vim exit. WE_ARE_PROFILING is defined in Makefile. */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000314 {SIGPROF, "PROF", TRUE},
315#endif
316#ifdef SIGXCPU
317 {SIGXCPU, "XCPU", TRUE},
318#endif
319#ifdef SIGXFSZ
320 {SIGXFSZ, "XFSZ", TRUE},
321#endif
322#ifdef SIGUSR1
323 {SIGUSR1, "USR1", TRUE},
324#endif
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000325#if defined(SIGUSR2) && !defined(FEAT_SYSMOUSE)
326 /* Used for sysmouse handling */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000327 {SIGUSR2, "USR2", TRUE},
328#endif
329#ifdef SIGINT
330 {SIGINT, "INT", FALSE},
331#endif
332#ifdef SIGWINCH
333 {SIGWINCH, "WINCH", FALSE},
334#endif
335#ifdef SIGTSTP
336 {SIGTSTP, "TSTP", FALSE},
337#endif
338#ifdef SIGPIPE
339 {SIGPIPE, "PIPE", FALSE},
340#endif
341 {-1, "Unknown!", FALSE}
342};
343
Bram Moolenaar25724922009-07-14 15:38:41 +0000344 int
345mch_chdir(path)
346 char *path;
347{
348 if (p_verbose >= 5)
349 {
350 verbose_enter();
351 smsg((char_u *)"chdir(%s)", path);
352 verbose_leave();
353 }
354# ifdef VMS
355 return chdir(vms_fixfilename(path));
356# else
357 return chdir(path);
358# endif
359}
360
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +0000361/*
362 * Write s[len] to the screen.
363 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000364 void
365mch_write(s, len)
366 char_u *s;
367 int len;
368{
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +0000369 ignored = (int)write(1, (char *)s, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000370 if (p_wd) /* Unix is too fast, slow down a bit more */
371 RealWaitForChar(read_cmd_fd, p_wd, NULL);
372}
373
374/*
Bram Moolenaarc2a27c32007-12-01 16:19:33 +0000375 * mch_inchar(): low level input function.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000376 * Get a characters from the keyboard.
377 * Return the number of characters that are available.
378 * If wtime == 0 do not wait for characters.
379 * If wtime == n wait a short time for characters.
380 * If wtime == -1 wait forever for characters.
381 */
382 int
383mch_inchar(buf, maxlen, wtime, tb_change_cnt)
384 char_u *buf;
385 int maxlen;
386 long wtime; /* don't use "time", MIPS cannot handle it */
387 int tb_change_cnt;
388{
389 int len;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000390
Bram Moolenaar93c88e02015-09-15 14:12:05 +0200391#ifdef MESSAGE_QUEUE
392 parse_queued_messages();
Bram Moolenaar67c53842010-05-22 18:28:27 +0200393#endif
394
Bram Moolenaar071d4272004-06-13 20:20:40 +0000395 /* Check if window changed size while we were busy, perhaps the ":set
396 * columns=99" command was used. */
397 while (do_resize)
398 handle_resize();
399
400 if (wtime >= 0)
401 {
402 while (WaitForChar(wtime) == 0) /* no character available */
403 {
Bram Moolenaar5d8afeb2015-11-19 19:55:16 +0100404 if (do_resize)
405 handle_resize();
406#ifdef FEAT_CLIENTSERVER
407 else if (!server_waiting())
408#else
409 else
410#endif
411 /* return if not interrupted by resize or server */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000412 return 0;
Bram Moolenaar93c88e02015-09-15 14:12:05 +0200413#ifdef MESSAGE_QUEUE
414 parse_queued_messages();
Bram Moolenaar67c53842010-05-22 18:28:27 +0200415#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000416 }
417 }
418 else /* wtime == -1 */
419 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000420 /*
421 * If there is no character available within 'updatetime' seconds
Bram Moolenaar4317d9b2005-03-18 20:25:31 +0000422 * flush all the swap files to disk.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000423 * Also done when interrupted by SIGWINCH.
424 */
425 if (WaitForChar(p_ut) == 0)
426 {
427#ifdef FEAT_AUTOCMD
Bram Moolenaard35f9712005-12-18 22:02:33 +0000428 if (trigger_cursorhold() && maxlen >= 3
429 && !typebuf_changed(tb_change_cnt))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000430 {
Bram Moolenaar4317d9b2005-03-18 20:25:31 +0000431 buf[0] = K_SPECIAL;
432 buf[1] = KS_EXTRA;
433 buf[2] = (int)KE_CURSORHOLD;
434 return 3;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000435 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000436#endif
Bram Moolenaard4098f52005-06-27 22:37:13 +0000437 before_blocking();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000438 }
439 }
440
441 for (;;) /* repeat until we got a character */
442 {
443 while (do_resize) /* window changed size */
444 handle_resize();
Bram Moolenaar67c53842010-05-22 18:28:27 +0200445
Bram Moolenaar93c88e02015-09-15 14:12:05 +0200446#ifdef MESSAGE_QUEUE
447 parse_queued_messages();
Bram Moolenaar67c53842010-05-22 18:28:27 +0200448#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000449 /*
Bram Moolenaar48bae372010-07-29 23:12:15 +0200450 * We want to be interrupted by the winch signal
451 * or by an event on the monitored file descriptors.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000452 */
Bram Moolenaar67c53842010-05-22 18:28:27 +0200453 if (WaitForChar(-1L) == 0)
454 {
455 if (do_resize) /* interrupted by SIGWINCH signal */
456 handle_resize();
457 return 0;
458 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000459
460 /* If input was put directly in typeahead buffer bail out here. */
461 if (typebuf_changed(tb_change_cnt))
462 return 0;
463
464 /*
465 * For some terminals we only get one character at a time.
466 * We want the get all available characters, so we could keep on
467 * trying until none is available
468 * For some other terminals this is quite slow, that's why we don't do
469 * it.
470 */
471 len = read_from_input_buf(buf, (long)maxlen);
472 if (len > 0)
473 {
474#ifdef OS2
475 int i;
476
477 for (i = 0; i < len; i++)
478 if (buf[i] == 0)
479 buf[i] = K_NUL;
480#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000481 return len;
482 }
483 }
484}
485
486 static void
487handle_resize()
488{
489 do_resize = FALSE;
490 shell_resized();
491}
492
493/*
494 * return non-zero if a character is available
495 */
496 int
497mch_char_avail()
498{
499 return WaitForChar(0L);
500}
501
502#if defined(HAVE_TOTAL_MEM) || defined(PROTO)
503# ifdef HAVE_SYS_RESOURCE_H
Bram Moolenaar8f0b2d42009-05-16 14:41:10 +0000504# include <sys/resource.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +0000505# endif
506# if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTL)
507# include <sys/sysctl.h>
508# endif
509# if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
510# include <sys/sysinfo.h>
511# endif
512
513/*
Bram Moolenaar914572a2007-05-01 11:37:47 +0000514 * Return total amount of memory available in Kbyte.
515 * Doesn't change when memory has been allocated.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000516 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000517 long_u
518mch_total_mem(special)
Bram Moolenaar78a15312009-05-15 19:33:18 +0000519 int special UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000520{
521# ifdef __EMX__
Bram Moolenaar914572a2007-05-01 11:37:47 +0000522 return ulimit(3, 0L) >> 10; /* always 32MB? */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000523# else
524 long_u mem = 0;
Bram Moolenaar914572a2007-05-01 11:37:47 +0000525 long_u shiftright = 10; /* how much to shift "mem" right for Kbyte */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000526
527# ifdef HAVE_SYSCTL
528 int mib[2], physmem;
529 size_t len;
530
531 /* BSD way of getting the amount of RAM available. */
532 mib[0] = CTL_HW;
533 mib[1] = HW_USERMEM;
534 len = sizeof(physmem);
535 if (sysctl(mib, 2, &physmem, &len, NULL, 0) == 0)
536 mem = (long_u)physmem;
537# endif
538
539# if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
540 if (mem == 0)
541 {
542 struct sysinfo sinfo;
543
544 /* Linux way of getting amount of RAM available */
545 if (sysinfo(&sinfo) == 0)
Bram Moolenaar914572a2007-05-01 11:37:47 +0000546 {
547# ifdef HAVE_SYSINFO_MEM_UNIT
548 /* avoid overflow as much as possible */
549 while (shiftright > 0 && (sinfo.mem_unit & 1) == 0)
550 {
551 sinfo.mem_unit = sinfo.mem_unit >> 1;
552 --shiftright;
553 }
554 mem = sinfo.totalram * sinfo.mem_unit;
555# else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000556 mem = sinfo.totalram;
Bram Moolenaar914572a2007-05-01 11:37:47 +0000557# endif
558 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000559 }
560# endif
561
562# ifdef HAVE_SYSCONF
563 if (mem == 0)
564 {
565 long pagesize, pagecount;
566
567 /* Solaris way of getting amount of RAM available */
568 pagesize = sysconf(_SC_PAGESIZE);
569 pagecount = sysconf(_SC_PHYS_PAGES);
570 if (pagesize > 0 && pagecount > 0)
Bram Moolenaar914572a2007-05-01 11:37:47 +0000571 {
572 /* avoid overflow as much as possible */
573 while (shiftright > 0 && (pagesize & 1) == 0)
574 {
Bram Moolenaar3d27a452007-05-10 17:44:18 +0000575 pagesize = (long_u)pagesize >> 1;
Bram Moolenaar914572a2007-05-01 11:37:47 +0000576 --shiftright;
577 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000578 mem = (long_u)pagesize * pagecount;
Bram Moolenaar914572a2007-05-01 11:37:47 +0000579 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000580 }
581# endif
582
583 /* Return the minimum of the physical memory and the user limit, because
584 * using more than the user limit may cause Vim to be terminated. */
585# if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT)
586 {
587 struct rlimit rlp;
588
589 if (getrlimit(RLIMIT_DATA, &rlp) == 0
590 && rlp.rlim_cur < ((rlim_t)1 << (sizeof(long_u) * 8 - 1))
591# ifdef RLIM_INFINITY
592 && rlp.rlim_cur != RLIM_INFINITY
593# endif
Bram Moolenaar914572a2007-05-01 11:37:47 +0000594 && ((long_u)rlp.rlim_cur >> 10) < (mem >> shiftright)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000595 )
Bram Moolenaar914572a2007-05-01 11:37:47 +0000596 {
597 mem = (long_u)rlp.rlim_cur;
598 shiftright = 10;
599 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000600 }
601# endif
602
603 if (mem > 0)
Bram Moolenaar914572a2007-05-01 11:37:47 +0000604 return mem >> shiftright;
605 return (long_u)0x1fffff;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000606# endif
607}
608#endif
609
610 void
611mch_delay(msec, ignoreinput)
612 long msec;
613 int ignoreinput;
614{
615 int old_tmode;
Bram Moolenaar325b7a22004-07-05 15:58:32 +0000616#ifdef FEAT_MZSCHEME
617 long total = msec; /* remember original value */
618#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000619
620 if (ignoreinput)
621 {
622 /* Go to cooked mode without echo, to allow SIGINT interrupting us
Bram Moolenaarae0f2ca2008-02-10 21:25:55 +0000623 * here. But we don't want QUIT to kill us (CTRL-\ used in a
624 * shell may produce SIGQUIT). */
625 in_mch_delay = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000626 old_tmode = curr_tmode;
627 if (curr_tmode == TMODE_RAW)
628 settmode(TMODE_SLEEP);
629
630 /*
631 * Everybody sleeps in a different way...
632 * Prefer nanosleep(), some versions of usleep() can only sleep up to
633 * one second.
634 */
Bram Moolenaar325b7a22004-07-05 15:58:32 +0000635#ifdef FEAT_MZSCHEME
636 do
637 {
638 /* if total is large enough, wait by portions in p_mzq */
639 if (total > p_mzq)
640 msec = p_mzq;
641 else
642 msec = total;
643 total -= msec;
644#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000645#ifdef HAVE_NANOSLEEP
646 {
647 struct timespec ts;
648
649 ts.tv_sec = msec / 1000;
650 ts.tv_nsec = (msec % 1000) * 1000000;
651 (void)nanosleep(&ts, NULL);
652 }
653#else
654# ifdef HAVE_USLEEP
655 while (msec >= 1000)
656 {
657 usleep((unsigned int)(999 * 1000));
658 msec -= 999;
659 }
660 usleep((unsigned int)(msec * 1000));
661# else
662# ifndef HAVE_SELECT
663 poll(NULL, 0, (int)msec);
664# else
665# ifdef __EMX__
666 _sleep2(msec);
667# else
668 {
669 struct timeval tv;
670
671 tv.tv_sec = msec / 1000;
672 tv.tv_usec = (msec % 1000) * 1000;
673 /*
674 * NOTE: Solaris 2.6 has a bug that makes select() hang here. Get
675 * a patch from Sun to fix this. Reported by Gunnar Pedersen.
676 */
677 select(0, NULL, NULL, NULL, &tv);
678 }
679# endif /* __EMX__ */
680# endif /* HAVE_SELECT */
681# endif /* HAVE_NANOSLEEP */
682#endif /* HAVE_USLEEP */
Bram Moolenaar325b7a22004-07-05 15:58:32 +0000683#ifdef FEAT_MZSCHEME
684 }
685 while (total > 0);
686#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000687
688 settmode(old_tmode);
Bram Moolenaarae0f2ca2008-02-10 21:25:55 +0000689 in_mch_delay = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000690 }
691 else
692 WaitForChar(msec);
693}
694
Bram Moolenaarbc7aa852005-03-06 23:38:09 +0000695#if defined(HAVE_STACK_LIMIT) \
Bram Moolenaar071d4272004-06-13 20:20:40 +0000696 || (!defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGSTACK))
697# define HAVE_CHECK_STACK_GROWTH
698/*
699 * Support for checking for an almost-out-of-stack-space situation.
700 */
701
702/*
703 * Return a pointer to an item on the stack. Used to find out if the stack
704 * grows up or down.
705 */
706static void check_stack_growth __ARGS((char *p));
707static int stack_grows_downwards;
708
709/*
710 * Find out if the stack grows upwards or downwards.
711 * "p" points to a variable on the stack of the caller.
712 */
713 static void
714check_stack_growth(p)
715 char *p;
716{
717 int i;
718
719 stack_grows_downwards = (p > (char *)&i);
720}
721#endif
722
Bram Moolenaarbc7aa852005-03-06 23:38:09 +0000723#if defined(HAVE_STACK_LIMIT) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000724static char *stack_limit = NULL;
725
726#if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
727# include <pthread.h>
728# include <pthread_np.h>
729#endif
730
731/*
732 * Find out until how var the stack can grow without getting into trouble.
733 * Called when starting up and when switching to the signal stack in
734 * deathtrap().
735 */
736 static void
737get_stack_limit()
738{
739 struct rlimit rlp;
740 int i;
741 long lim;
742
743 /* Set the stack limit to 15/16 of the allowable size. Skip this when the
744 * limit doesn't fit in a long (rlim_cur might be "long long"). */
745 if (getrlimit(RLIMIT_STACK, &rlp) == 0
746 && rlp.rlim_cur < ((rlim_t)1 << (sizeof(long_u) * 8 - 1))
747# ifdef RLIM_INFINITY
748 && rlp.rlim_cur != RLIM_INFINITY
749# endif
750 )
751 {
752 lim = (long)rlp.rlim_cur;
753#if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
754 {
755 pthread_attr_t attr;
756 size_t size;
757
758 /* On FreeBSD the initial thread always has a fixed stack size, no
759 * matter what the limits are set to. Normally it's 1 Mbyte. */
760 pthread_attr_init(&attr);
761 if (pthread_attr_get_np(pthread_self(), &attr) == 0)
762 {
763 pthread_attr_getstacksize(&attr, &size);
764 if (lim > (long)size)
765 lim = (long)size;
766 }
767 pthread_attr_destroy(&attr);
768 }
769#endif
770 if (stack_grows_downwards)
771 {
772 stack_limit = (char *)((long)&i - (lim / 16L * 15L));
773 if (stack_limit >= (char *)&i)
774 /* overflow, set to 1/16 of current stack position */
775 stack_limit = (char *)((long)&i / 16L);
776 }
777 else
778 {
779 stack_limit = (char *)((long)&i + (lim / 16L * 15L));
780 if (stack_limit <= (char *)&i)
781 stack_limit = NULL; /* overflow */
782 }
783 }
784}
785
786/*
787 * Return FAIL when running out of stack space.
788 * "p" must point to any variable local to the caller that's on the stack.
789 */
790 int
791mch_stackcheck(p)
792 char *p;
793{
794 if (stack_limit != NULL)
795 {
796 if (stack_grows_downwards)
797 {
798 if (p < stack_limit)
799 return FAIL;
800 }
801 else if (p > stack_limit)
802 return FAIL;
803 }
804 return OK;
805}
806#endif
807
808#if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
809/*
810 * Support for using the signal stack.
811 * This helps when we run out of stack space, which causes a SIGSEGV. The
812 * signal handler then must run on another stack, since the normal stack is
813 * completely full.
814 */
815
Bram Moolenaar39766a72013-11-03 00:41:00 +0100816#if defined(HAVE_AVAILABILITYMACROS_H)
Bram Moolenaar4cc95d12013-11-02 21:49:32 +0100817# include <AvailabilityMacros.h>
818#endif
819
Bram Moolenaar071d4272004-06-13 20:20:40 +0000820#ifndef SIGSTKSZ
821# define SIGSTKSZ 8000 /* just a guess of how much stack is needed... */
822#endif
823
824# ifdef HAVE_SIGALTSTACK
825static stack_t sigstk; /* for sigaltstack() */
826# else
827static struct sigstack sigstk; /* for sigstack() */
828# endif
829
830static void init_signal_stack __ARGS((void));
831static char *signal_stack;
832
833 static void
834init_signal_stack()
835{
836 if (signal_stack != NULL)
837 {
838# ifdef HAVE_SIGALTSTACK
Bram Moolenaar1a3d0862007-08-30 09:47:38 +0000839# if defined(__APPLE__) && (!defined(MAC_OS_X_VERSION_MAX_ALLOWED) \
840 || MAC_OS_X_VERSION_MAX_ALLOWED <= 1040)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000841 /* missing prototype. Adding it to osdef?.h.in doesn't work, because
842 * "struct sigaltstack" needs to be declared. */
843 extern int sigaltstack __ARGS((const struct sigaltstack *ss, struct sigaltstack *oss));
844# endif
845
846# ifdef HAVE_SS_BASE
847 sigstk.ss_base = signal_stack;
848# else
849 sigstk.ss_sp = signal_stack;
850# endif
851 sigstk.ss_size = SIGSTKSZ;
852 sigstk.ss_flags = 0;
853 (void)sigaltstack(&sigstk, NULL);
854# else
855 sigstk.ss_sp = signal_stack;
856 if (stack_grows_downwards)
857 sigstk.ss_sp += SIGSTKSZ - 1;
858 sigstk.ss_onstack = 0;
859 (void)sigstack(&sigstk, NULL);
860# endif
861 }
862}
863#endif
864
865/*
Bram Moolenaar76243bd2009-03-02 01:47:02 +0000866 * We need correct prototypes for a signal function, otherwise mean compilers
Bram Moolenaar071d4272004-06-13 20:20:40 +0000867 * will barf when the second argument to signal() is ``wrong''.
868 * Let me try it with a few tricky defines from my own osdef.h (jw).
869 */
870#if defined(SIGWINCH)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000871 static RETSIGTYPE
872sig_winch SIGDEFARG(sigarg)
873{
874 /* this is not required on all systems, but it doesn't hurt anybody */
875 signal(SIGWINCH, (RETSIGTYPE (*)())sig_winch);
876 do_resize = TRUE;
877 SIGRETURN;
878}
879#endif
880
881#if defined(SIGINT)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000882 static RETSIGTYPE
883catch_sigint SIGDEFARG(sigarg)
884{
885 /* this is not required on all systems, but it doesn't hurt anybody */
886 signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
887 got_int = TRUE;
888 SIGRETURN;
889}
890#endif
891
892#if defined(SIGPWR)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000893 static RETSIGTYPE
894catch_sigpwr SIGDEFARG(sigarg)
895{
Bram Moolenaard8b0cf12004-12-12 11:33:30 +0000896 /* this is not required on all systems, but it doesn't hurt anybody */
897 signal(SIGPWR, (RETSIGTYPE (*)())catch_sigpwr);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000898 /*
899 * I'm not sure we get the SIGPWR signal when the system is really going
900 * down or when the batteries are almost empty. Just preserve the swap
901 * files and don't exit, that can't do any harm.
902 */
903 ml_sync_all(FALSE, FALSE);
904 SIGRETURN;
905}
906#endif
907
908#ifdef SET_SIG_ALARM
909/*
910 * signal function for alarm().
911 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000912 static RETSIGTYPE
913sig_alarm SIGDEFARG(sigarg)
914{
915 /* doesn't do anything, just to break a system call */
916 sig_alarm_called = TRUE;
917 SIGRETURN;
918}
919#endif
920
Bram Moolenaar44ecf652005-03-07 23:09:59 +0000921#if (defined(HAVE_SETJMP_H) \
922 && ((defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) \
923 || defined(FEAT_LIBCALL))) \
924 || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000925/*
926 * A simplistic version of setjmp() that only allows one level of using.
927 * Don't call twice before calling mch_endjmp()!.
928 * Usage:
929 * mch_startjmp();
930 * if (SETJMP(lc_jump_env) != 0)
931 * {
932 * mch_didjmp();
933 * EMSG("crash!");
934 * }
935 * else
936 * {
937 * do_the_work;
938 * mch_endjmp();
939 * }
940 * Note: Can't move SETJMP() here, because a function calling setjmp() must
941 * not return before the saved environment is used.
942 * Returns OK for normal return, FAIL when the protected code caused a
943 * problem and LONGJMP() was used.
944 */
945 void
946mch_startjmp()
947{
948#ifdef SIGHASARG
949 lc_signal = 0;
950#endif
951 lc_active = TRUE;
952}
953
954 void
955mch_endjmp()
956{
957 lc_active = FALSE;
958}
959
960 void
961mch_didjmp()
962{
963# if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
964 /* On FreeBSD the signal stack has to be reset after using siglongjmp(),
965 * otherwise catching the signal only works once. */
966 init_signal_stack();
967# endif
968}
969#endif
970
971/*
972 * This function handles deadly signals.
Bram Moolenaarbec9c202013-09-05 21:41:39 +0200973 * It tries to preserve any swap files and exit properly.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000974 * (partly from Elvis).
Bram Moolenaarbec9c202013-09-05 21:41:39 +0200975 * NOTE: Avoid unsafe functions, such as allocating memory, they can result in
976 * a deadlock.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000977 */
978 static RETSIGTYPE
979deathtrap SIGDEFARG(sigarg)
980{
981 static int entered = 0; /* count the number of times we got here.
982 Note: when memory has been corrupted
983 this may get an arbitrary value! */
984#ifdef SIGHASARG
985 int i;
986#endif
987
988#if defined(HAVE_SETJMP_H)
989 /*
990 * Catch a crash in protected code.
991 * Restores the environment saved in lc_jump_env, which looks like
992 * SETJMP() returns 1.
993 */
994 if (lc_active)
995 {
996# if defined(SIGHASARG)
997 lc_signal = sigarg;
998# endif
999 lc_active = FALSE; /* don't jump again */
1000 LONGJMP(lc_jump_env, 1);
1001 /* NOTREACHED */
1002 }
1003#endif
1004
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001005#ifdef SIGHASARG
Bram Moolenaarae0f2ca2008-02-10 21:25:55 +00001006# ifdef SIGQUIT
1007 /* While in mch_delay() we go to cooked mode to allow a CTRL-C to
1008 * interrupt us. But in cooked mode we may also get SIGQUIT, e.g., when
1009 * pressing CTRL-\, but we don't want Vim to exit then. */
1010 if (in_mch_delay && sigarg == SIGQUIT)
1011 SIGRETURN;
1012# endif
1013
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001014 /* When SIGHUP, SIGQUIT, etc. are blocked: postpone the effect and return
1015 * here. This avoids that a non-reentrant function is interrupted, e.g.,
1016 * free(). Calling free() again may then cause a crash. */
1017 if (entered == 0
1018 && (0
1019# ifdef SIGHUP
1020 || sigarg == SIGHUP
1021# endif
1022# ifdef SIGQUIT
1023 || sigarg == SIGQUIT
1024# endif
1025# ifdef SIGTERM
1026 || sigarg == SIGTERM
1027# endif
1028# ifdef SIGPWR
1029 || sigarg == SIGPWR
1030# endif
1031# ifdef SIGUSR1
1032 || sigarg == SIGUSR1
1033# endif
1034# ifdef SIGUSR2
1035 || sigarg == SIGUSR2
1036# endif
1037 )
Bram Moolenaar1f28b072005-07-12 22:42:41 +00001038 && !vim_handle_signal(sigarg))
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001039 SIGRETURN;
1040#endif
1041
Bram Moolenaar071d4272004-06-13 20:20:40 +00001042 /* Remember how often we have been called. */
1043 ++entered;
1044
1045#ifdef FEAT_EVAL
1046 /* Set the v:dying variable. */
1047 set_vim_var_nr(VV_DYING, (long)entered);
1048#endif
1049
Bram Moolenaarbc7aa852005-03-06 23:38:09 +00001050#ifdef HAVE_STACK_LIMIT
Bram Moolenaar071d4272004-06-13 20:20:40 +00001051 /* Since we are now using the signal stack, need to reset the stack
1052 * limit. Otherwise using a regexp will fail. */
1053 get_stack_limit();
1054#endif
1055
Bram Moolenaar1f4d4de2006-03-14 23:00:46 +00001056#if 0
1057 /* This is for opening gdb the moment Vim crashes.
1058 * You need to manually adjust the file name and Vim executable name.
1059 * Suggested by SungHyun Nam. */
1060 {
1061# define VI_GDB_FILE "/tmp/vimgdb"
1062# define VIM_NAME "/usr/bin/vim"
1063 FILE *fp = fopen(VI_GDB_FILE, "w");
1064 if (fp)
1065 {
1066 fprintf(fp,
1067 "file %s\n"
1068 "attach %d\n"
1069 "set height 1000\n"
1070 "bt full\n"
1071 , VIM_NAME, getpid());
1072 fclose(fp);
1073 system("xterm -e gdb -x "VI_GDB_FILE);
1074 unlink(VI_GDB_FILE);
1075 }
1076 }
1077#endif
1078
Bram Moolenaar071d4272004-06-13 20:20:40 +00001079#ifdef SIGHASARG
1080 /* try to find the name of this signal */
1081 for (i = 0; signal_info[i].sig != -1; i++)
1082 if (sigarg == signal_info[i].sig)
1083 break;
1084 deadly_signal = sigarg;
1085#endif
1086
1087 full_screen = FALSE; /* don't write message to the GUI, it might be
1088 * part of the problem... */
1089 /*
1090 * If something goes wrong after entering here, we may get here again.
1091 * When this happens, give a message and try to exit nicely (resetting the
1092 * terminal mode, etc.)
1093 * When this happens twice, just exit, don't even try to give a message,
1094 * stack may be corrupt or something weird.
1095 * When this still happens again (or memory was corrupted in such a way
1096 * that "entered" was clobbered) use _exit(), don't try freeing resources.
1097 */
1098 if (entered >= 3)
1099 {
1100 reset_signals(); /* don't catch any signals anymore */
1101 may_core_dump();
1102 if (entered >= 4)
1103 _exit(8);
1104 exit(7);
1105 }
1106 if (entered == 2)
1107 {
Bram Moolenaarbec9c202013-09-05 21:41:39 +02001108 /* No translation, it may call malloc(). */
1109 OUT_STR("Vim: Double signal, exiting\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001110 out_flush();
1111 getout(1);
1112 }
1113
Bram Moolenaarbec9c202013-09-05 21:41:39 +02001114 /* No translation, it may call malloc(). */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001115#ifdef SIGHASARG
Bram Moolenaarbec9c202013-09-05 21:41:39 +02001116 sprintf((char *)IObuff, "Vim: Caught deadly signal %s\n",
Bram Moolenaar071d4272004-06-13 20:20:40 +00001117 signal_info[i].name);
1118#else
Bram Moolenaarbec9c202013-09-05 21:41:39 +02001119 sprintf((char *)IObuff, "Vim: Caught deadly signal\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001120#endif
Bram Moolenaarbec9c202013-09-05 21:41:39 +02001121
1122 /* Preserve files and exit. This sets the really_exiting flag to prevent
1123 * calling free(). */
1124 preserve_exit();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001125
Bram Moolenaar009b2592004-10-24 19:18:58 +00001126#ifdef NBDEBUG
1127 reset_signals();
1128 may_core_dump();
1129 abort();
1130#endif
1131
Bram Moolenaar071d4272004-06-13 20:20:40 +00001132 SIGRETURN;
1133}
1134
Bram Moolenaar76243bd2009-03-02 01:47:02 +00001135#if defined(_REENTRANT) && defined(SIGCONT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001136/*
1137 * On Solaris with multi-threading, suspending might not work immediately.
1138 * Catch the SIGCONT signal, which will be used as an indication whether the
1139 * suspending has been done or not.
Bram Moolenaar76243bd2009-03-02 01:47:02 +00001140 *
1141 * On Linux, signal is not always handled immediately either.
1142 * See https://bugs.launchpad.net/bugs/291373
1143 *
Bram Moolenaarb292a2a2011-02-09 18:47:40 +01001144 * volatile because it is used in signal handler sigcont_handler().
Bram Moolenaar071d4272004-06-13 20:20:40 +00001145 */
Bram Moolenaar76243bd2009-03-02 01:47:02 +00001146static volatile int sigcont_received;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001147static RETSIGTYPE sigcont_handler __ARGS(SIGPROTOARG);
1148
1149/*
1150 * signal handler for SIGCONT
1151 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001152 static RETSIGTYPE
1153sigcont_handler SIGDEFARG(sigarg)
1154{
1155 sigcont_received = TRUE;
1156 SIGRETURN;
1157}
1158#endif
1159
Bram Moolenaar62b42182010-09-21 22:09:37 +02001160# if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
1161static void loose_clipboard __ARGS((void));
Bram Moolenaar090cfc12013-03-19 12:35:42 +01001162# ifdef USE_SYSTEM
Bram Moolenaar1a0316c2013-03-13 17:50:25 +01001163static void save_clipboard __ARGS((void));
1164static void restore_clipboard __ARGS((void));
1165
1166static void *clip_star_save = NULL;
1167static void *clip_plus_save = NULL;
Bram Moolenaar090cfc12013-03-19 12:35:42 +01001168# endif
Bram Moolenaar62b42182010-09-21 22:09:37 +02001169
1170/*
1171 * Called when Vim is going to sleep or execute a shell command.
1172 * We can't respond to requests for the X selections. Lose them, otherwise
1173 * other applications will hang. But first copy the text to cut buffer 0.
1174 */
1175 static void
1176loose_clipboard()
1177{
1178 if (clip_star.owned || clip_plus.owned)
1179 {
1180 x11_export_final_selection();
1181 if (clip_star.owned)
1182 clip_lose_selection(&clip_star);
1183 if (clip_plus.owned)
1184 clip_lose_selection(&clip_plus);
1185 if (x11_display != NULL)
1186 XFlush(x11_display);
1187 }
1188}
Bram Moolenaar1a0316c2013-03-13 17:50:25 +01001189
Bram Moolenaar090cfc12013-03-19 12:35:42 +01001190# ifdef USE_SYSTEM
Bram Moolenaar1a0316c2013-03-13 17:50:25 +01001191/*
1192 * Save clipboard text to restore later.
1193 */
1194 static void
1195save_clipboard()
1196{
1197 if (clip_star.owned)
1198 clip_star_save = get_register('*', TRUE);
1199 if (clip_plus.owned)
1200 clip_plus_save = get_register('+', TRUE);
1201}
1202
1203/*
1204 * Restore clipboard text if no one own the X selection.
1205 */
1206 static void
1207restore_clipboard()
1208{
1209 if (clip_star_save != NULL)
1210 {
1211 if (!clip_gen_owner_exists(&clip_star))
1212 put_register('*', clip_star_save);
1213 else
1214 free_register(clip_star_save);
1215 clip_star_save = NULL;
1216 }
1217 if (clip_plus_save != NULL)
1218 {
1219 if (!clip_gen_owner_exists(&clip_plus))
1220 put_register('+', clip_plus_save);
1221 else
1222 free_register(clip_plus_save);
1223 clip_plus_save = NULL;
1224 }
1225}
Bram Moolenaar090cfc12013-03-19 12:35:42 +01001226# endif
Bram Moolenaar62b42182010-09-21 22:09:37 +02001227#endif
1228
Bram Moolenaar071d4272004-06-13 20:20:40 +00001229/*
1230 * If the machine has job control, use it to suspend the program,
1231 * otherwise fake it by starting a new shell.
1232 */
1233 void
1234mch_suspend()
1235{
1236 /* BeOS does have SIGTSTP, but it doesn't work. */
1237#if defined(SIGTSTP) && !defined(__BEOS__)
1238 out_flush(); /* needed to make cursor visible on some systems */
1239 settmode(TMODE_COOK);
1240 out_flush(); /* needed to disable mouse on some systems */
1241
1242# if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
Bram Moolenaar62b42182010-09-21 22:09:37 +02001243 loose_clipboard();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001244# endif
1245
Bram Moolenaar76243bd2009-03-02 01:47:02 +00001246# if defined(_REENTRANT) && defined(SIGCONT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001247 sigcont_received = FALSE;
1248# endif
1249 kill(0, SIGTSTP); /* send ourselves a STOP signal */
Bram Moolenaar76243bd2009-03-02 01:47:02 +00001250# if defined(_REENTRANT) && defined(SIGCONT)
1251 /*
1252 * Wait for the SIGCONT signal to be handled. It generally happens
1253 * immediately, but somehow not all the time. Do not call pause()
1254 * because there would be race condition which would hang Vim if
1255 * signal happened in between the test of sigcont_received and the
1256 * call to pause(). If signal is not yet received, call sleep(0)
1257 * to just yield CPU. Signal should then be received. If somehow
1258 * it's still not received, sleep 1, 2, 3 ms. Don't bother waiting
1259 * further if signal is not received after 1+2+3+4 ms (not expected
1260 * to happen).
1261 */
1262 {
Bram Moolenaar262735e2009-07-14 10:20:22 +00001263 long wait_time;
1264 for (wait_time = 0; !sigcont_received && wait_time <= 3L; wait_time++)
Bram Moolenaar76243bd2009-03-02 01:47:02 +00001265 /* Loop is not entered most of the time */
Bram Moolenaar262735e2009-07-14 10:20:22 +00001266 mch_delay(wait_time, FALSE);
Bram Moolenaar76243bd2009-03-02 01:47:02 +00001267 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001268# endif
1269
1270# ifdef FEAT_TITLE
1271 /*
1272 * Set oldtitle to NULL, so the current title is obtained again.
1273 */
1274 vim_free(oldtitle);
1275 oldtitle = NULL;
1276# endif
1277 settmode(TMODE_RAW);
1278 need_check_timestamps = TRUE;
1279 did_check_timestamps = FALSE;
1280#else
1281 suspend_shell();
1282#endif
1283}
1284
1285 void
1286mch_init()
1287{
1288 Columns = 80;
1289 Rows = 24;
1290
1291 out_flush();
1292 set_signals();
Bram Moolenaardf177f62005-02-22 08:39:57 +00001293
Bram Moolenaar56718732006-03-15 22:53:57 +00001294#ifdef MACOS_CONVERT
Bram Moolenaardf177f62005-02-22 08:39:57 +00001295 mac_conv_init();
1296#endif
Bram Moolenaar693e40c2013-02-26 14:56:42 +01001297#ifdef FEAT_CYGWIN_WIN32_CLIPBOARD
1298 win_clip_init();
1299#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001300}
1301
1302 static void
1303set_signals()
1304{
1305#if defined(SIGWINCH)
1306 /*
1307 * WINDOW CHANGE signal is handled with sig_winch().
1308 */
1309 signal(SIGWINCH, (RETSIGTYPE (*)())sig_winch);
1310#endif
1311
1312 /*
1313 * We want the STOP signal to work, to make mch_suspend() work.
1314 * For "rvim" the STOP signal is ignored.
1315 */
1316#ifdef SIGTSTP
1317 signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
1318#endif
Bram Moolenaar76243bd2009-03-02 01:47:02 +00001319#if defined(_REENTRANT) && defined(SIGCONT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001320 signal(SIGCONT, sigcont_handler);
1321#endif
1322
1323 /*
1324 * We want to ignore breaking of PIPEs.
1325 */
1326#ifdef SIGPIPE
1327 signal(SIGPIPE, SIG_IGN);
1328#endif
1329
Bram Moolenaar071d4272004-06-13 20:20:40 +00001330#ifdef SIGINT
Bram Moolenaardf177f62005-02-22 08:39:57 +00001331 catch_int_signal();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001332#endif
1333
1334 /*
1335 * Ignore alarm signals (Perl's alarm() generates it).
1336 */
1337#ifdef SIGALRM
1338 signal(SIGALRM, SIG_IGN);
1339#endif
1340
1341 /*
1342 * Catch SIGPWR (power failure?) to preserve the swap files, so that no
1343 * work will be lost.
1344 */
1345#ifdef SIGPWR
1346 signal(SIGPWR, (RETSIGTYPE (*)())catch_sigpwr);
1347#endif
1348
1349 /*
1350 * Arrange for other signals to gracefully shutdown Vim.
1351 */
1352 catch_signals(deathtrap, SIG_ERR);
1353
1354#if defined(FEAT_GUI) && defined(SIGHUP)
1355 /*
1356 * When the GUI is running, ignore the hangup signal.
1357 */
1358 if (gui.in_use)
1359 signal(SIGHUP, SIG_IGN);
1360#endif
1361}
1362
Bram Moolenaardf177f62005-02-22 08:39:57 +00001363#if defined(SIGINT) || defined(PROTO)
1364/*
1365 * Catch CTRL-C (only works while in Cooked mode).
1366 */
1367 static void
1368catch_int_signal()
1369{
1370 signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
1371}
1372#endif
1373
Bram Moolenaar071d4272004-06-13 20:20:40 +00001374 void
1375reset_signals()
1376{
1377 catch_signals(SIG_DFL, SIG_DFL);
Bram Moolenaar76243bd2009-03-02 01:47:02 +00001378#if defined(_REENTRANT) && defined(SIGCONT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001379 /* SIGCONT isn't in the list, because its default action is ignore */
1380 signal(SIGCONT, SIG_DFL);
1381#endif
1382}
1383
1384 static void
1385catch_signals(func_deadly, func_other)
1386 RETSIGTYPE (*func_deadly)();
1387 RETSIGTYPE (*func_other)();
1388{
1389 int i;
1390
1391 for (i = 0; signal_info[i].sig != -1; i++)
1392 if (signal_info[i].deadly)
1393 {
1394#if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION)
1395 struct sigaction sa;
1396
1397 /* Setup to use the alternate stack for the signal function. */
1398 sa.sa_handler = func_deadly;
1399 sigemptyset(&sa.sa_mask);
1400# if defined(__linux__) && defined(_REENTRANT)
1401 /* On Linux, with glibc compiled for kernel 2.2, there is a bug in
1402 * thread handling in combination with using the alternate stack:
1403 * pthread library functions try to use the stack pointer to
1404 * identify the current thread, causing a SEGV signal, which
1405 * recursively calls deathtrap() and hangs. */
1406 sa.sa_flags = 0;
1407# else
1408 sa.sa_flags = SA_ONSTACK;
1409# endif
1410 sigaction(signal_info[i].sig, &sa, NULL);
1411#else
1412# if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGVEC)
1413 struct sigvec sv;
1414
1415 /* Setup to use the alternate stack for the signal function. */
1416 sv.sv_handler = func_deadly;
1417 sv.sv_mask = 0;
1418 sv.sv_flags = SV_ONSTACK;
1419 sigvec(signal_info[i].sig, &sv, NULL);
1420# else
1421 signal(signal_info[i].sig, func_deadly);
1422# endif
1423#endif
1424 }
1425 else if (func_other != SIG_ERR)
1426 signal(signal_info[i].sig, func_other);
1427}
1428
1429/*
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001430 * Handling of SIGHUP, SIGQUIT and SIGTERM:
Bram Moolenaar9e1d2832007-05-06 12:51:41 +00001431 * "when" == a signal: when busy, postpone and return FALSE, otherwise
1432 * return TRUE
1433 * "when" == SIGNAL_BLOCK: Going to be busy, block signals
1434 * "when" == SIGNAL_UNBLOCK: Going to wait, unblock signals, use postponed
Bram Moolenaar67c53842010-05-22 18:28:27 +02001435 * signal
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001436 * Returns TRUE when Vim should exit.
1437 */
1438 int
Bram Moolenaar1f28b072005-07-12 22:42:41 +00001439vim_handle_signal(sig)
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001440 int sig;
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001441{
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001442 static int got_signal = 0;
1443 static int blocked = TRUE;
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001444
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001445 switch (sig)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001446 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001447 case SIGNAL_BLOCK: blocked = TRUE;
1448 break;
1449
1450 case SIGNAL_UNBLOCK: blocked = FALSE;
1451 if (got_signal != 0)
1452 {
1453 kill(getpid(), got_signal);
1454 got_signal = 0;
1455 }
1456 break;
1457
1458 default: if (!blocked)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001459 return TRUE; /* exit! */
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001460 got_signal = sig;
1461#ifdef SIGPWR
1462 if (sig != SIGPWR)
1463#endif
1464 got_int = TRUE; /* break any loops */
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001465 break;
1466 }
1467 return FALSE;
1468}
1469
1470/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00001471 * Check_win checks whether we have an interactive stdout.
1472 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001473 int
1474mch_check_win(argc, argv)
Bram Moolenaar78a15312009-05-15 19:33:18 +00001475 int argc UNUSED;
1476 char **argv UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001477{
1478#ifdef OS2
1479 /*
1480 * Store argv[0], may be used for $VIM. Only use it if it is an absolute
1481 * name, mostly it's just "vim" and found in the path, which is unusable.
1482 */
1483 if (mch_isFullName(argv[0]))
1484 exe_name = vim_strsave((char_u *)argv[0]);
1485#endif
1486 if (isatty(1))
1487 return OK;
1488 return FAIL;
1489}
1490
1491/*
1492 * Return TRUE if the input comes from a terminal, FALSE otherwise.
1493 */
1494 int
1495mch_input_isatty()
1496{
1497 if (isatty(read_cmd_fd))
1498 return TRUE;
1499 return FALSE;
1500}
1501
1502#ifdef FEAT_X11
1503
1504# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) \
1505 && (defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE))
1506
1507static void xopen_message __ARGS((struct timeval *tvp));
1508
1509/*
1510 * Give a message about the elapsed time for opening the X window.
1511 */
1512 static void
1513xopen_message(tvp)
1514 struct timeval *tvp; /* must contain start time */
1515{
1516 struct timeval end_tv;
1517
1518 /* Compute elapsed time. */
1519 gettimeofday(&end_tv, NULL);
1520 smsg((char_u *)_("Opening the X display took %ld msec"),
1521 (end_tv.tv_sec - tvp->tv_sec) * 1000L
Bram Moolenaar051b7822005-05-19 21:00:46 +00001522 + (end_tv.tv_usec - tvp->tv_usec) / 1000L);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001523}
1524# endif
1525#endif
1526
1527#if defined(FEAT_X11) && (defined(FEAT_TITLE) || defined(FEAT_XCLIPBOARD))
1528/*
1529 * A few functions shared by X11 title and clipboard code.
1530 */
1531static int x_error_handler __ARGS((Display *dpy, XErrorEvent *error_event));
1532static int x_error_check __ARGS((Display *dpy, XErrorEvent *error_event));
1533static int x_connect_to_server __ARGS((void));
1534static int test_x11_window __ARGS((Display *dpy));
1535
1536static int got_x_error = FALSE;
1537
1538/*
1539 * X Error handler, otherwise X just exits! (very rude) -- webb
1540 */
1541 static int
1542x_error_handler(dpy, error_event)
1543 Display *dpy;
1544 XErrorEvent *error_event;
1545{
Bram Moolenaar843ee412004-06-30 16:16:41 +00001546 XGetErrorText(dpy, error_event->error_code, (char *)IObuff, IOSIZE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001547 STRCAT(IObuff, _("\nVim: Got X error\n"));
1548
1549 /* We cannot print a message and continue, because no X calls are allowed
1550 * here (causes my system to hang). Silently continuing might be an
1551 * alternative... */
1552 preserve_exit(); /* preserve files and exit */
1553
1554 return 0; /* NOTREACHED */
1555}
1556
1557/*
1558 * Another X Error handler, just used to check for errors.
1559 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001560 static int
1561x_error_check(dpy, error_event)
Bram Moolenaar2c4278f2009-05-17 11:33:22 +00001562 Display *dpy UNUSED;
1563 XErrorEvent *error_event UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001564{
1565 got_x_error = TRUE;
1566 return 0;
1567}
1568
1569#if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
1570# if defined(HAVE_SETJMP_H)
1571/*
1572 * An X IO Error handler, used to catch error while opening the display.
1573 */
1574static int x_IOerror_check __ARGS((Display *dpy));
1575
Bram Moolenaar071d4272004-06-13 20:20:40 +00001576 static int
1577x_IOerror_check(dpy)
Bram Moolenaar2c4278f2009-05-17 11:33:22 +00001578 Display *dpy UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001579{
1580 /* This function should not return, it causes exit(). Longjump instead. */
1581 LONGJMP(lc_jump_env, 1);
Bram Moolenaarfe17e762013-06-29 14:17:02 +02001582# if defined(VMS) || defined(__CYGWIN__) || defined(__CYGWIN32__)
Bram Moolenaarb4990bf2010-02-11 18:19:38 +01001583 return 0; /* avoid the compiler complains about missing return value */
1584# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001585}
1586# endif
1587
1588/*
1589 * An X IO Error handler, used to catch terminal errors.
1590 */
1591static int x_IOerror_handler __ARGS((Display *dpy));
Bram Moolenaarb1e26502014-11-19 18:48:46 +01001592static void may_restore_clipboard __ARGS((void));
1593static int xterm_dpy_was_reset = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001594
Bram Moolenaar071d4272004-06-13 20:20:40 +00001595 static int
1596x_IOerror_handler(dpy)
Bram Moolenaar2c4278f2009-05-17 11:33:22 +00001597 Display *dpy UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001598{
1599 xterm_dpy = NULL;
Bram Moolenaarb1e26502014-11-19 18:48:46 +01001600 xterm_dpy_was_reset = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001601 x11_window = 0;
1602 x11_display = NULL;
1603 xterm_Shell = (Widget)0;
1604
1605 /* This function should not return, it causes exit(). Longjump instead. */
1606 LONGJMP(x_jump_env, 1);
Bram Moolenaarfe17e762013-06-29 14:17:02 +02001607# if defined(VMS) || defined(__CYGWIN__) || defined(__CYGWIN32__)
Bram Moolenaarb4990bf2010-02-11 18:19:38 +01001608 return 0; /* avoid the compiler complains about missing return value */
1609# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001610}
Bram Moolenaarb1e26502014-11-19 18:48:46 +01001611
1612/*
1613 * If the X11 connection was lost try to restore it.
1614 * Helps when the X11 server was stopped and restarted while Vim was inactive
Bram Moolenaarcaad4f02014-12-17 14:36:14 +01001615 * (e.g. through tmux).
Bram Moolenaarb1e26502014-11-19 18:48:46 +01001616 */
1617 static void
1618may_restore_clipboard()
1619{
1620 if (xterm_dpy_was_reset)
1621 {
1622 xterm_dpy_was_reset = FALSE;
Bram Moolenaar527a6782014-12-17 17:59:31 +01001623
1624# ifndef LESSTIF_VERSION
1625 /* This has been reported to avoid Vim getting stuck. */
1626 if (app_context != (XtAppContext)NULL)
1627 {
1628 XtDestroyApplicationContext(app_context);
1629 app_context = (XtAppContext)NULL;
1630 x11_display = NULL; /* freed by XtDestroyApplicationContext() */
1631 }
1632# endif
1633
Bram Moolenaarb1e26502014-11-19 18:48:46 +01001634 setup_term_clip();
1635 get_x11_title(FALSE);
1636 }
1637}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001638#endif
1639
1640/*
1641 * Return TRUE when connection to the X server is desired.
1642 */
1643 static int
1644x_connect_to_server()
1645{
Bram Moolenaar071d4272004-06-13 20:20:40 +00001646#if defined(FEAT_CLIENTSERVER)
1647 if (x_force_connect)
1648 return TRUE;
1649#endif
1650 if (x_no_connect)
1651 return FALSE;
1652
1653 /* Check for a match with "exclude:" from 'clipboard'. */
1654 if (clip_exclude_prog != NULL)
1655 {
Bram Moolenaardffa5b82014-11-19 16:38:07 +01001656 if (vim_regexec_prog(&clip_exclude_prog, FALSE, T_NAME, (colnr_T)0))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001657 return FALSE;
1658 }
1659 return TRUE;
1660}
1661
1662/*
1663 * Test if "dpy" and x11_window are valid by getting the window title.
1664 * I don't actually want it yet, so there may be a simpler call to use, but
1665 * this will cause the error handler x_error_check() to be called if anything
1666 * is wrong, such as the window pointer being invalid (as can happen when the
1667 * user changes his DISPLAY, but not his WINDOWID) -- webb
1668 */
1669 static int
1670test_x11_window(dpy)
1671 Display *dpy;
1672{
1673 int (*old_handler)();
1674 XTextProperty text_prop;
1675
1676 old_handler = XSetErrorHandler(x_error_check);
1677 got_x_error = FALSE;
1678 if (XGetWMName(dpy, x11_window, &text_prop))
1679 XFree((void *)text_prop.value);
1680 XSync(dpy, False);
1681 (void)XSetErrorHandler(old_handler);
1682
1683 if (p_verbose > 0 && got_x_error)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00001684 verb_msg((char_u *)_("Testing the X display failed"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001685
1686 return (got_x_error ? FAIL : OK);
1687}
1688#endif
1689
1690#ifdef FEAT_TITLE
1691
1692#ifdef FEAT_X11
1693
1694static int get_x11_thing __ARGS((int get_title, int test_only));
1695
1696/*
1697 * try to get x11 window and display
1698 *
1699 * return FAIL for failure, OK otherwise
1700 */
1701 static int
1702get_x11_windis()
1703{
1704 char *winid;
1705 static int result = -1;
1706#define XD_NONE 0 /* x11_display not set here */
1707#define XD_HERE 1 /* x11_display opened here */
1708#define XD_GUI 2 /* x11_display used from gui.dpy */
1709#define XD_XTERM 3 /* x11_display used from xterm_dpy */
1710 static int x11_display_from = XD_NONE;
1711 static int did_set_error_handler = FALSE;
1712
1713 if (!did_set_error_handler)
1714 {
1715 /* X just exits if it finds an error otherwise! */
1716 (void)XSetErrorHandler(x_error_handler);
1717 did_set_error_handler = TRUE;
1718 }
1719
Bram Moolenaar9372a112005-12-06 19:59:18 +00001720#if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001721 if (gui.in_use)
1722 {
1723 /*
1724 * If the X11 display was opened here before, for the window where Vim
1725 * was started, close that one now to avoid a memory leak.
1726 */
1727 if (x11_display_from == XD_HERE && x11_display != NULL)
1728 {
1729 XCloseDisplay(x11_display);
1730 x11_display_from = XD_NONE;
1731 }
1732 if (gui_get_x11_windis(&x11_window, &x11_display) == OK)
1733 {
1734 x11_display_from = XD_GUI;
1735 return OK;
1736 }
1737 x11_display = NULL;
1738 return FAIL;
1739 }
1740 else if (x11_display_from == XD_GUI)
1741 {
1742 /* GUI must have stopped somehow, clear x11_display */
1743 x11_window = 0;
1744 x11_display = NULL;
1745 x11_display_from = XD_NONE;
1746 }
1747#endif
1748
1749 /* When started with the "-X" argument, don't try connecting. */
1750 if (!x_connect_to_server())
1751 return FAIL;
1752
1753 /*
1754 * If WINDOWID not set, should try another method to find out
1755 * what the current window number is. The only code I know for
1756 * this is very complicated.
1757 * We assume that zero is invalid for WINDOWID.
1758 */
1759 if (x11_window == 0 && (winid = getenv("WINDOWID")) != NULL)
1760 x11_window = (Window)atol(winid);
1761
1762#ifdef FEAT_XCLIPBOARD
1763 if (xterm_dpy != NULL && x11_window != 0)
1764 {
Bram Moolenaarc2a27c32007-12-01 16:19:33 +00001765 /* We may have checked it already, but Gnome terminal can move us to
1766 * another window, so we need to check every time. */
1767 if (x11_display_from != XD_XTERM)
1768 {
1769 /*
1770 * If the X11 display was opened here before, for the window where
1771 * Vim was started, close that one now to avoid a memory leak.
1772 */
1773 if (x11_display_from == XD_HERE && x11_display != NULL)
1774 XCloseDisplay(x11_display);
1775 x11_display = xterm_dpy;
1776 x11_display_from = XD_XTERM;
1777 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001778 if (test_x11_window(x11_display) == FAIL)
1779 {
1780 /* probably bad $WINDOWID */
1781 x11_window = 0;
1782 x11_display = NULL;
1783 x11_display_from = XD_NONE;
1784 return FAIL;
1785 }
1786 return OK;
1787 }
1788#endif
1789
1790 if (x11_window == 0 || x11_display == NULL)
1791 result = -1;
1792
1793 if (result != -1) /* Have already been here and set this */
1794 return result; /* Don't do all these X calls again */
1795
1796 if (x11_window != 0 && x11_display == NULL)
1797 {
1798#ifdef SET_SIG_ALARM
1799 RETSIGTYPE (*sig_save)();
1800#endif
1801#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
1802 struct timeval start_tv;
1803
1804 if (p_verbose > 0)
1805 gettimeofday(&start_tv, NULL);
1806#endif
1807
1808#ifdef SET_SIG_ALARM
1809 /*
1810 * Opening the Display may hang if the DISPLAY setting is wrong, or
1811 * the network connection is bad. Set an alarm timer to get out.
1812 */
1813 sig_alarm_called = FALSE;
1814 sig_save = (RETSIGTYPE (*)())signal(SIGALRM,
1815 (RETSIGTYPE (*)())sig_alarm);
1816 alarm(2);
1817#endif
1818 x11_display = XOpenDisplay(NULL);
1819
1820#ifdef SET_SIG_ALARM
1821 alarm(0);
1822 signal(SIGALRM, (RETSIGTYPE (*)())sig_save);
1823 if (p_verbose > 0 && sig_alarm_called)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00001824 verb_msg((char_u *)_("Opening the X display timed out"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001825#endif
1826 if (x11_display != NULL)
1827 {
1828# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
1829 if (p_verbose > 0)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00001830 {
1831 verbose_enter();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001832 xopen_message(&start_tv);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00001833 verbose_leave();
1834 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001835# endif
1836 if (test_x11_window(x11_display) == FAIL)
1837 {
1838 /* Maybe window id is bad */
1839 x11_window = 0;
1840 XCloseDisplay(x11_display);
1841 x11_display = NULL;
1842 }
1843 else
1844 x11_display_from = XD_HERE;
1845 }
1846 }
1847 if (x11_window == 0 || x11_display == NULL)
1848 return (result = FAIL);
Bram Moolenaar727c8762010-10-20 19:17:48 +02001849
1850# ifdef FEAT_EVAL
1851 set_vim_var_nr(VV_WINDOWID, (long)x11_window);
1852# endif
1853
Bram Moolenaar071d4272004-06-13 20:20:40 +00001854 return (result = OK);
1855}
1856
1857/*
1858 * Determine original x11 Window Title
1859 */
1860 static int
1861get_x11_title(test_only)
1862 int test_only;
1863{
Bram Moolenaar47136d72004-10-12 20:02:24 +00001864 return get_x11_thing(TRUE, test_only);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001865}
1866
1867/*
1868 * Determine original x11 Window icon
1869 */
1870 static int
1871get_x11_icon(test_only)
1872 int test_only;
1873{
1874 int retval = FALSE;
1875
1876 retval = get_x11_thing(FALSE, test_only);
1877
1878 /* could not get old icon, use terminal name */
1879 if (oldicon == NULL && !test_only)
1880 {
1881 if (STRNCMP(T_NAME, "builtin_", 8) == 0)
Bram Moolenaar20de1c22009-07-22 11:28:11 +00001882 oldicon = vim_strsave(T_NAME + 8);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001883 else
Bram Moolenaar20de1c22009-07-22 11:28:11 +00001884 oldicon = vim_strsave(T_NAME);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001885 }
1886
1887 return retval;
1888}
1889
1890 static int
1891get_x11_thing(get_title, test_only)
1892 int get_title; /* get title string */
1893 int test_only;
1894{
1895 XTextProperty text_prop;
1896 int retval = FALSE;
1897 Status status;
1898
1899 if (get_x11_windis() == OK)
1900 {
1901 /* Get window/icon name if any */
1902 if (get_title)
1903 status = XGetWMName(x11_display, x11_window, &text_prop);
1904 else
1905 status = XGetWMIconName(x11_display, x11_window, &text_prop);
1906
1907 /*
1908 * If terminal is xterm, then x11_window may be a child window of the
1909 * outer xterm window that actually contains the window/icon name, so
1910 * keep traversing up the tree until a window with a title/icon is
1911 * found.
1912 */
1913 /* Previously this was only done for xterm and alikes. I don't see a
1914 * reason why it would fail for other terminal emulators.
1915 * if (term_is_xterm) */
1916 {
1917 Window root;
1918 Window parent;
1919 Window win = x11_window;
1920 Window *children;
1921 unsigned int num_children;
1922
1923 while (!status || text_prop.value == NULL)
1924 {
1925 if (!XQueryTree(x11_display, win, &root, &parent, &children,
1926 &num_children))
1927 break;
1928 if (children)
1929 XFree((void *)children);
1930 if (parent == root || parent == 0)
1931 break;
1932
1933 win = parent;
1934 if (get_title)
1935 status = XGetWMName(x11_display, win, &text_prop);
1936 else
1937 status = XGetWMIconName(x11_display, win, &text_prop);
1938 }
1939 }
1940 if (status && text_prop.value != NULL)
1941 {
1942 retval = TRUE;
1943 if (!test_only)
1944 {
Bram Moolenaarf82bac32010-07-25 22:30:20 +02001945#if defined(FEAT_XFONTSET) || defined(FEAT_MBYTE)
1946 if (text_prop.encoding == XA_STRING
1947# ifdef FEAT_MBYTE
1948 && !has_mbyte
1949# endif
1950 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00001951 {
1952#endif
1953 if (get_title)
1954 oldtitle = vim_strsave((char_u *)text_prop.value);
1955 else
1956 oldicon = vim_strsave((char_u *)text_prop.value);
Bram Moolenaarf82bac32010-07-25 22:30:20 +02001957#if defined(FEAT_XFONTSET) || defined(FEAT_MBYTE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001958 }
1959 else
1960 {
1961 char **cl;
1962 Status transform_status;
1963 int n = 0;
1964
1965 transform_status = XmbTextPropertyToTextList(x11_display,
1966 &text_prop,
1967 &cl, &n);
1968 if (transform_status >= Success && n > 0 && cl[0])
1969 {
1970 if (get_title)
1971 oldtitle = vim_strsave((char_u *) cl[0]);
1972 else
1973 oldicon = vim_strsave((char_u *) cl[0]);
1974 XFreeStringList(cl);
1975 }
1976 else
1977 {
1978 if (get_title)
1979 oldtitle = vim_strsave((char_u *)text_prop.value);
1980 else
1981 oldicon = vim_strsave((char_u *)text_prop.value);
1982 }
1983 }
1984#endif
1985 }
1986 XFree((void *)text_prop.value);
1987 }
1988 }
1989 return retval;
1990}
1991
Bram Moolenaarcbc246a2014-10-11 14:47:26 +02001992/* Xutf8 functions are not avaialble on older systems. Note that on some
1993 * systems X_HAVE_UTF8_STRING may be defined in a header file but
1994 * Xutf8SetWMProperties() is not in the X11 library. Configure checks for
1995 * that and defines HAVE_XUTF8SETWMPROPERTIES. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001996#if defined(X_HAVE_UTF8_STRING) && defined(FEAT_MBYTE)
Bram Moolenaarcbc246a2014-10-11 14:47:26 +02001997# if X_HAVE_UTF8_STRING && HAVE_XUTF8SETWMPROPERTIES
Bram Moolenaar071d4272004-06-13 20:20:40 +00001998# define USE_UTF8_STRING
1999# endif
2000#endif
2001
2002/*
2003 * Set x11 Window Title
2004 *
2005 * get_x11_windis() must be called before this and have returned OK
2006 */
2007 static void
2008set_x11_title(title)
2009 char_u *title;
2010{
2011 /* XmbSetWMProperties() and Xutf8SetWMProperties() should use a STRING
2012 * when possible, COMPOUND_TEXT otherwise. COMPOUND_TEXT isn't
2013 * supported everywhere and STRING doesn't work for multi-byte titles.
2014 */
2015#ifdef USE_UTF8_STRING
2016 if (enc_utf8)
2017 Xutf8SetWMProperties(x11_display, x11_window, (const char *)title,
2018 NULL, NULL, 0, NULL, NULL, NULL);
2019 else
2020#endif
2021 {
2022#if XtSpecificationRelease >= 4
2023# ifdef FEAT_XFONTSET
2024 XmbSetWMProperties(x11_display, x11_window, (const char *)title,
2025 NULL, NULL, 0, NULL, NULL, NULL);
2026# else
2027 XTextProperty text_prop;
Bram Moolenaar9d75c832005-01-25 21:57:23 +00002028 char *c_title = (char *)title;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002029
2030 /* directly from example 3-18 "basicwin" of Xlib Programming Manual */
Bram Moolenaar9d75c832005-01-25 21:57:23 +00002031 (void)XStringListToTextProperty(&c_title, 1, &text_prop);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002032 XSetWMProperties(x11_display, x11_window, &text_prop,
2033 NULL, NULL, 0, NULL, NULL, NULL);
2034# endif
2035#else
2036 XStoreName(x11_display, x11_window, (char *)title);
2037#endif
2038 }
2039 XFlush(x11_display);
2040}
2041
2042/*
2043 * Set x11 Window icon
2044 *
2045 * get_x11_windis() must be called before this and have returned OK
2046 */
2047 static void
2048set_x11_icon(icon)
2049 char_u *icon;
2050{
2051 /* See above for comments about using X*SetWMProperties(). */
2052#ifdef USE_UTF8_STRING
2053 if (enc_utf8)
2054 Xutf8SetWMProperties(x11_display, x11_window, NULL, (const char *)icon,
2055 NULL, 0, NULL, NULL, NULL);
2056 else
2057#endif
2058 {
2059#if XtSpecificationRelease >= 4
2060# ifdef FEAT_XFONTSET
2061 XmbSetWMProperties(x11_display, x11_window, NULL, (const char *)icon,
2062 NULL, 0, NULL, NULL, NULL);
2063# else
2064 XTextProperty text_prop;
Bram Moolenaar9d75c832005-01-25 21:57:23 +00002065 char *c_icon = (char *)icon;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002066
Bram Moolenaar9d75c832005-01-25 21:57:23 +00002067 (void)XStringListToTextProperty(&c_icon, 1, &text_prop);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002068 XSetWMProperties(x11_display, x11_window, NULL, &text_prop,
2069 NULL, 0, NULL, NULL, NULL);
2070# endif
2071#else
2072 XSetIconName(x11_display, x11_window, (char *)icon);
2073#endif
2074 }
2075 XFlush(x11_display);
2076}
2077
2078#else /* FEAT_X11 */
2079
Bram Moolenaar071d4272004-06-13 20:20:40 +00002080 static int
2081get_x11_title(test_only)
Bram Moolenaar2c4278f2009-05-17 11:33:22 +00002082 int test_only UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002083{
2084 return FALSE;
2085}
2086
2087 static int
2088get_x11_icon(test_only)
2089 int test_only;
2090{
2091 if (!test_only)
2092 {
2093 if (STRNCMP(T_NAME, "builtin_", 8) == 0)
Bram Moolenaar20de1c22009-07-22 11:28:11 +00002094 oldicon = vim_strsave(T_NAME + 8);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002095 else
Bram Moolenaar20de1c22009-07-22 11:28:11 +00002096 oldicon = vim_strsave(T_NAME);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002097 }
2098 return FALSE;
2099}
2100
2101#endif /* FEAT_X11 */
2102
2103 int
2104mch_can_restore_title()
2105{
2106 return get_x11_title(TRUE);
2107}
2108
2109 int
2110mch_can_restore_icon()
2111{
2112 return get_x11_icon(TRUE);
2113}
2114
2115/*
2116 * Set the window title and icon.
2117 */
2118 void
2119mch_settitle(title, icon)
2120 char_u *title;
2121 char_u *icon;
2122{
2123 int type = 0;
2124 static int recursive = 0;
2125
2126 if (T_NAME == NULL) /* no terminal name (yet) */
2127 return;
2128 if (title == NULL && icon == NULL) /* nothing to do */
2129 return;
2130
2131 /* When one of the X11 functions causes a deadly signal, we get here again
2132 * recursively. Avoid hanging then (something is probably locked). */
2133 if (recursive)
2134 return;
2135 ++recursive;
2136
2137 /*
2138 * if the window ID and the display is known, we may use X11 calls
2139 */
2140#ifdef FEAT_X11
2141 if (get_x11_windis() == OK)
2142 type = 1;
2143#else
2144# if defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_GTK)
2145 if (gui.in_use)
2146 type = 1;
2147# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002148#endif
2149
2150 /*
Bram Moolenaarf82bac32010-07-25 22:30:20 +02002151 * Note: if "t_ts" is set, title is set with escape sequence rather
Bram Moolenaar071d4272004-06-13 20:20:40 +00002152 * than x11 calls, because the x11 calls don't always work
2153 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002154 if ((type || *T_TS != NUL) && title != NULL)
2155 {
2156 if (oldtitle == NULL
2157#ifdef FEAT_GUI
2158 && !gui.in_use
2159#endif
2160 ) /* first call but not in GUI, save title */
2161 (void)get_x11_title(FALSE);
2162
2163 if (*T_TS != NUL) /* it's OK if t_fs is empty */
2164 term_settitle(title);
2165#ifdef FEAT_X11
2166 else
2167# ifdef FEAT_GUI_GTK
2168 if (!gui.in_use) /* don't do this if GTK+ is running */
2169# endif
2170 set_x11_title(title); /* x11 */
2171#endif
Bram Moolenaar2fa15e62005-01-04 21:23:48 +00002172#if defined(FEAT_GUI_GTK) \
Bram Moolenaar071d4272004-06-13 20:20:40 +00002173 || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC)
2174 else
2175 gui_mch_settitle(title, icon);
2176#endif
2177 did_set_title = TRUE;
2178 }
2179
2180 if ((type || *T_CIS != NUL) && icon != NULL)
2181 {
2182 if (oldicon == NULL
2183#ifdef FEAT_GUI
2184 && !gui.in_use
2185#endif
2186 ) /* first call, save icon */
2187 get_x11_icon(FALSE);
2188
2189 if (*T_CIS != NUL)
2190 {
2191 out_str(T_CIS); /* set icon start */
2192 out_str_nf(icon);
2193 out_str(T_CIE); /* set icon end */
2194 out_flush();
2195 }
2196#ifdef FEAT_X11
2197 else
2198# ifdef FEAT_GUI_GTK
2199 if (!gui.in_use) /* don't do this if GTK+ is running */
2200# endif
2201 set_x11_icon(icon); /* x11 */
2202#endif
2203 did_set_icon = TRUE;
2204 }
2205 --recursive;
2206}
2207
2208/*
2209 * Restore the window/icon title.
2210 * "which" is one of:
2211 * 1 only restore title
2212 * 2 only restore icon
2213 * 3 restore title and icon
2214 */
2215 void
2216mch_restore_title(which)
2217 int which;
2218{
2219 /* only restore the title or icon when it has been set */
2220 mch_settitle(((which & 1) && did_set_title) ?
2221 (oldtitle ? oldtitle : p_titleold) : NULL,
2222 ((which & 2) && did_set_icon) ? oldicon : NULL);
2223}
2224
2225#endif /* FEAT_TITLE */
2226
2227/*
2228 * Return TRUE if "name" looks like some xterm name.
Bram Moolenaar3a7c85b2005-02-05 21:39:53 +00002229 * Seiichi Sato mentioned that "mlterm" works like xterm.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002230 */
2231 int
2232vim_is_xterm(name)
2233 char_u *name;
2234{
2235 if (name == NULL)
2236 return FALSE;
2237 return (STRNICMP(name, "xterm", 5) == 0
2238 || STRNICMP(name, "nxterm", 6) == 0
2239 || STRNICMP(name, "kterm", 5) == 0
Bram Moolenaar3a7c85b2005-02-05 21:39:53 +00002240 || STRNICMP(name, "mlterm", 6) == 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00002241 || STRNICMP(name, "rxvt", 4) == 0
2242 || STRCMP(name, "builtin_xterm") == 0);
2243}
2244
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00002245#if defined(FEAT_MOUSE_XTERM) || defined(PROTO)
2246/*
2247 * Return TRUE if "name" appears to be that of a terminal
2248 * known to support the xterm-style mouse protocol.
2249 * Relies on term_is_xterm having been set to its correct value.
2250 */
2251 int
2252use_xterm_like_mouse(name)
2253 char_u *name;
2254{
2255 return (name != NULL
2256 && (term_is_xterm || STRNICMP(name, "screen", 6) == 0));
2257}
2258#endif
2259
Bram Moolenaar071d4272004-06-13 20:20:40 +00002260#if defined(FEAT_MOUSE_TTY) || defined(PROTO)
2261/*
2262 * Return non-zero when using an xterm mouse, according to 'ttymouse'.
2263 * Return 1 for "xterm".
2264 * Return 2 for "xterm2".
Bram Moolenaarc8427482011-10-20 21:09:35 +02002265 * Return 3 for "urxvt".
Bram Moolenaar2b9578f2012-08-15 16:21:32 +02002266 * Return 4 for "sgr".
Bram Moolenaar071d4272004-06-13 20:20:40 +00002267 */
2268 int
2269use_xterm_mouse()
2270{
Bram Moolenaar2b9578f2012-08-15 16:21:32 +02002271 if (ttym_flags == TTYM_SGR)
2272 return 4;
Bram Moolenaarc8427482011-10-20 21:09:35 +02002273 if (ttym_flags == TTYM_URXVT)
2274 return 3;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002275 if (ttym_flags == TTYM_XTERM2)
2276 return 2;
2277 if (ttym_flags == TTYM_XTERM)
2278 return 1;
2279 return 0;
2280}
2281#endif
2282
2283 int
2284vim_is_iris(name)
2285 char_u *name;
2286{
2287 if (name == NULL)
2288 return FALSE;
2289 return (STRNICMP(name, "iris-ansi", 9) == 0
2290 || STRCMP(name, "builtin_iris-ansi") == 0);
2291}
2292
2293 int
2294vim_is_vt300(name)
2295 char_u *name;
2296{
2297 if (name == NULL)
2298 return FALSE; /* actually all ANSI comp. terminals should be here */
Bram Moolenaard4755bb2004-09-02 19:12:26 +00002299 /* catch VT100 - VT5xx */
2300 return ((STRNICMP(name, "vt", 2) == 0
2301 && vim_strchr((char_u *)"12345", name[2]) != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002302 || STRCMP(name, "builtin_vt320") == 0);
2303}
2304
2305/*
2306 * Return TRUE if "name" is a terminal for which 'ttyfast' should be set.
2307 * This should include all windowed terminal emulators.
2308 */
2309 int
2310vim_is_fastterm(name)
2311 char_u *name;
2312{
2313 if (name == NULL)
2314 return FALSE;
2315 if (vim_is_xterm(name) || vim_is_vt300(name) || vim_is_iris(name))
2316 return TRUE;
2317 return ( STRNICMP(name, "hpterm", 6) == 0
2318 || STRNICMP(name, "sun-cmd", 7) == 0
2319 || STRNICMP(name, "screen", 6) == 0
2320 || STRNICMP(name, "dtterm", 6) == 0);
2321}
2322
2323/*
2324 * Insert user name in s[len].
2325 * Return OK if a name found.
2326 */
2327 int
2328mch_get_user_name(s, len)
2329 char_u *s;
2330 int len;
2331{
2332#ifdef VMS
Bram Moolenaarffb8ab02005-09-07 21:15:32 +00002333 vim_strncpy(s, (char_u *)cuserid(NULL), len - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002334 return OK;
2335#else
2336 return mch_get_uname(getuid(), s, len);
2337#endif
2338}
2339
2340/*
2341 * Insert user name for "uid" in s[len].
2342 * Return OK if a name found.
2343 */
2344 int
2345mch_get_uname(uid, s, len)
2346 uid_t uid;
2347 char_u *s;
2348 int len;
2349{
2350#if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
2351 struct passwd *pw;
2352
2353 if ((pw = getpwuid(uid)) != NULL
2354 && pw->pw_name != NULL && *(pw->pw_name) != NUL)
2355 {
Bram Moolenaarbbebc852005-07-18 21:47:53 +00002356 vim_strncpy(s, (char_u *)pw->pw_name, len - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002357 return OK;
2358 }
2359#endif
2360 sprintf((char *)s, "%d", (int)uid); /* assumes s is long enough */
2361 return FAIL; /* a number is not a name */
2362}
2363
2364/*
2365 * Insert host name is s[len].
2366 */
2367
2368#ifdef HAVE_SYS_UTSNAME_H
2369 void
2370mch_get_host_name(s, len)
2371 char_u *s;
2372 int len;
2373{
2374 struct utsname vutsname;
2375
2376 if (uname(&vutsname) < 0)
2377 *s = NUL;
2378 else
Bram Moolenaarbbebc852005-07-18 21:47:53 +00002379 vim_strncpy(s, (char_u *)vutsname.nodename, len - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002380}
2381#else /* HAVE_SYS_UTSNAME_H */
2382
2383# ifdef HAVE_SYS_SYSTEMINFO_H
2384# define gethostname(nam, len) sysinfo(SI_HOSTNAME, nam, len)
2385# endif
2386
2387 void
2388mch_get_host_name(s, len)
2389 char_u *s;
2390 int len;
2391{
2392# ifdef VAXC
2393 vaxc$gethostname((char *)s, len);
2394# else
2395 gethostname((char *)s, len);
2396# endif
2397 s[len - 1] = NUL; /* make sure it's terminated */
2398}
2399#endif /* HAVE_SYS_UTSNAME_H */
2400
2401/*
2402 * return process ID
2403 */
2404 long
2405mch_get_pid()
2406{
2407 return (long)getpid();
2408}
2409
2410#if !defined(HAVE_STRERROR) && defined(USE_GETCWD)
2411static char *strerror __ARGS((int));
2412
2413 static char *
2414strerror(err)
2415 int err;
2416{
2417 extern int sys_nerr;
2418 extern char *sys_errlist[];
2419 static char er[20];
2420
2421 if (err > 0 && err < sys_nerr)
2422 return (sys_errlist[err]);
2423 sprintf(er, "Error %d", err);
2424 return er;
2425}
2426#endif
2427
2428/*
2429 * Get name of current directory into buffer 'buf' of length 'len' bytes.
2430 * Return OK for success, FAIL for failure.
2431 */
2432 int
2433mch_dirname(buf, len)
2434 char_u *buf;
2435 int len;
2436{
2437#if defined(USE_GETCWD)
2438 if (getcwd((char *)buf, len) == NULL)
2439 {
2440 STRCPY(buf, strerror(errno));
2441 return FAIL;
2442 }
2443 return OK;
2444#else
2445 return (getwd((char *)buf) != NULL ? OK : FAIL);
2446#endif
2447}
2448
2449#if defined(OS2) || defined(PROTO)
2450/*
2451 * Replace all slashes by backslashes.
2452 * When 'shellslash' set do it the other way around.
2453 */
2454 void
2455slash_adjust(p)
2456 char_u *p;
2457{
2458 while (*p)
2459 {
2460 if (*p == psepcN)
2461 *p = psepc;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00002462 mb_ptr_adv(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002463 }
2464}
2465#endif
2466
2467/*
Bram Moolenaar3d20ca12006-11-28 16:43:58 +00002468 * Get absolute file name into "buf[len]".
Bram Moolenaar071d4272004-06-13 20:20:40 +00002469 *
2470 * return FAIL for failure, OK for success
2471 */
2472 int
2473mch_FullName(fname, buf, len, force)
2474 char_u *fname, *buf;
2475 int len;
2476 int force; /* also expand when already absolute path */
2477{
2478 int l;
Bram Moolenaar38323e42007-03-06 19:22:53 +00002479#ifdef OS2
Bram Moolenaar071d4272004-06-13 20:20:40 +00002480 int only_drive; /* file name is only a drive letter */
Bram Moolenaar38323e42007-03-06 19:22:53 +00002481#endif
2482#ifdef HAVE_FCHDIR
Bram Moolenaar071d4272004-06-13 20:20:40 +00002483 int fd = -1;
2484 static int dont_fchdir = FALSE; /* TRUE when fchdir() doesn't work */
Bram Moolenaar38323e42007-03-06 19:22:53 +00002485#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002486 char_u olddir[MAXPATHL];
2487 char_u *p;
2488 int retval = OK;
Bram Moolenaarbf820722008-06-21 11:12:49 +00002489#ifdef __CYGWIN__
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00002490 char_u posix_fname[MAXPATHL]; /* Cygwin docs mention MAX_PATH, but
2491 it's not always defined */
Bram Moolenaarbf820722008-06-21 11:12:49 +00002492#endif
2493
Bram Moolenaar38323e42007-03-06 19:22:53 +00002494#ifdef VMS
2495 fname = vms_fixfilename(fname);
2496#endif
2497
Bram Moolenaara2442432007-04-26 14:26:37 +00002498#ifdef __CYGWIN__
2499 /*
2500 * This helps for when "/etc/hosts" is a symlink to "c:/something/hosts".
2501 */
Bram Moolenaar0d1498e2008-06-29 12:00:49 +00002502# if CYGWIN_VERSION_DLL_MAJOR >= 1007
2503 cygwin_conv_path(CCP_WIN_A_TO_POSIX, fname, posix_fname, MAXPATHL);
2504# else
Bram Moolenaarbf820722008-06-21 11:12:49 +00002505 cygwin_conv_to_posix_path(fname, posix_fname);
Bram Moolenaar0d1498e2008-06-29 12:00:49 +00002506# endif
Bram Moolenaarbf820722008-06-21 11:12:49 +00002507 fname = posix_fname;
Bram Moolenaara2442432007-04-26 14:26:37 +00002508#endif
2509
Bram Moolenaar071d4272004-06-13 20:20:40 +00002510 /* expand it if forced or not an absolute path */
2511 if (force || !mch_isFullName(fname))
2512 {
2513 /*
2514 * If the file name has a path, change to that directory for a moment,
2515 * and then do the getwd() (and get back to where we were).
2516 * This will get the correct path name with "../" things.
2517 */
Bram Moolenaar38323e42007-03-06 19:22:53 +00002518#ifdef OS2
Bram Moolenaar071d4272004-06-13 20:20:40 +00002519 only_drive = 0;
2520 if (((p = vim_strrchr(fname, '/')) != NULL)
2521 || ((p = vim_strrchr(fname, '\\')) != NULL)
2522 || (((p = vim_strchr(fname, ':')) != NULL) && ++only_drive))
Bram Moolenaar38323e42007-03-06 19:22:53 +00002523#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002524 if ((p = vim_strrchr(fname, '/')) != NULL)
Bram Moolenaar38323e42007-03-06 19:22:53 +00002525#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002526 {
Bram Moolenaar38323e42007-03-06 19:22:53 +00002527#ifdef HAVE_FCHDIR
Bram Moolenaar071d4272004-06-13 20:20:40 +00002528 /*
2529 * Use fchdir() if possible, it's said to be faster and more
2530 * reliable. But on SunOS 4 it might not work. Check this by
2531 * doing a fchdir() right now.
2532 */
2533 if (!dont_fchdir)
2534 {
2535 fd = open(".", O_RDONLY | O_EXTRA, 0);
2536 if (fd >= 0 && fchdir(fd) < 0)
2537 {
2538 close(fd);
2539 fd = -1;
2540 dont_fchdir = TRUE; /* don't try again */
2541 }
2542 }
Bram Moolenaar38323e42007-03-06 19:22:53 +00002543#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002544
2545 /* Only change directory when we are sure we can return to where
2546 * we are now. After doing "su" chdir(".") might not work. */
2547 if (
Bram Moolenaar38323e42007-03-06 19:22:53 +00002548#ifdef HAVE_FCHDIR
Bram Moolenaar071d4272004-06-13 20:20:40 +00002549 fd < 0 &&
Bram Moolenaar38323e42007-03-06 19:22:53 +00002550#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002551 (mch_dirname(olddir, MAXPATHL) == FAIL
2552 || mch_chdir((char *)olddir) != 0))
2553 {
2554 p = NULL; /* can't get current dir: don't chdir */
2555 retval = FAIL;
2556 }
2557 else
2558 {
Bram Moolenaar38323e42007-03-06 19:22:53 +00002559#ifdef OS2
Bram Moolenaar071d4272004-06-13 20:20:40 +00002560 /*
2561 * compensate for case where ':' from "D:" was the only
2562 * path separator detected in the file name; the _next_
2563 * character has to be removed, and then restored later.
2564 */
2565 if (only_drive)
2566 p++;
Bram Moolenaar38323e42007-03-06 19:22:53 +00002567#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002568 /* The directory is copied into buf[], to be able to remove
2569 * the file name without changing it (could be a string in
2570 * read-only memory) */
2571 if (p - fname >= len)
2572 retval = FAIL;
2573 else
2574 {
Bram Moolenaarbbebc852005-07-18 21:47:53 +00002575 vim_strncpy(buf, fname, p - fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002576 if (mch_chdir((char *)buf))
2577 retval = FAIL;
2578 else
2579 fname = p + 1;
2580 *buf = NUL;
2581 }
Bram Moolenaar38323e42007-03-06 19:22:53 +00002582#ifdef OS2
Bram Moolenaar071d4272004-06-13 20:20:40 +00002583 if (only_drive)
2584 {
2585 p--;
2586 if (retval != FAIL)
2587 fname--;
2588 }
Bram Moolenaar38323e42007-03-06 19:22:53 +00002589#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002590 }
2591 }
2592 if (mch_dirname(buf, len) == FAIL)
2593 {
2594 retval = FAIL;
2595 *buf = NUL;
2596 }
2597 if (p != NULL)
2598 {
Bram Moolenaar38323e42007-03-06 19:22:53 +00002599#ifdef HAVE_FCHDIR
Bram Moolenaar071d4272004-06-13 20:20:40 +00002600 if (fd >= 0)
2601 {
Bram Moolenaar25724922009-07-14 15:38:41 +00002602 if (p_verbose >= 5)
2603 {
2604 verbose_enter();
2605 MSG("fchdir() to previous dir");
2606 verbose_leave();
2607 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002608 l = fchdir(fd);
2609 close(fd);
2610 }
2611 else
Bram Moolenaar38323e42007-03-06 19:22:53 +00002612#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002613 l = mch_chdir((char *)olddir);
2614 if (l != 0)
2615 EMSG(_(e_prev_dir));
2616 }
2617
2618 l = STRLEN(buf);
Bram Moolenaardac75692012-10-14 04:35:45 +02002619 if (l >= len - 1)
2620 retval = FAIL; /* no space for trailing "/" */
Bram Moolenaar38323e42007-03-06 19:22:53 +00002621#ifndef VMS
Bram Moolenaardac75692012-10-14 04:35:45 +02002622 else if (l > 0 && buf[l - 1] != '/' && *fname != NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +00002623 && STRCMP(fname, ".") != 0)
Bram Moolenaardac75692012-10-14 04:35:45 +02002624 STRCAT(buf, "/");
Bram Moolenaar38323e42007-03-06 19:22:53 +00002625#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002626 }
Bram Moolenaar3d20ca12006-11-28 16:43:58 +00002627
Bram Moolenaar071d4272004-06-13 20:20:40 +00002628 /* Catch file names which are too long. */
Bram Moolenaar78a15312009-05-15 19:33:18 +00002629 if (retval == FAIL || (int)(STRLEN(buf) + STRLEN(fname)) >= len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002630 return FAIL;
2631
2632 /* Do not append ".", "/dir/." is equal to "/dir". */
2633 if (STRCMP(fname, ".") != 0)
2634 STRCAT(buf, fname);
2635
2636 return OK;
2637}
2638
2639/*
2640 * Return TRUE if "fname" does not depend on the current directory.
2641 */
2642 int
2643mch_isFullName(fname)
2644 char_u *fname;
2645{
2646#ifdef __EMX__
2647 return _fnisabs(fname);
2648#else
2649# ifdef VMS
2650 return ( fname[0] == '/' || fname[0] == '.' ||
2651 strchr((char *)fname,':') || strchr((char *)fname,'"') ||
2652 (strchr((char *)fname,'[') && strchr((char *)fname,']'))||
2653 (strchr((char *)fname,'<') && strchr((char *)fname,'>')) );
2654# else
2655 return (*fname == '/' || *fname == '~');
2656# endif
2657#endif
2658}
2659
Bram Moolenaar24552be2005-12-10 20:17:30 +00002660#if defined(USE_FNAME_CASE) || defined(PROTO)
2661/*
2662 * Set the case of the file name, if it already exists. This will cause the
2663 * file name to remain exactly the same.
Bram Moolenaarc2a27c32007-12-01 16:19:33 +00002664 * Only required for file systems where case is ignored and preserved.
Bram Moolenaar24552be2005-12-10 20:17:30 +00002665 */
Bram Moolenaar24552be2005-12-10 20:17:30 +00002666 void
2667fname_case(name, len)
2668 char_u *name;
Bram Moolenaar2c4278f2009-05-17 11:33:22 +00002669 int len UNUSED; /* buffer size, only used when name gets longer */
Bram Moolenaar24552be2005-12-10 20:17:30 +00002670{
2671 struct stat st;
2672 char_u *slash, *tail;
2673 DIR *dirp;
2674 struct dirent *dp;
2675
2676 if (lstat((char *)name, &st) >= 0)
2677 {
2678 /* Open the directory where the file is located. */
2679 slash = vim_strrchr(name, '/');
2680 if (slash == NULL)
2681 {
2682 dirp = opendir(".");
2683 tail = name;
2684 }
2685 else
2686 {
2687 *slash = NUL;
2688 dirp = opendir((char *)name);
2689 *slash = '/';
2690 tail = slash + 1;
2691 }
2692
2693 if (dirp != NULL)
2694 {
2695 while ((dp = readdir(dirp)) != NULL)
2696 {
2697 /* Only accept names that differ in case and are the same byte
2698 * length. TODO: accept different length name. */
2699 if (STRICMP(tail, dp->d_name) == 0
2700 && STRLEN(tail) == STRLEN(dp->d_name))
2701 {
2702 char_u newname[MAXPATHL + 1];
2703 struct stat st2;
2704
2705 /* Verify the inode is equal. */
2706 vim_strncpy(newname, name, MAXPATHL);
2707 vim_strncpy(newname + (tail - name), (char_u *)dp->d_name,
2708 MAXPATHL - (tail - name));
2709 if (lstat((char *)newname, &st2) >= 0
2710 && st.st_ino == st2.st_ino
2711 && st.st_dev == st2.st_dev)
2712 {
2713 STRCPY(tail, dp->d_name);
2714 break;
2715 }
2716 }
2717 }
2718
2719 closedir(dirp);
2720 }
2721 }
2722}
2723#endif
2724
Bram Moolenaar071d4272004-06-13 20:20:40 +00002725/*
2726 * Get file permissions for 'name'.
2727 * Returns -1 when it doesn't exist.
2728 */
2729 long
2730mch_getperm(name)
2731 char_u *name;
2732{
2733 struct stat statb;
2734
2735 /* Keep the #ifdef outside of stat(), it may be a macro. */
2736#ifdef VMS
2737 if (stat((char *)vms_fixfilename(name), &statb))
2738#else
2739 if (stat((char *)name, &statb))
2740#endif
2741 return -1;
Bram Moolenaar708f62c2007-08-11 20:24:10 +00002742#ifdef __INTERIX
2743 /* The top bit makes the value negative, which means the file doesn't
2744 * exist. Remove the bit, we don't use it. */
2745 return statb.st_mode & ~S_ADDACE;
2746#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002747 return statb.st_mode;
Bram Moolenaar708f62c2007-08-11 20:24:10 +00002748#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002749}
2750
2751/*
2752 * set file permission for 'name' to 'perm'
2753 *
2754 * return FAIL for failure, OK otherwise
2755 */
2756 int
2757mch_setperm(name, perm)
2758 char_u *name;
2759 long perm;
2760{
2761 return (chmod((char *)
2762#ifdef VMS
2763 vms_fixfilename(name),
2764#else
2765 name,
2766#endif
2767 (mode_t)perm) == 0 ? OK : FAIL);
2768}
2769
2770#if defined(HAVE_ACL) || defined(PROTO)
2771# ifdef HAVE_SYS_ACL_H
2772# include <sys/acl.h>
2773# endif
2774# ifdef HAVE_SYS_ACCESS_H
2775# include <sys/access.h>
2776# endif
2777
2778# ifdef HAVE_SOLARIS_ACL
2779typedef struct vim_acl_solaris_T {
2780 int acl_cnt;
2781 aclent_t *acl_entry;
2782} vim_acl_solaris_T;
2783# endif
2784
Bram Moolenaar588ebeb2008-05-07 17:09:24 +00002785#if defined(HAVE_SELINUX) || defined(PROTO)
2786/*
2787 * Copy security info from "from_file" to "to_file".
2788 */
2789 void
2790mch_copy_sec(from_file, to_file)
2791 char_u *from_file;
2792 char_u *to_file;
2793{
2794 if (from_file == NULL)
2795 return;
2796
2797 if (selinux_enabled == -1)
2798 selinux_enabled = is_selinux_enabled();
2799
2800 if (selinux_enabled > 0)
2801 {
2802 security_context_t from_context = NULL;
2803 security_context_t to_context = NULL;
2804
2805 if (getfilecon((char *)from_file, &from_context) < 0)
2806 {
2807 /* If the filesystem doesn't support extended attributes,
2808 the original had no special security context and the
2809 target cannot have one either. */
2810 if (errno == EOPNOTSUPP)
2811 return;
2812
2813 MSG_PUTS(_("\nCould not get security context for "));
2814 msg_outtrans(from_file);
2815 msg_putchar('\n');
2816 return;
2817 }
2818 if (getfilecon((char *)to_file, &to_context) < 0)
2819 {
2820 MSG_PUTS(_("\nCould not get security context for "));
2821 msg_outtrans(to_file);
2822 msg_putchar('\n');
2823 freecon (from_context);
2824 return ;
2825 }
2826 if (strcmp(from_context, to_context) != 0)
2827 {
2828 if (setfilecon((char *)to_file, from_context) < 0)
2829 {
2830 MSG_PUTS(_("\nCould not set security context for "));
2831 msg_outtrans(to_file);
2832 msg_putchar('\n');
2833 }
2834 }
2835 freecon(to_context);
2836 freecon(from_context);
2837 }
2838}
2839#endif /* HAVE_SELINUX */
2840
Bram Moolenaar5bd32f42014-04-02 14:05:38 +02002841#if defined(HAVE_SMACK) && !defined(PROTO)
2842/*
2843 * Copy security info from "from_file" to "to_file".
2844 */
2845 void
2846mch_copy_sec(from_file, to_file)
2847 char_u *from_file;
2848 char_u *to_file;
2849{
Bram Moolenaar62f167f2014-04-23 12:52:40 +02002850 static const char * const smack_copied_attributes[] =
Bram Moolenaar5bd32f42014-04-02 14:05:38 +02002851 {
2852 XATTR_NAME_SMACK,
2853 XATTR_NAME_SMACKEXEC,
2854 XATTR_NAME_SMACKMMAP
2855 };
2856
2857 char buffer[SMACK_LABEL_LEN];
2858 const char *name;
2859 int index;
2860 int ret;
2861 ssize_t size;
2862
2863 if (from_file == NULL)
2864 return;
2865
2866 for (index = 0 ; index < (int)(sizeof(smack_copied_attributes)
2867 / sizeof(smack_copied_attributes)[0]) ; index++)
2868 {
2869 /* get the name of the attribute to copy */
2870 name = smack_copied_attributes[index];
2871
2872 /* get the value of the attribute in buffer */
2873 size = getxattr((char*)from_file, name, buffer, sizeof(buffer));
2874 if (size >= 0)
2875 {
2876 /* copy the attribute value of buffer */
2877 ret = setxattr((char*)to_file, name, buffer, (size_t)size, 0);
2878 if (ret < 0)
2879 {
2880 MSG_PUTS(_("Could not set security context "));
2881 MSG_PUTS(name);
2882 MSG_PUTS(_(" for "));
2883 msg_outtrans(to_file);
2884 msg_putchar('\n');
2885 }
2886 }
2887 else
2888 {
2889 /* what reason of not having the attribute value? */
2890 switch (errno)
2891 {
2892 case ENOTSUP:
2893 /* extended attributes aren't supported or enabled */
2894 /* should a message be echoed? not sure... */
2895 return; /* leave because it isn't usefull to continue */
2896
2897 case ERANGE:
2898 default:
2899 /* no enough size OR unexpected error */
2900 MSG_PUTS(_("Could not get security context "));
2901 MSG_PUTS(name);
2902 MSG_PUTS(_(" for "));
2903 msg_outtrans(from_file);
2904 MSG_PUTS(_(". Removing it!\n"));
2905 /* FALLTHROUGH to remove the attribute */
2906
2907 case ENODATA:
2908 /* no attribute of this name */
2909 ret = removexattr((char*)to_file, name);
Bram Moolenaar57a728d2014-04-02 23:09:26 +02002910 /* Silently ignore errors, apparently this happens when
2911 * smack is not actually being used. */
Bram Moolenaar5bd32f42014-04-02 14:05:38 +02002912 break;
2913 }
2914 }
2915 }
2916}
2917#endif /* HAVE_SMACK */
2918
Bram Moolenaar071d4272004-06-13 20:20:40 +00002919/*
2920 * Return a pointer to the ACL of file "fname" in allocated memory.
2921 * Return NULL if the ACL is not available for whatever reason.
2922 */
2923 vim_acl_T
2924mch_get_acl(fname)
Bram Moolenaar78a15312009-05-15 19:33:18 +00002925 char_u *fname UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002926{
2927 vim_acl_T ret = NULL;
2928#ifdef HAVE_POSIX_ACL
2929 ret = (vim_acl_T)acl_get_file((char *)fname, ACL_TYPE_ACCESS);
2930#else
Bram Moolenaar8d462f92012-02-05 22:51:33 +01002931#ifdef HAVE_SOLARIS_ZFS_ACL
2932 acl_t *aclent;
2933
2934 if (acl_get((char *)fname, 0, &aclent) < 0)
2935 return NULL;
2936 ret = (vim_acl_T)aclent;
2937#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002938#ifdef HAVE_SOLARIS_ACL
2939 vim_acl_solaris_T *aclent;
2940
2941 aclent = malloc(sizeof(vim_acl_solaris_T));
2942 if ((aclent->acl_cnt = acl((char *)fname, GETACLCNT, 0, NULL)) < 0)
2943 {
2944 free(aclent);
2945 return NULL;
2946 }
2947 aclent->acl_entry = malloc(aclent->acl_cnt * sizeof(aclent_t));
2948 if (acl((char *)fname, GETACL, aclent->acl_cnt, aclent->acl_entry) < 0)
2949 {
2950 free(aclent->acl_entry);
2951 free(aclent);
2952 return NULL;
2953 }
2954 ret = (vim_acl_T)aclent;
2955#else
2956#if defined(HAVE_AIX_ACL)
2957 int aclsize;
2958 struct acl *aclent;
2959
2960 aclsize = sizeof(struct acl);
2961 aclent = malloc(aclsize);
2962 if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
2963 {
2964 if (errno == ENOSPC)
2965 {
2966 aclsize = aclent->acl_len;
2967 aclent = realloc(aclent, aclsize);
2968 if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
2969 {
2970 free(aclent);
2971 return NULL;
2972 }
2973 }
2974 else
2975 {
2976 free(aclent);
2977 return NULL;
2978 }
2979 }
2980 ret = (vim_acl_T)aclent;
2981#endif /* HAVE_AIX_ACL */
2982#endif /* HAVE_SOLARIS_ACL */
Bram Moolenaar8d462f92012-02-05 22:51:33 +01002983#endif /* HAVE_SOLARIS_ZFS_ACL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002984#endif /* HAVE_POSIX_ACL */
2985 return ret;
2986}
2987
2988/*
2989 * Set the ACL of file "fname" to "acl" (unless it's NULL).
2990 */
2991 void
2992mch_set_acl(fname, aclent)
Bram Moolenaar78a15312009-05-15 19:33:18 +00002993 char_u *fname UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002994 vim_acl_T aclent;
2995{
2996 if (aclent == NULL)
2997 return;
2998#ifdef HAVE_POSIX_ACL
2999 acl_set_file((char *)fname, ACL_TYPE_ACCESS, (acl_t)aclent);
3000#else
Bram Moolenaar8d462f92012-02-05 22:51:33 +01003001#ifdef HAVE_SOLARIS_ZFS_ACL
3002 acl_set((char *)fname, (acl_t *)aclent);
3003#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00003004#ifdef HAVE_SOLARIS_ACL
3005 acl((char *)fname, SETACL, ((vim_acl_solaris_T *)aclent)->acl_cnt,
3006 ((vim_acl_solaris_T *)aclent)->acl_entry);
3007#else
3008#ifdef HAVE_AIX_ACL
3009 chacl((char *)fname, aclent, ((struct acl *)aclent)->acl_len);
3010#endif /* HAVE_AIX_ACL */
3011#endif /* HAVE_SOLARIS_ACL */
Bram Moolenaar8d462f92012-02-05 22:51:33 +01003012#endif /* HAVE_SOLARIS_ZFS_ACL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003013#endif /* HAVE_POSIX_ACL */
3014}
3015
3016 void
3017mch_free_acl(aclent)
3018 vim_acl_T aclent;
3019{
3020 if (aclent == NULL)
3021 return;
3022#ifdef HAVE_POSIX_ACL
3023 acl_free((acl_t)aclent);
3024#else
Bram Moolenaar8d462f92012-02-05 22:51:33 +01003025#ifdef HAVE_SOLARIS_ZFS_ACL
3026 acl_free((acl_t *)aclent);
3027#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00003028#ifdef HAVE_SOLARIS_ACL
3029 free(((vim_acl_solaris_T *)aclent)->acl_entry);
3030 free(aclent);
3031#else
3032#ifdef HAVE_AIX_ACL
3033 free(aclent);
3034#endif /* HAVE_AIX_ACL */
3035#endif /* HAVE_SOLARIS_ACL */
Bram Moolenaar8d462f92012-02-05 22:51:33 +01003036#endif /* HAVE_SOLARIS_ZFS_ACL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003037#endif /* HAVE_POSIX_ACL */
3038}
3039#endif
3040
3041/*
3042 * Set hidden flag for "name".
3043 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003044 void
3045mch_hide(name)
Bram Moolenaar78a15312009-05-15 19:33:18 +00003046 char_u *name UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003047{
3048 /* can't hide a file */
3049}
3050
3051/*
3052 * return TRUE if "name" is a directory
3053 * return FALSE if "name" is not a directory
3054 * return FALSE for error
3055 */
3056 int
3057mch_isdir(name)
3058 char_u *name;
3059{
3060 struct stat statb;
3061
3062 if (*name == NUL) /* Some stat()s don't flag "" as an error. */
3063 return FALSE;
3064 if (stat((char *)name, &statb))
3065 return FALSE;
3066#ifdef _POSIX_SOURCE
3067 return (S_ISDIR(statb.st_mode) ? TRUE : FALSE);
3068#else
3069 return ((statb.st_mode & S_IFMT) == S_IFDIR ? TRUE : FALSE);
3070#endif
3071}
3072
Bram Moolenaar071d4272004-06-13 20:20:40 +00003073static int executable_file __ARGS((char_u *name));
3074
3075/*
3076 * Return 1 if "name" is an executable file, 0 if not or it doesn't exist.
3077 */
3078 static int
3079executable_file(name)
3080 char_u *name;
3081{
3082 struct stat st;
3083
3084 if (stat((char *)name, &st))
3085 return 0;
Bram Moolenaar206f0112014-03-12 16:51:55 +01003086#ifdef VMS
3087 /* Like on Unix system file can have executable rights but not necessarily
3088 * be an executable, but on Unix is not a default for an ordianry file to
3089 * have an executable flag - on VMS it is in most cases.
3090 * Therefore, this check does not have any sense - let keep us to the
3091 * conventions instead:
3092 * *.COM and *.EXE files are the executables - the rest are not. This is
3093 * not ideal but better then it was.
3094 */
3095 int vms_executable = 0;
3096 if (S_ISREG(st.st_mode) && mch_access((char *)name, X_OK) == 0)
3097 {
3098 if (strstr(vms_tolower((char*)name),".exe") != NULL
3099 || strstr(vms_tolower((char*)name),".com")!= NULL)
3100 vms_executable = 1;
3101 }
3102 return vms_executable;
3103#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00003104 return S_ISREG(st.st_mode) && mch_access((char *)name, X_OK) == 0;
Bram Moolenaar206f0112014-03-12 16:51:55 +01003105#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003106}
3107
3108/*
3109 * Return 1 if "name" can be found in $PATH and executed, 0 if not.
Bram Moolenaarb5971142015-03-21 17:32:19 +01003110 * If "use_path" is FALSE only check if "name" is executable.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003111 * Return -1 if unknown.
3112 */
3113 int
Bram Moolenaarb5971142015-03-21 17:32:19 +01003114mch_can_exe(name, path, use_path)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003115 char_u *name;
Bram Moolenaarc7f02552014-04-01 21:00:59 +02003116 char_u **path;
Bram Moolenaarb5971142015-03-21 17:32:19 +01003117 int use_path;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003118{
3119 char_u *buf;
3120 char_u *p, *e;
3121 int retval;
3122
Bram Moolenaarb5971142015-03-21 17:32:19 +01003123 /* When "use_path" is false and if it's an absolute or relative path don't
3124 * need to use $PATH. */
3125 if (!use_path || mch_isFullName(name) || (name[0] == '.'
3126 && (name[1] == '/' || (name[1] == '.' && name[2] == '/'))))
Bram Moolenaar206f0112014-03-12 16:51:55 +01003127 {
Bram Moolenaarb5971142015-03-21 17:32:19 +01003128 /* There must be a path separator, files in the current directory
3129 * can't be executed. */
3130 if (gettail(name) != name && executable_file(name))
Bram Moolenaarc7f02552014-04-01 21:00:59 +02003131 {
3132 if (path != NULL)
3133 {
3134 if (name[0] == '.')
3135 *path = FullName_save(name, TRUE);
3136 else
3137 *path = vim_strsave(name);
3138 }
3139 return TRUE;
3140 }
3141 return FALSE;
Bram Moolenaar206f0112014-03-12 16:51:55 +01003142 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003143
3144 p = (char_u *)getenv("PATH");
3145 if (p == NULL || *p == NUL)
3146 return -1;
3147 buf = alloc((unsigned)(STRLEN(name) + STRLEN(p) + 2));
3148 if (buf == NULL)
3149 return -1;
3150
3151 /*
3152 * Walk through all entries in $PATH to check if "name" exists there and
3153 * is an executable file.
3154 */
3155 for (;;)
3156 {
3157 e = (char_u *)strchr((char *)p, ':');
3158 if (e == NULL)
3159 e = p + STRLEN(p);
3160 if (e - p <= 1) /* empty entry means current dir */
3161 STRCPY(buf, "./");
3162 else
3163 {
Bram Moolenaarbbebc852005-07-18 21:47:53 +00003164 vim_strncpy(buf, p, e - p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003165 add_pathsep(buf);
3166 }
3167 STRCAT(buf, name);
3168 retval = executable_file(buf);
3169 if (retval == 1)
Bram Moolenaarc7f02552014-04-01 21:00:59 +02003170 {
3171 if (path != NULL)
3172 {
3173 if (buf[0] == '.')
3174 *path = FullName_save(buf, TRUE);
3175 else
3176 *path = vim_strsave(buf);
3177 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003178 break;
Bram Moolenaarc7f02552014-04-01 21:00:59 +02003179 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003180
3181 if (*e != ':')
3182 break;
3183 p = e + 1;
3184 }
3185
3186 vim_free(buf);
3187 return retval;
3188}
Bram Moolenaar071d4272004-06-13 20:20:40 +00003189
3190/*
3191 * Check what "name" is:
3192 * NODE_NORMAL: file or directory (or doesn't exist)
3193 * NODE_WRITABLE: writable device, socket, fifo, etc.
3194 * NODE_OTHER: non-writable things
3195 */
3196 int
3197mch_nodetype(name)
3198 char_u *name;
3199{
3200 struct stat st;
3201
3202 if (stat((char *)name, &st))
3203 return NODE_NORMAL;
3204 if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
3205 return NODE_NORMAL;
3206#ifndef OS2
3207 if (S_ISBLK(st.st_mode)) /* block device isn't writable */
3208 return NODE_OTHER;
3209#endif
3210 /* Everything else is writable? */
3211 return NODE_WRITABLE;
3212}
3213
3214 void
3215mch_early_init()
3216{
3217#ifdef HAVE_CHECK_STACK_GROWTH
3218 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003219
Bram Moolenaar071d4272004-06-13 20:20:40 +00003220 check_stack_growth((char *)&i);
3221
Bram Moolenaarbc7aa852005-03-06 23:38:09 +00003222# ifdef HAVE_STACK_LIMIT
Bram Moolenaar071d4272004-06-13 20:20:40 +00003223 get_stack_limit();
3224# endif
3225
3226#endif
3227
3228 /*
3229 * Setup an alternative stack for signals. Helps to catch signals when
3230 * running out of stack space.
3231 * Use of sigaltstack() is preferred, it's more portable.
3232 * Ignore any errors.
3233 */
3234#if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
Bram Moolenaar5a221812008-11-12 12:08:45 +00003235 signal_stack = (char *)alloc(SIGSTKSZ);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003236 init_signal_stack();
3237#endif
3238}
3239
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00003240#if defined(EXITFREE) || defined(PROTO)
3241 void
3242mch_free_mem()
3243{
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00003244# if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
3245 if (clip_star.owned)
3246 clip_lose_selection(&clip_star);
3247 if (clip_plus.owned)
3248 clip_lose_selection(&clip_plus);
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00003249# endif
Bram Moolenaare8208012008-06-20 09:59:25 +00003250# if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00003251 if (xterm_Shell != (Widget)0)
3252 XtDestroyWidget(xterm_Shell);
Bram Moolenaare8208012008-06-20 09:59:25 +00003253# ifndef LESSTIF_VERSION
3254 /* Lesstif crashes here, lose some memory */
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00003255 if (xterm_dpy != NULL)
3256 XtCloseDisplay(xterm_dpy);
3257 if (app_context != (XtAppContext)NULL)
Bram Moolenaare8208012008-06-20 09:59:25 +00003258 {
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00003259 XtDestroyApplicationContext(app_context);
Bram Moolenaare8208012008-06-20 09:59:25 +00003260# ifdef FEAT_X11
3261 x11_display = NULL; /* freed by XtDestroyApplicationContext() */
3262# endif
3263 }
3264# endif
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00003265# endif
Bram Moolenaar0eda7ac2010-06-26 05:38:18 +02003266# if defined(FEAT_X11)
Bram Moolenaare8208012008-06-20 09:59:25 +00003267 if (x11_display != NULL
3268# ifdef FEAT_XCLIPBOARD
3269 && x11_display != xterm_dpy
3270# endif
3271 )
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00003272 XCloseDisplay(x11_display);
3273# endif
3274# if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
3275 vim_free(signal_stack);
3276 signal_stack = NULL;
3277# endif
3278# ifdef FEAT_TITLE
3279 vim_free(oldtitle);
3280 vim_free(oldicon);
3281# endif
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00003282}
3283#endif
3284
Bram Moolenaar071d4272004-06-13 20:20:40 +00003285static void exit_scroll __ARGS((void));
3286
3287/*
3288 * Output a newline when exiting.
3289 * Make sure the newline goes to the same stream as the text.
3290 */
3291 static void
3292exit_scroll()
3293{
Bram Moolenaardf177f62005-02-22 08:39:57 +00003294 if (silent_mode)
3295 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003296 if (newline_on_exit || msg_didout)
3297 {
3298 if (msg_use_printf())
3299 {
3300 if (info_message)
3301 mch_msg("\n");
3302 else
3303 mch_errmsg("\r\n");
3304 }
3305 else
3306 out_char('\n');
3307 }
3308 else
3309 {
3310 restore_cterm_colors(); /* get original colors back */
3311 msg_clr_eos_force(); /* clear the rest of the display */
3312 windgoto((int)Rows - 1, 0); /* may have moved the cursor */
3313 }
3314}
3315
3316 void
3317mch_exit(r)
3318 int r;
3319{
3320 exiting = TRUE;
3321
3322#if defined(FEAT_X11) && defined(FEAT_CLIPBOARD)
3323 x11_export_final_selection();
3324#endif
3325
3326#ifdef FEAT_GUI
3327 if (!gui.in_use)
3328#endif
3329 {
3330 settmode(TMODE_COOK);
3331#ifdef FEAT_TITLE
3332 mch_restore_title(3); /* restore xterm title and icon name */
3333#endif
3334 /*
3335 * When t_ti is not empty but it doesn't cause swapping terminal
3336 * pages, need to output a newline when msg_didout is set. But when
3337 * t_ti does swap pages it should not go to the shell page. Do this
3338 * before stoptermcap().
3339 */
3340 if (swapping_screen() && !newline_on_exit)
3341 exit_scroll();
3342
3343 /* Stop termcap: May need to check for T_CRV response, which
3344 * requires RAW mode. */
3345 stoptermcap();
3346
3347 /*
3348 * A newline is only required after a message in the alternate screen.
3349 * This is set to TRUE by wait_return().
3350 */
3351 if (!swapping_screen() || newline_on_exit)
3352 exit_scroll();
3353
3354 /* Cursor may have been switched off without calling starttermcap()
3355 * when doing "vim -u vimrc" and vimrc contains ":q". */
3356 if (full_screen)
3357 cursor_on();
3358 }
3359 out_flush();
3360 ml_close_all(TRUE); /* remove all memfiles */
3361 may_core_dump();
3362#ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00003363 if (gui.in_use)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003364 gui_exit(r);
3365#endif
Bram Moolenaardf177f62005-02-22 08:39:57 +00003366
Bram Moolenaar56718732006-03-15 22:53:57 +00003367#ifdef MACOS_CONVERT
Bram Moolenaardf177f62005-02-22 08:39:57 +00003368 mac_conv_cleanup();
3369#endif
3370
Bram Moolenaar071d4272004-06-13 20:20:40 +00003371#ifdef __QNX__
3372 /* A core dump won't be created if the signal handler
3373 * doesn't return, so we can't call exit() */
3374 if (deadly_signal != 0)
3375 return;
3376#endif
3377
Bram Moolenaar009b2592004-10-24 19:18:58 +00003378#ifdef FEAT_NETBEANS_INTG
Bram Moolenaarb26e6322010-05-22 21:34:09 +02003379 netbeans_send_disconnect();
Bram Moolenaar009b2592004-10-24 19:18:58 +00003380#endif
Bram Moolenaar0a5fe212005-06-24 23:01:23 +00003381
3382#ifdef EXITFREE
3383 free_all_mem();
3384#endif
3385
Bram Moolenaar071d4272004-06-13 20:20:40 +00003386 exit(r);
3387}
3388
3389 static void
3390may_core_dump()
3391{
3392 if (deadly_signal != 0)
3393 {
3394 signal(deadly_signal, SIG_DFL);
3395 kill(getpid(), deadly_signal); /* Die using the signal we caught */
3396 }
3397}
3398
3399#ifndef VMS
3400
3401 void
3402mch_settmode(tmode)
3403 int tmode;
3404{
3405 static int first = TRUE;
3406
3407 /* Why is NeXT excluded here (and not in os_unixx.h)? */
3408#if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
3409 /*
3410 * for "new" tty systems
3411 */
3412# ifdef HAVE_TERMIOS_H
3413 static struct termios told;
3414 struct termios tnew;
3415# else
3416 static struct termio told;
3417 struct termio tnew;
3418# endif
3419
3420 if (first)
3421 {
3422 first = FALSE;
3423# if defined(HAVE_TERMIOS_H)
3424 tcgetattr(read_cmd_fd, &told);
3425# else
3426 ioctl(read_cmd_fd, TCGETA, &told);
3427# endif
3428 }
3429
3430 tnew = told;
3431 if (tmode == TMODE_RAW)
3432 {
3433 /*
3434 * ~ICRNL enables typing ^V^M
3435 */
3436 tnew.c_iflag &= ~ICRNL;
3437 tnew.c_lflag &= ~(ICANON | ECHO | ISIG | ECHOE
3438# if defined(IEXTEN) && !defined(__MINT__)
3439 | IEXTEN /* IEXTEN enables typing ^V on SOLARIS */
3440 /* but it breaks function keys on MINT */
3441# endif
3442 );
3443# ifdef ONLCR /* don't map NL -> CR NL, we do it ourselves */
3444 tnew.c_oflag &= ~ONLCR;
3445# endif
3446 tnew.c_cc[VMIN] = 1; /* return after 1 char */
3447 tnew.c_cc[VTIME] = 0; /* don't wait */
3448 }
3449 else if (tmode == TMODE_SLEEP)
3450 tnew.c_lflag &= ~(ECHO);
3451
3452# if defined(HAVE_TERMIOS_H)
3453 {
3454 int n = 10;
3455
3456 /* A signal may cause tcsetattr() to fail (e.g., SIGCONT). Retry a
3457 * few times. */
3458 while (tcsetattr(read_cmd_fd, TCSANOW, &tnew) == -1
3459 && errno == EINTR && n > 0)
3460 --n;
3461 }
3462# else
3463 ioctl(read_cmd_fd, TCSETA, &tnew);
3464# endif
3465
3466#else
3467
3468 /*
3469 * for "old" tty systems
3470 */
3471# ifndef TIOCSETN
3472# define TIOCSETN TIOCSETP /* for hpux 9.0 */
3473# endif
3474 static struct sgttyb ttybold;
3475 struct sgttyb ttybnew;
3476
3477 if (first)
3478 {
3479 first = FALSE;
3480 ioctl(read_cmd_fd, TIOCGETP, &ttybold);
3481 }
3482
3483 ttybnew = ttybold;
3484 if (tmode == TMODE_RAW)
3485 {
3486 ttybnew.sg_flags &= ~(CRMOD | ECHO);
3487 ttybnew.sg_flags |= RAW;
3488 }
3489 else if (tmode == TMODE_SLEEP)
3490 ttybnew.sg_flags &= ~(ECHO);
3491 ioctl(read_cmd_fd, TIOCSETN, &ttybnew);
3492#endif
3493 curr_tmode = tmode;
3494}
3495
3496/*
3497 * Try to get the code for "t_kb" from the stty setting
3498 *
3499 * Even if termcap claims a backspace key, the user's setting *should*
3500 * prevail. stty knows more about reality than termcap does, and if
3501 * somebody's usual erase key is DEL (which, for most BSD users, it will
3502 * be), they're going to get really annoyed if their erase key starts
3503 * doing forward deletes for no reason. (Eric Fischer)
3504 */
3505 void
3506get_stty()
3507{
3508 char_u buf[2];
3509 char_u *p;
3510
3511 /* Why is NeXT excluded here (and not in os_unixx.h)? */
3512#if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
3513 /* for "new" tty systems */
3514# ifdef HAVE_TERMIOS_H
3515 struct termios keys;
3516# else
3517 struct termio keys;
3518# endif
3519
3520# if defined(HAVE_TERMIOS_H)
3521 if (tcgetattr(read_cmd_fd, &keys) != -1)
3522# else
3523 if (ioctl(read_cmd_fd, TCGETA, &keys) != -1)
3524# endif
3525 {
3526 buf[0] = keys.c_cc[VERASE];
3527 intr_char = keys.c_cc[VINTR];
3528#else
3529 /* for "old" tty systems */
3530 struct sgttyb keys;
3531
3532 if (ioctl(read_cmd_fd, TIOCGETP, &keys) != -1)
3533 {
3534 buf[0] = keys.sg_erase;
3535 intr_char = keys.sg_kill;
3536#endif
3537 buf[1] = NUL;
3538 add_termcode((char_u *)"kb", buf, FALSE);
3539
3540 /*
3541 * If <BS> and <DEL> are now the same, redefine <DEL>.
3542 */
3543 p = find_termcode((char_u *)"kD");
3544 if (p != NULL && p[0] == buf[0] && p[1] == buf[1])
3545 do_fixdel(NULL);
3546 }
3547#if 0
3548 } /* to keep cindent happy */
3549#endif
3550}
3551
3552#endif /* VMS */
3553
3554#if defined(FEAT_MOUSE_TTY) || defined(PROTO)
3555/*
3556 * Set mouse clicks on or off.
3557 */
3558 void
3559mch_setmouse(on)
3560 int on;
3561{
3562 static int ison = FALSE;
3563 int xterm_mouse_vers;
3564
3565 if (on == ison) /* return quickly if nothing to do */
3566 return;
3567
3568 xterm_mouse_vers = use_xterm_mouse();
Bram Moolenaarc8427482011-10-20 21:09:35 +02003569
3570# ifdef FEAT_MOUSE_URXVT
Bram Moolenaar2b9578f2012-08-15 16:21:32 +02003571 if (ttym_flags == TTYM_URXVT)
3572 {
Bram Moolenaarc8427482011-10-20 21:09:35 +02003573 out_str_nf((char_u *)
3574 (on
3575 ? IF_EB("\033[?1015h", ESC_STR "[?1015h")
3576 : IF_EB("\033[?1015l", ESC_STR "[?1015l")));
3577 ison = on;
3578 }
3579# endif
3580
Bram Moolenaar2b9578f2012-08-15 16:21:32 +02003581# ifdef FEAT_MOUSE_SGR
3582 if (ttym_flags == TTYM_SGR)
3583 {
3584 out_str_nf((char_u *)
3585 (on
3586 ? IF_EB("\033[?1006h", ESC_STR "[?1006h")
3587 : IF_EB("\033[?1006l", ESC_STR "[?1006l")));
3588 ison = on;
3589 }
3590# endif
3591
Bram Moolenaar071d4272004-06-13 20:20:40 +00003592 if (xterm_mouse_vers > 0)
3593 {
3594 if (on) /* enable mouse events, use mouse tracking if available */
3595 out_str_nf((char_u *)
3596 (xterm_mouse_vers > 1
3597 ? IF_EB("\033[?1002h", ESC_STR "[?1002h")
3598 : IF_EB("\033[?1000h", ESC_STR "[?1000h")));
3599 else /* disable mouse events, could probably always send the same */
3600 out_str_nf((char_u *)
3601 (xterm_mouse_vers > 1
3602 ? IF_EB("\033[?1002l", ESC_STR "[?1002l")
3603 : IF_EB("\033[?1000l", ESC_STR "[?1000l")));
3604 ison = on;
3605 }
3606
3607# ifdef FEAT_MOUSE_DEC
3608 else if (ttym_flags == TTYM_DEC)
3609 {
3610 if (on) /* enable mouse events */
3611 out_str_nf((char_u *)"\033[1;2'z\033[1;3'{");
3612 else /* disable mouse events */
3613 out_str_nf((char_u *)"\033['z");
3614 ison = on;
3615 }
3616# endif
3617
3618# ifdef FEAT_MOUSE_GPM
3619 else
3620 {
3621 if (on)
3622 {
3623 if (gpm_open())
3624 ison = TRUE;
3625 }
3626 else
3627 {
3628 gpm_close();
3629 ison = FALSE;
3630 }
3631 }
3632# endif
3633
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00003634# ifdef FEAT_SYSMOUSE
3635 else
3636 {
3637 if (on)
3638 {
3639 if (sysmouse_open() == OK)
3640 ison = TRUE;
3641 }
3642 else
3643 {
3644 sysmouse_close();
3645 ison = FALSE;
3646 }
3647 }
3648# endif
3649
Bram Moolenaar071d4272004-06-13 20:20:40 +00003650# ifdef FEAT_MOUSE_JSB
3651 else
3652 {
3653 if (on)
3654 {
3655 /* D - Enable Mouse up/down messages
3656 * L - Enable Left Button Reporting
3657 * M - Enable Middle Button Reporting
3658 * R - Enable Right Button Reporting
3659 * K - Enable SHIFT and CTRL key Reporting
3660 * + - Enable Advanced messaging of mouse moves and up/down messages
3661 * Q - Quiet No Ack
3662 * # - Numeric value of mouse pointer required
3663 * 0 = Multiview 2000 cursor, used as standard
3664 * 1 = Windows Arrow
3665 * 2 = Windows I Beam
3666 * 3 = Windows Hour Glass
3667 * 4 = Windows Cross Hair
3668 * 5 = Windows UP Arrow
3669 */
Bram Moolenaarf8de1612013-04-15 15:32:25 +02003670# ifdef JSBTERM_MOUSE_NONADVANCED
3671 /* Disables full feedback of pointer movements */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003672 out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK1Q\033\\",
3673 ESC_STR "[0~ZwLMRK1Q" ESC_STR "\\"));
Bram Moolenaarf8de1612013-04-15 15:32:25 +02003674# else
Bram Moolenaar071d4272004-06-13 20:20:40 +00003675 out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK+1Q\033\\",
3676 ESC_STR "[0~ZwLMRK+1Q" ESC_STR "\\"));
Bram Moolenaarf8de1612013-04-15 15:32:25 +02003677# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003678 ison = TRUE;
3679 }
3680 else
3681 {
3682 out_str_nf((char_u *)IF_EB("\033[0~ZwQ\033\\",
3683 ESC_STR "[0~ZwQ" ESC_STR "\\"));
3684 ison = FALSE;
3685 }
3686 }
3687# endif
3688# ifdef FEAT_MOUSE_PTERM
3689 else
3690 {
3691 /* 1 = button press, 6 = release, 7 = drag, 1h...9l = right button */
3692 if (on)
3693 out_str_nf("\033[>1h\033[>6h\033[>7h\033[>1h\033[>9l");
3694 else
3695 out_str_nf("\033[>1l\033[>6l\033[>7l\033[>1l\033[>9h");
3696 ison = on;
3697 }
3698# endif
3699}
3700
3701/*
3702 * Set the mouse termcode, depending on the 'term' and 'ttymouse' options.
3703 */
3704 void
3705check_mouse_termcode()
3706{
3707# ifdef FEAT_MOUSE_XTERM
3708 if (use_xterm_mouse()
Bram Moolenaarc8427482011-10-20 21:09:35 +02003709# ifdef FEAT_MOUSE_URXVT
3710 && use_xterm_mouse() != 3
3711# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003712# ifdef FEAT_GUI
3713 && !gui.in_use
3714# endif
3715 )
3716 {
3717 set_mouse_termcode(KS_MOUSE, (char_u *)(term_is_8bit(T_NAME)
Bram Moolenaarbc7aa852005-03-06 23:38:09 +00003718 ? IF_EB("\233M", CSI_STR "M")
3719 : IF_EB("\033[M", ESC_STR "[M")));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003720 if (*p_mouse != NUL)
3721 {
3722 /* force mouse off and maybe on to send possibly new mouse
3723 * activation sequence to the xterm, with(out) drag tracing. */
3724 mch_setmouse(FALSE);
3725 setmouse();
3726 }
3727 }
3728 else
3729 del_mouse_termcode(KS_MOUSE);
3730# endif
3731
3732# ifdef FEAT_MOUSE_GPM
3733 if (!use_xterm_mouse()
3734# ifdef FEAT_GUI
3735 && !gui.in_use
3736# endif
3737 )
3738 set_mouse_termcode(KS_MOUSE, (char_u *)IF_EB("\033MG", ESC_STR "MG"));
3739# endif
3740
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00003741# ifdef FEAT_SYSMOUSE
3742 if (!use_xterm_mouse()
3743# ifdef FEAT_GUI
3744 && !gui.in_use
3745# endif
3746 )
3747 set_mouse_termcode(KS_MOUSE, (char_u *)IF_EB("\033MS", ESC_STR "MS"));
3748# endif
3749
Bram Moolenaar071d4272004-06-13 20:20:40 +00003750# ifdef FEAT_MOUSE_JSB
Bram Moolenaar4e067c82014-07-30 17:21:58 +02003751 /* Conflicts with xterm mouse: "\033[" and "\033[M" ??? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003752 if (!use_xterm_mouse()
3753# ifdef FEAT_GUI
3754 && !gui.in_use
3755# endif
3756 )
3757 set_mouse_termcode(KS_JSBTERM_MOUSE,
3758 (char_u *)IF_EB("\033[0~zw", ESC_STR "[0~zw"));
3759 else
3760 del_mouse_termcode(KS_JSBTERM_MOUSE);
3761# endif
3762
3763# ifdef FEAT_MOUSE_NET
Bram Moolenaarbc7aa852005-03-06 23:38:09 +00003764 /* There is no conflict, but one may type "ESC }" from Insert mode. Don't
Bram Moolenaar071d4272004-06-13 20:20:40 +00003765 * define it in the GUI or when using an xterm. */
3766 if (!use_xterm_mouse()
3767# ifdef FEAT_GUI
3768 && !gui.in_use
3769# endif
3770 )
3771 set_mouse_termcode(KS_NETTERM_MOUSE,
3772 (char_u *)IF_EB("\033}", ESC_STR "}"));
3773 else
3774 del_mouse_termcode(KS_NETTERM_MOUSE);
3775# endif
3776
3777# ifdef FEAT_MOUSE_DEC
Bram Moolenaar4e067c82014-07-30 17:21:58 +02003778 /* Conflicts with xterm mouse: "\033[" and "\033[M" */
Bram Moolenaarcbc17d62014-05-22 21:22:19 +02003779 if (!use_xterm_mouse()
Bram Moolenaar071d4272004-06-13 20:20:40 +00003780# ifdef FEAT_GUI
3781 && !gui.in_use
3782# endif
3783 )
Bram Moolenaarbc7aa852005-03-06 23:38:09 +00003784 set_mouse_termcode(KS_DEC_MOUSE, (char_u *)(term_is_8bit(T_NAME)
3785 ? IF_EB("\233", CSI_STR) : IF_EB("\033[", ESC_STR "[")));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003786 else
3787 del_mouse_termcode(KS_DEC_MOUSE);
3788# endif
3789# ifdef FEAT_MOUSE_PTERM
Bram Moolenaar4e067c82014-07-30 17:21:58 +02003790 /* same conflict as the dec mouse */
Bram Moolenaarcbc17d62014-05-22 21:22:19 +02003791 if (!use_xterm_mouse()
Bram Moolenaar071d4272004-06-13 20:20:40 +00003792# ifdef FEAT_GUI
3793 && !gui.in_use
3794# endif
3795 )
3796 set_mouse_termcode(KS_PTERM_MOUSE,
3797 (char_u *) IF_EB("\033[", ESC_STR "["));
3798 else
3799 del_mouse_termcode(KS_PTERM_MOUSE);
3800# endif
Bram Moolenaarc8427482011-10-20 21:09:35 +02003801# ifdef FEAT_MOUSE_URXVT
Bram Moolenaar4e067c82014-07-30 17:21:58 +02003802 /* same conflict as the dec mouse */
Bram Moolenaarcbc17d62014-05-22 21:22:19 +02003803 if (use_xterm_mouse() == 3
Bram Moolenaarc8427482011-10-20 21:09:35 +02003804# ifdef FEAT_GUI
3805 && !gui.in_use
3806# endif
3807 )
3808 {
3809 set_mouse_termcode(KS_URXVT_MOUSE, (char_u *)(term_is_8bit(T_NAME)
3810 ? IF_EB("\233", CSI_STR)
3811 : IF_EB("\033[", ESC_STR "[")));
3812
3813 if (*p_mouse != NUL)
3814 {
3815 mch_setmouse(FALSE);
3816 setmouse();
3817 }
3818 }
3819 else
3820 del_mouse_termcode(KS_URXVT_MOUSE);
3821# endif
Bram Moolenaar2b9578f2012-08-15 16:21:32 +02003822# ifdef FEAT_MOUSE_SGR
Bram Moolenaar24dc2302014-05-13 20:19:58 +02003823 /* There is no conflict with xterm mouse */
Bram Moolenaar2b9578f2012-08-15 16:21:32 +02003824 if (use_xterm_mouse() == 4
3825# ifdef FEAT_GUI
3826 && !gui.in_use
3827# endif
3828 )
3829 {
3830 set_mouse_termcode(KS_SGR_MOUSE, (char_u *)(term_is_8bit(T_NAME)
3831 ? IF_EB("\233<", CSI_STR "<")
3832 : IF_EB("\033[<", ESC_STR "[<")));
3833
3834 if (*p_mouse != NUL)
3835 {
3836 mch_setmouse(FALSE);
3837 setmouse();
3838 }
3839 }
3840 else
3841 del_mouse_termcode(KS_SGR_MOUSE);
3842# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003843}
3844#endif
3845
3846/*
3847 * set screen mode, always fails.
3848 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003849 int
3850mch_screenmode(arg)
Bram Moolenaar78a15312009-05-15 19:33:18 +00003851 char_u *arg UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003852{
3853 EMSG(_(e_screenmode));
3854 return FAIL;
3855}
3856
3857#ifndef VMS
3858
3859/*
3860 * Try to get the current window size:
3861 * 1. with an ioctl(), most accurate method
3862 * 2. from the environment variables LINES and COLUMNS
3863 * 3. from the termcap
3864 * 4. keep using the old values
3865 * Return OK when size could be determined, FAIL otherwise.
3866 */
3867 int
3868mch_get_shellsize()
3869{
3870 long rows = 0;
3871 long columns = 0;
3872 char_u *p;
3873
3874 /*
3875 * For OS/2 use _scrsize().
3876 */
3877# ifdef __EMX__
3878 {
3879 int s[2];
3880
3881 _scrsize(s);
3882 columns = s[0];
3883 rows = s[1];
3884 }
3885# endif
3886
3887 /*
3888 * 1. try using an ioctl. It is the most accurate method.
3889 *
3890 * Try using TIOCGWINSZ first, some systems that have it also define
3891 * TIOCGSIZE but don't have a struct ttysize.
3892 */
3893# ifdef TIOCGWINSZ
3894 {
3895 struct winsize ws;
3896 int fd = 1;
3897
3898 /* When stdout is not a tty, use stdin for the ioctl(). */
3899 if (!isatty(fd) && isatty(read_cmd_fd))
3900 fd = read_cmd_fd;
3901 if (ioctl(fd, TIOCGWINSZ, &ws) == 0)
3902 {
3903 columns = ws.ws_col;
3904 rows = ws.ws_row;
3905 }
3906 }
3907# else /* TIOCGWINSZ */
3908# ifdef TIOCGSIZE
3909 {
3910 struct ttysize ts;
3911 int fd = 1;
3912
3913 /* When stdout is not a tty, use stdin for the ioctl(). */
3914 if (!isatty(fd) && isatty(read_cmd_fd))
3915 fd = read_cmd_fd;
3916 if (ioctl(fd, TIOCGSIZE, &ts) == 0)
3917 {
3918 columns = ts.ts_cols;
3919 rows = ts.ts_lines;
3920 }
3921 }
3922# endif /* TIOCGSIZE */
3923# endif /* TIOCGWINSZ */
3924
3925 /*
3926 * 2. get size from environment
Bram Moolenaar4399ef42005-02-12 14:29:27 +00003927 * When being POSIX compliant ('|' flag in 'cpoptions') this overrules
3928 * the ioctl() values!
Bram Moolenaar071d4272004-06-13 20:20:40 +00003929 */
Bram Moolenaar4399ef42005-02-12 14:29:27 +00003930 if (columns == 0 || rows == 0 || vim_strchr(p_cpo, CPO_TSIZE) != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003931 {
3932 if ((p = (char_u *)getenv("LINES")))
3933 rows = atoi((char *)p);
3934 if ((p = (char_u *)getenv("COLUMNS")))
3935 columns = atoi((char *)p);
3936 }
3937
3938#ifdef HAVE_TGETENT
3939 /*
3940 * 3. try reading "co" and "li" entries from termcap
3941 */
3942 if (columns == 0 || rows == 0)
3943 getlinecol(&columns, &rows);
3944#endif
3945
3946 /*
3947 * 4. If everything fails, use the old values
3948 */
3949 if (columns <= 0 || rows <= 0)
3950 return FAIL;
3951
3952 Rows = rows;
3953 Columns = columns;
Bram Moolenaare057d402013-06-30 17:51:51 +02003954 limit_screen_size();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003955 return OK;
3956}
3957
3958/*
3959 * Try to set the window size to Rows and Columns.
3960 */
3961 void
3962mch_set_shellsize()
3963{
3964 if (*T_CWS)
3965 {
3966 /*
3967 * NOTE: if you get an error here that term_set_winsize() is
3968 * undefined, check the output of configure. It could probably not
3969 * find a ncurses, termcap or termlib library.
3970 */
3971 term_set_winsize((int)Rows, (int)Columns);
3972 out_flush();
3973 screen_start(); /* don't know where cursor is now */
3974 }
3975}
3976
3977#endif /* VMS */
3978
3979/*
3980 * Rows and/or Columns has changed.
3981 */
3982 void
3983mch_new_shellsize()
3984{
3985 /* Nothing to do. */
3986}
3987
Bram Moolenaar205b8862011-09-07 15:04:31 +02003988/*
3989 * Wait for process "child" to end.
3990 * Return "child" if it exited properly, <= 0 on error.
3991 */
3992 static pid_t
3993wait4pid(child, status)
3994 pid_t child;
3995 waitstatus *status;
3996{
3997 pid_t wait_pid = 0;
3998
3999 while (wait_pid != child)
4000 {
Bram Moolenaar6be120e2012-04-20 15:55:16 +02004001 /* When compiled with Python threads are probably used, in which case
4002 * wait() sometimes hangs for no obvious reason. Use waitpid()
4003 * instead and loop (like the GUI). Also needed for other interfaces,
4004 * they might call system(). */
4005# ifdef __NeXT__
Bram Moolenaar205b8862011-09-07 15:04:31 +02004006 wait_pid = wait4(child, status, WNOHANG, (struct rusage *)0);
Bram Moolenaar6be120e2012-04-20 15:55:16 +02004007# else
Bram Moolenaar205b8862011-09-07 15:04:31 +02004008 wait_pid = waitpid(child, status, WNOHANG);
Bram Moolenaar6be120e2012-04-20 15:55:16 +02004009# endif
Bram Moolenaar205b8862011-09-07 15:04:31 +02004010 if (wait_pid == 0)
4011 {
Bram Moolenaar75676462013-01-30 14:55:42 +01004012 /* Wait for 10 msec before trying again. */
Bram Moolenaar205b8862011-09-07 15:04:31 +02004013 mch_delay(10L, TRUE);
4014 continue;
4015 }
Bram Moolenaar205b8862011-09-07 15:04:31 +02004016 if (wait_pid <= 0
4017# ifdef ECHILD
4018 && errno == ECHILD
4019# endif
4020 )
4021 break;
4022 }
4023 return wait_pid;
4024}
4025
Bram Moolenaar071d4272004-06-13 20:20:40 +00004026 int
4027mch_call_shell(cmd, options)
4028 char_u *cmd;
4029 int options; /* SHELL_*, see vim.h */
4030{
4031#ifdef VMS
4032 char *ifn = NULL;
4033 char *ofn = NULL;
4034#endif
4035 int tmode = cur_tmode;
4036#ifdef USE_SYSTEM /* use system() to start the shell: simple but slow */
4037 int x;
4038# ifndef __EMX__
4039 char_u *newcmd; /* only needed for unix */
4040# else
4041 /*
4042 * Set the preferred shell in the EMXSHELL environment variable (but
4043 * only if it is different from what is already in the environment).
4044 * Emx then takes care of whether to use "/c" or "-c" in an
4045 * intelligent way. Simply pass the whole thing to emx's system() call.
4046 * Emx also starts an interactive shell if system() is passed an empty
4047 * string.
4048 */
4049 char_u *p, *old;
4050
4051 if (((old = (char_u *)getenv("EMXSHELL")) == NULL) || STRCMP(old, p_sh))
4052 {
4053 /* should check HAVE_SETENV, but I know we don't have it. */
4054 p = alloc(10 + strlen(p_sh));
4055 if (p)
4056 {
4057 sprintf((char *)p, "EMXSHELL=%s", p_sh);
4058 putenv((char *)p); /* don't free the pointer! */
4059 }
4060 }
4061# endif
4062
4063 out_flush();
4064
4065 if (options & SHELL_COOKED)
4066 settmode(TMODE_COOK); /* set to normal mode */
4067
Bram Moolenaar62b42182010-09-21 22:09:37 +02004068# if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
Bram Moolenaar1a0316c2013-03-13 17:50:25 +01004069 save_clipboard();
Bram Moolenaar62b42182010-09-21 22:09:37 +02004070 loose_clipboard();
4071# endif
4072
Bram Moolenaar071d4272004-06-13 20:20:40 +00004073# ifdef __EMX__
4074 if (cmd == NULL)
4075 x = system(""); /* this starts an interactive shell in emx */
4076 else
4077 x = system((char *)cmd);
4078 /* system() returns -1 when error occurs in starting shell */
4079 if (x == -1 && !emsg_silent)
4080 {
4081 MSG_PUTS(_("\nCannot execute shell "));
4082 msg_outtrans(p_sh);
4083 msg_putchar('\n');
4084 }
4085# else /* not __EMX__ */
4086 if (cmd == NULL)
4087 x = system((char *)p_sh);
4088 else
4089 {
4090# ifdef VMS
4091 if (ofn = strchr((char *)cmd, '>'))
4092 *ofn++ = '\0';
4093 if (ifn = strchr((char *)cmd, '<'))
4094 {
4095 char *p;
4096
4097 *ifn++ = '\0';
4098 p = strchr(ifn,' '); /* chop off any trailing spaces */
4099 if (p)
4100 *p = '\0';
4101 }
4102 if (ofn)
4103 x = vms_sys((char *)cmd, ofn, ifn);
4104 else
4105 x = system((char *)cmd);
4106# else
4107 newcmd = lalloc(STRLEN(p_sh)
4108 + (extra_shell_arg == NULL ? 0 : STRLEN(extra_shell_arg))
4109 + STRLEN(p_shcf) + STRLEN(cmd) + 4, TRUE);
4110 if (newcmd == NULL)
4111 x = 0;
4112 else
4113 {
4114 sprintf((char *)newcmd, "%s %s %s %s", p_sh,
4115 extra_shell_arg == NULL ? "" : (char *)extra_shell_arg,
4116 (char *)p_shcf,
4117 (char *)cmd);
4118 x = system((char *)newcmd);
4119 vim_free(newcmd);
4120 }
4121# endif
4122 }
4123# ifdef VMS
4124 x = vms_sys_status(x);
4125# endif
4126 if (emsg_silent)
4127 ;
4128 else if (x == 127)
4129 MSG_PUTS(_("\nCannot execute shell sh\n"));
4130# endif /* __EMX__ */
4131 else if (x && !(options & SHELL_SILENT))
4132 {
4133 MSG_PUTS(_("\nshell returned "));
4134 msg_outnum((long)x);
4135 msg_putchar('\n');
4136 }
4137
4138 if (tmode == TMODE_RAW)
4139 settmode(TMODE_RAW); /* set to raw mode */
4140# ifdef FEAT_TITLE
4141 resettitle();
4142# endif
Bram Moolenaar1a0316c2013-03-13 17:50:25 +01004143# if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
4144 restore_clipboard();
4145# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004146 return x;
4147
4148#else /* USE_SYSTEM */ /* don't use system(), use fork()/exec() */
4149
Bram Moolenaardf177f62005-02-22 08:39:57 +00004150# define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
4151 127, some shells use that already */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004152
4153 char_u *newcmd = NULL;
4154 pid_t pid;
Bram Moolenaardf177f62005-02-22 08:39:57 +00004155 pid_t wpid = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004156 pid_t wait_pid = 0;
4157# ifdef HAVE_UNION_WAIT
4158 union wait status;
4159# else
4160 int status = -1;
4161# endif
4162 int retval = -1;
4163 char **argv = NULL;
4164 int argc;
Bram Moolenaarea35ef62011-08-04 22:59:28 +02004165 char_u *p_shcf_copy = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004166 int i;
4167 char_u *p;
4168 int inquote;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004169 int pty_master_fd = -1; /* for pty's */
Bram Moolenaardf177f62005-02-22 08:39:57 +00004170# ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00004171 int pty_slave_fd = -1;
4172 char *tty_name;
Bram Moolenaardf177f62005-02-22 08:39:57 +00004173# endif
Bram Moolenaar12033fb2005-12-16 21:49:31 +00004174 int fd_toshell[2]; /* for pipes */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004175 int fd_fromshell[2];
4176 int pipe_error = FALSE;
Bram Moolenaardf177f62005-02-22 08:39:57 +00004177# ifdef HAVE_SETENV
Bram Moolenaar071d4272004-06-13 20:20:40 +00004178 char envbuf[50];
Bram Moolenaardf177f62005-02-22 08:39:57 +00004179# else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004180 static char envbuf_Rows[20];
4181 static char envbuf_Columns[20];
Bram Moolenaar071d4272004-06-13 20:20:40 +00004182# endif
Bram Moolenaar12033fb2005-12-16 21:49:31 +00004183 int did_settmode = FALSE; /* settmode(TMODE_RAW) called */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004184
Bram Moolenaar62b42182010-09-21 22:09:37 +02004185 newcmd = vim_strsave(p_sh);
4186 if (newcmd == NULL) /* out of memory */
4187 goto error;
4188
Bram Moolenaar071d4272004-06-13 20:20:40 +00004189 out_flush();
4190 if (options & SHELL_COOKED)
4191 settmode(TMODE_COOK); /* set to normal mode */
4192
Bram Moolenaar12033fb2005-12-16 21:49:31 +00004193 /*
4194 * Do this loop twice:
4195 * 1: find number of arguments
4196 * 2: separate them and build argv[]
4197 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004198 for (i = 0; i < 2; ++i)
4199 {
4200 p = newcmd;
4201 inquote = FALSE;
4202 argc = 0;
4203 for (;;)
4204 {
4205 if (i == 1)
4206 argv[argc] = (char *)p;
4207 ++argc;
4208 while (*p && (inquote || (*p != ' ' && *p != TAB)))
4209 {
4210 if (*p == '"')
4211 inquote = !inquote;
4212 ++p;
4213 }
4214 if (*p == NUL)
4215 break;
4216 if (i == 1)
4217 *p++ = NUL;
4218 p = skipwhite(p);
4219 }
Bram Moolenaareb3593b2006-04-22 22:33:57 +00004220 if (argv == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004221 {
Bram Moolenaarea35ef62011-08-04 22:59:28 +02004222 /*
4223 * Account for possible multiple args in p_shcf.
4224 */
4225 p = p_shcf;
4226 for (;;)
4227 {
4228 p = skiptowhite(p);
4229 if (*p == NUL)
4230 break;
4231 ++argc;
4232 p = skipwhite(p);
4233 }
4234
Bram Moolenaar071d4272004-06-13 20:20:40 +00004235 argv = (char **)alloc((unsigned)((argc + 4) * sizeof(char *)));
4236 if (argv == NULL) /* out of memory */
4237 goto error;
4238 }
4239 }
4240 if (cmd != NULL)
4241 {
Bram Moolenaar70b2a562012-01-10 22:26:17 +01004242 char_u *s;
4243
Bram Moolenaar071d4272004-06-13 20:20:40 +00004244 if (extra_shell_arg != NULL)
4245 argv[argc++] = (char *)extra_shell_arg;
Bram Moolenaarea35ef62011-08-04 22:59:28 +02004246
4247 /* Break 'shellcmdflag' into white separated parts. This doesn't
4248 * handle quoted strings, they are very unlikely to appear. */
4249 p_shcf_copy = alloc((unsigned)STRLEN(p_shcf) + 1);
4250 if (p_shcf_copy == NULL) /* out of memory */
4251 goto error;
4252 s = p_shcf_copy;
4253 p = p_shcf;
4254 while (*p != NUL)
4255 {
4256 argv[argc++] = (char *)s;
4257 while (*p && *p != ' ' && *p != TAB)
4258 *s++ = *p++;
4259 *s++ = NUL;
4260 p = skipwhite(p);
4261 }
4262
Bram Moolenaar071d4272004-06-13 20:20:40 +00004263 argv[argc++] = (char *)cmd;
4264 }
4265 argv[argc] = NULL;
4266
Bram Moolenaar071d4272004-06-13 20:20:40 +00004267 /*
Bram Moolenaardf177f62005-02-22 08:39:57 +00004268 * For the GUI, when writing the output into the buffer and when reading
4269 * input from the buffer: Try using a pseudo-tty to get the stdin/stdout
4270 * of the executed command into the Vim window. Or use a pipe.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004271 */
Bram Moolenaardf177f62005-02-22 08:39:57 +00004272 if ((options & (SHELL_READ|SHELL_WRITE))
4273# ifdef FEAT_GUI
4274 || (gui.in_use && show_shell_mess)
4275# endif
4276 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00004277 {
Bram Moolenaardf177f62005-02-22 08:39:57 +00004278# ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00004279 /*
4280 * Try to open a master pty.
4281 * If this works, open the slave pty.
4282 * If the slave can't be opened, close the master pty.
4283 */
Bram Moolenaardf177f62005-02-22 08:39:57 +00004284 if (p_guipty && !(options & (SHELL_READ|SHELL_WRITE)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004285 {
4286 pty_master_fd = OpenPTY(&tty_name); /* open pty */
Bram Moolenaare70172e2011-08-04 19:36:52 +02004287 if (pty_master_fd >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004288 {
Bram Moolenaare70172e2011-08-04 19:36:52 +02004289 /* Leaving out O_NOCTTY may lead to waitpid() always returning
4290 * 0 on Mac OS X 10.7 thereby causing freezes. Let's assume
4291 * adding O_NOCTTY always works when defined. */
4292#ifdef O_NOCTTY
4293 pty_slave_fd = open(tty_name, O_RDWR | O_NOCTTY | O_EXTRA, 0);
4294#else
4295 pty_slave_fd = open(tty_name, O_RDWR | O_EXTRA, 0);
4296#endif
4297 if (pty_slave_fd < 0)
4298 {
4299 close(pty_master_fd);
4300 pty_master_fd = -1;
4301 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004302 }
4303 }
4304 /*
4305 * If not opening a pty or it didn't work, try using pipes.
4306 */
4307 if (pty_master_fd < 0)
Bram Moolenaardf177f62005-02-22 08:39:57 +00004308# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004309 {
4310 pipe_error = (pipe(fd_toshell) < 0);
4311 if (!pipe_error) /* pipe create OK */
4312 {
4313 pipe_error = (pipe(fd_fromshell) < 0);
4314 if (pipe_error) /* pipe create failed */
4315 {
4316 close(fd_toshell[0]);
4317 close(fd_toshell[1]);
4318 }
4319 }
4320 if (pipe_error)
4321 {
4322 MSG_PUTS(_("\nCannot create pipes\n"));
4323 out_flush();
4324 }
4325 }
4326 }
4327
4328 if (!pipe_error) /* pty or pipe opened or not used */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004329 {
4330# ifdef __BEOS__
4331 beos_cleanup_read_thread();
4332# endif
Bram Moolenaar12033fb2005-12-16 21:49:31 +00004333
Bram Moolenaar071d4272004-06-13 20:20:40 +00004334 if ((pid = fork()) == -1) /* maybe we should use vfork() */
4335 {
4336 MSG_PUTS(_("\nCannot fork\n"));
Bram Moolenaardf177f62005-02-22 08:39:57 +00004337 if ((options & (SHELL_READ|SHELL_WRITE))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004338# ifdef FEAT_GUI
Bram Moolenaardf177f62005-02-22 08:39:57 +00004339 || (gui.in_use && show_shell_mess)
4340# endif
4341 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00004342 {
Bram Moolenaardf177f62005-02-22 08:39:57 +00004343# ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00004344 if (pty_master_fd >= 0) /* close the pseudo tty */
4345 {
4346 close(pty_master_fd);
4347 close(pty_slave_fd);
4348 }
4349 else /* close the pipes */
Bram Moolenaardf177f62005-02-22 08:39:57 +00004350# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004351 {
4352 close(fd_toshell[0]);
4353 close(fd_toshell[1]);
4354 close(fd_fromshell[0]);
4355 close(fd_fromshell[1]);
4356 }
4357 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004358 }
4359 else if (pid == 0) /* child */
4360 {
4361 reset_signals(); /* handle signals normally */
4362
4363 if (!show_shell_mess || (options & SHELL_EXPAND))
4364 {
4365 int fd;
4366
4367 /*
4368 * Don't want to show any message from the shell. Can't just
4369 * close stdout and stderr though, because some systems will
4370 * break if you try to write to them after that, so we must
4371 * use dup() to replace them with something else -- webb
4372 * Connect stdin to /dev/null too, so ":n `cat`" doesn't hang,
4373 * waiting for input.
4374 */
4375 fd = open("/dev/null", O_RDWR | O_EXTRA, 0);
4376 fclose(stdin);
4377 fclose(stdout);
4378 fclose(stderr);
4379
4380 /*
4381 * If any of these open()'s and dup()'s fail, we just continue
4382 * anyway. It's not fatal, and on most systems it will make
4383 * no difference at all. On a few it will cause the execvp()
4384 * to exit with a non-zero status even when the completion
4385 * could be done, which is nothing too serious. If the open()
4386 * or dup() failed we'd just do the same thing ourselves
4387 * anyway -- webb
4388 */
4389 if (fd >= 0)
4390 {
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00004391 ignored = dup(fd); /* To replace stdin (fd 0) */
4392 ignored = dup(fd); /* To replace stdout (fd 1) */
4393 ignored = dup(fd); /* To replace stderr (fd 2) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004394
4395 /* Don't need this now that we've duplicated it */
4396 close(fd);
4397 }
4398 }
Bram Moolenaardf177f62005-02-22 08:39:57 +00004399 else if ((options & (SHELL_READ|SHELL_WRITE))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004400# ifdef FEAT_GUI
Bram Moolenaardf177f62005-02-22 08:39:57 +00004401 || gui.in_use
4402# endif
4403 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00004404 {
4405
Bram Moolenaardf177f62005-02-22 08:39:57 +00004406# ifdef HAVE_SETSID
Bram Moolenaar12033fb2005-12-16 21:49:31 +00004407 /* Create our own process group, so that the child and all its
4408 * children can be kill()ed. Don't do this when using pipes,
Bram Moolenaare37d50a2008-08-06 17:06:04 +00004409 * because stdin is not a tty, we would lose /dev/tty. */
Bram Moolenaar12033fb2005-12-16 21:49:31 +00004410 if (p_stmp)
Bram Moolenaar07256082009-02-04 13:19:42 +00004411 {
Bram Moolenaar12033fb2005-12-16 21:49:31 +00004412 (void)setsid();
Bram Moolenaar07256082009-02-04 13:19:42 +00004413# if defined(SIGHUP)
4414 /* When doing "!xterm&" and 'shell' is bash: the shell
4415 * will exit and send SIGHUP to all processes in its
4416 * group, killing the just started process. Ignore SIGHUP
4417 * to avoid that. (suggested by Simon Schubert)
4418 */
4419 signal(SIGHUP, SIG_IGN);
4420# endif
4421 }
Bram Moolenaardf177f62005-02-22 08:39:57 +00004422# endif
4423# ifdef FEAT_GUI
Bram Moolenaar12033fb2005-12-16 21:49:31 +00004424 if (pty_slave_fd >= 0)
4425 {
4426 /* push stream discipline modules */
4427 if (options & SHELL_COOKED)
4428 SetupSlavePTY(pty_slave_fd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004429# ifdef TIOCSCTTY
Bram Moolenaar12033fb2005-12-16 21:49:31 +00004430 /* Try to become controlling tty (probably doesn't work,
4431 * unless run by root) */
4432 ioctl(pty_slave_fd, TIOCSCTTY, (char *)NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004433# endif
Bram Moolenaar12033fb2005-12-16 21:49:31 +00004434 }
Bram Moolenaardf177f62005-02-22 08:39:57 +00004435# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004436 /* Simulate to have a dumb terminal (for now) */
Bram Moolenaardf177f62005-02-22 08:39:57 +00004437# ifdef HAVE_SETENV
Bram Moolenaar071d4272004-06-13 20:20:40 +00004438 setenv("TERM", "dumb", 1);
4439 sprintf((char *)envbuf, "%ld", Rows);
4440 setenv("ROWS", (char *)envbuf, 1);
4441 sprintf((char *)envbuf, "%ld", Rows);
4442 setenv("LINES", (char *)envbuf, 1);
4443 sprintf((char *)envbuf, "%ld", Columns);
4444 setenv("COLUMNS", (char *)envbuf, 1);
Bram Moolenaardf177f62005-02-22 08:39:57 +00004445# else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004446 /*
4447 * Putenv does not copy the string, it has to remain valid.
Bram Moolenaare37d50a2008-08-06 17:06:04 +00004448 * Use a static array to avoid losing allocated memory.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004449 */
4450 putenv("TERM=dumb");
4451 sprintf(envbuf_Rows, "ROWS=%ld", Rows);
4452 putenv(envbuf_Rows);
4453 sprintf(envbuf_Rows, "LINES=%ld", Rows);
4454 putenv(envbuf_Rows);
4455 sprintf(envbuf_Columns, "COLUMNS=%ld", Columns);
4456 putenv(envbuf_Columns);
Bram Moolenaardf177f62005-02-22 08:39:57 +00004457# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004458
Bram Moolenaara5792f52005-11-23 21:25:05 +00004459 /*
4460 * stderr is only redirected when using the GUI, so that a
4461 * program like gpg can still access the terminal to get a
4462 * passphrase using stderr.
4463 */
Bram Moolenaardf177f62005-02-22 08:39:57 +00004464# ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00004465 if (pty_master_fd >= 0)
4466 {
4467 close(pty_master_fd); /* close master side of pty */
4468
4469 /* set up stdin/stdout/stderr for the child */
4470 close(0);
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00004471 ignored = dup(pty_slave_fd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004472 close(1);
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00004473 ignored = dup(pty_slave_fd);
Bram Moolenaara5792f52005-11-23 21:25:05 +00004474 if (gui.in_use)
4475 {
4476 close(2);
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00004477 ignored = dup(pty_slave_fd);
Bram Moolenaara5792f52005-11-23 21:25:05 +00004478 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004479
4480 close(pty_slave_fd); /* has been dupped, close it now */
4481 }
4482 else
Bram Moolenaardf177f62005-02-22 08:39:57 +00004483# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004484 {
4485 /* set up stdin for the child */
4486 close(fd_toshell[1]);
4487 close(0);
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00004488 ignored = dup(fd_toshell[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004489 close(fd_toshell[0]);
4490
4491 /* set up stdout for the child */
4492 close(fd_fromshell[0]);
4493 close(1);
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00004494 ignored = dup(fd_fromshell[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004495 close(fd_fromshell[1]);
4496
Bram Moolenaara5792f52005-11-23 21:25:05 +00004497# ifdef FEAT_GUI
4498 if (gui.in_use)
4499 {
4500 /* set up stderr for the child */
4501 close(2);
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00004502 ignored = dup(1);
Bram Moolenaara5792f52005-11-23 21:25:05 +00004503 }
4504# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004505 }
4506 }
Bram Moolenaardf177f62005-02-22 08:39:57 +00004507
Bram Moolenaar071d4272004-06-13 20:20:40 +00004508 /*
4509 * There is no type cast for the argv, because the type may be
4510 * different on different machines. This may cause a warning
4511 * message with strict compilers, don't worry about it.
4512 * Call _exit() instead of exit() to avoid closing the connection
4513 * to the X server (esp. with GTK, which uses atexit()).
4514 */
4515 execvp(argv[0], argv);
4516 _exit(EXEC_FAILED); /* exec failed, return failure code */
4517 }
4518 else /* parent */
4519 {
4520 /*
4521 * While child is running, ignore terminating signals.
Bram Moolenaardf177f62005-02-22 08:39:57 +00004522 * Do catch CTRL-C, so that "got_int" is set.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004523 */
4524 catch_signals(SIG_IGN, SIG_ERR);
Bram Moolenaardf177f62005-02-22 08:39:57 +00004525 catch_int_signal();
Bram Moolenaar071d4272004-06-13 20:20:40 +00004526
4527 /*
4528 * For the GUI we redirect stdin, stdout and stderr to our window.
Bram Moolenaardf177f62005-02-22 08:39:57 +00004529 * This is also used to pipe stdin/stdout to/from the external
4530 * command.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004531 */
Bram Moolenaardf177f62005-02-22 08:39:57 +00004532 if ((options & (SHELL_READ|SHELL_WRITE))
4533# ifdef FEAT_GUI
4534 || (gui.in_use && show_shell_mess)
4535# endif
4536 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00004537 {
Bram Moolenaardf177f62005-02-22 08:39:57 +00004538# define BUFLEN 100 /* length for buffer, pseudo tty limit is 128 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004539 char_u buffer[BUFLEN + 1];
Bram Moolenaardf177f62005-02-22 08:39:57 +00004540# ifdef FEAT_MBYTE
Bram Moolenaar071d4272004-06-13 20:20:40 +00004541 int buffer_off = 0; /* valid bytes in buffer[] */
Bram Moolenaardf177f62005-02-22 08:39:57 +00004542# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004543 char_u ta_buf[BUFLEN + 1]; /* TypeAHead */
4544 int ta_len = 0; /* valid bytes in ta_buf[] */
4545 int len;
4546 int p_more_save;
4547 int old_State;
4548 int c;
4549 int toshell_fd;
4550 int fromshell_fd;
Bram Moolenaardf177f62005-02-22 08:39:57 +00004551 garray_T ga;
4552 int noread_cnt;
Bram Moolenaarb3dc8fd2009-02-22 01:52:59 +00004553# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
4554 struct timeval start_tv;
4555# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004556
Bram Moolenaardf177f62005-02-22 08:39:57 +00004557# ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00004558 if (pty_master_fd >= 0)
4559 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004560 fromshell_fd = pty_master_fd;
4561 toshell_fd = dup(pty_master_fd);
4562 }
4563 else
Bram Moolenaardf177f62005-02-22 08:39:57 +00004564# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004565 {
4566 close(fd_toshell[0]);
4567 close(fd_fromshell[1]);
4568 toshell_fd = fd_toshell[1];
4569 fromshell_fd = fd_fromshell[0];
4570 }
4571
4572 /*
4573 * Write to the child if there are typed characters.
4574 * Read from the child if there are characters available.
4575 * Repeat the reading a few times if more characters are
4576 * available. Need to check for typed keys now and then, but
4577 * not too often (delays when no chars are available).
4578 * This loop is quit if no characters can be read from the pty
4579 * (WaitForChar detected special condition), or there are no
4580 * characters available and the child has exited.
4581 * Only check if the child has exited when there is no more
4582 * output. The child may exit before all the output has
4583 * been printed.
4584 *
4585 * Currently this busy loops!
4586 * This can probably dead-lock when the write blocks!
4587 */
4588 p_more_save = p_more;
4589 p_more = FALSE;
4590 old_State = State;
4591 State = EXTERNCMD; /* don't redraw at window resize */
4592
Bram Moolenaar12033fb2005-12-16 21:49:31 +00004593 if ((options & SHELL_WRITE) && toshell_fd >= 0)
Bram Moolenaardf177f62005-02-22 08:39:57 +00004594 {
4595 /* Fork a process that will write the lines to the
4596 * external program. */
4597 if ((wpid = fork()) == -1)
4598 {
4599 MSG_PUTS(_("\nCannot fork\n"));
4600 }
Bram Moolenaar205b8862011-09-07 15:04:31 +02004601 else if (wpid == 0) /* child */
Bram Moolenaardf177f62005-02-22 08:39:57 +00004602 {
4603 linenr_T lnum = curbuf->b_op_start.lnum;
4604 int written = 0;
Bram Moolenaar89d40322006-08-29 15:30:07 +00004605 char_u *lp = ml_get(lnum);
Bram Moolenaardf177f62005-02-22 08:39:57 +00004606 size_t l;
4607
Bram Moolenaar8cd06ca2005-02-28 22:44:58 +00004608 close(fromshell_fd);
Bram Moolenaardf177f62005-02-22 08:39:57 +00004609 for (;;)
4610 {
Bram Moolenaar89d40322006-08-29 15:30:07 +00004611 l = STRLEN(lp + written);
Bram Moolenaardf177f62005-02-22 08:39:57 +00004612 if (l == 0)
4613 len = 0;
Bram Moolenaar89d40322006-08-29 15:30:07 +00004614 else if (lp[written] == NL)
Bram Moolenaardf177f62005-02-22 08:39:57 +00004615 /* NL -> NUL translation */
4616 len = write(toshell_fd, "", (size_t)1);
4617 else
4618 {
Bram Moolenaar70b2a562012-01-10 22:26:17 +01004619 char_u *s = vim_strchr(lp + written, NL);
4620
Bram Moolenaar89d40322006-08-29 15:30:07 +00004621 len = write(toshell_fd, (char *)lp + written,
Bram Moolenaar78a15312009-05-15 19:33:18 +00004622 s == NULL ? l
4623 : (size_t)(s - (lp + written)));
Bram Moolenaardf177f62005-02-22 08:39:57 +00004624 }
Bram Moolenaar78a15312009-05-15 19:33:18 +00004625 if (len == (int)l)
Bram Moolenaardf177f62005-02-22 08:39:57 +00004626 {
4627 /* Finished a line, add a NL, unless this line
4628 * should not have one. */
4629 if (lnum != curbuf->b_op_end.lnum
Bram Moolenaar34d72d42015-07-17 14:18:08 +02004630 || (!curbuf->b_p_bin
4631 && curbuf->b_p_fixeol)
Bram Moolenaarcab35ad2011-02-15 17:39:22 +01004632 || (lnum != curbuf->b_no_eol_lnum
Bram Moolenaardf177f62005-02-22 08:39:57 +00004633 && (lnum !=
4634 curbuf->b_ml.ml_line_count
4635 || curbuf->b_p_eol)))
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00004636 ignored = write(toshell_fd, "\n",
4637 (size_t)1);
Bram Moolenaardf177f62005-02-22 08:39:57 +00004638 ++lnum;
4639 if (lnum > curbuf->b_op_end.lnum)
4640 {
4641 /* finished all the lines, close pipe */
4642 close(toshell_fd);
4643 toshell_fd = -1;
4644 break;
4645 }
Bram Moolenaar89d40322006-08-29 15:30:07 +00004646 lp = ml_get(lnum);
Bram Moolenaardf177f62005-02-22 08:39:57 +00004647 written = 0;
4648 }
4649 else if (len > 0)
4650 written += len;
4651 }
4652 _exit(0);
4653 }
Bram Moolenaar205b8862011-09-07 15:04:31 +02004654 else /* parent */
Bram Moolenaardf177f62005-02-22 08:39:57 +00004655 {
4656 close(toshell_fd);
4657 toshell_fd = -1;
4658 }
4659 }
4660
4661 if (options & SHELL_READ)
4662 ga_init2(&ga, 1, BUFLEN);
4663
4664 noread_cnt = 0;
Bram Moolenaarb3dc8fd2009-02-22 01:52:59 +00004665# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
4666 gettimeofday(&start_tv, NULL);
4667# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004668 for (;;)
4669 {
4670 /*
4671 * Check if keys have been typed, write them to the child
Bram Moolenaar5b962cf2005-12-12 21:58:40 +00004672 * if there are any.
4673 * Don't do this if we are expanding wild cards (would eat
4674 * typeahead).
4675 * Don't do this when filtering and terminal is in cooked
4676 * mode, the shell command will handle the I/O. Avoids
4677 * that a typed password is echoed for ssh or gpg command.
Bram Moolenaar12033fb2005-12-16 21:49:31 +00004678 * Don't get characters when the child has already
4679 * finished (wait_pid == 0).
Bram Moolenaardf177f62005-02-22 08:39:57 +00004680 * Don't read characters unless we didn't get output for a
Bram Moolenaarb3dc8fd2009-02-22 01:52:59 +00004681 * while (noread_cnt > 4), avoids that ":r !ls" eats
4682 * typeahead.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004683 */
4684 len = 0;
4685 if (!(options & SHELL_EXPAND)
Bram Moolenaar5b962cf2005-12-12 21:58:40 +00004686 && ((options &
4687 (SHELL_READ|SHELL_WRITE|SHELL_COOKED))
4688 != (SHELL_READ|SHELL_WRITE|SHELL_COOKED)
Bram Moolenaarb3dc8fd2009-02-22 01:52:59 +00004689# ifdef FEAT_GUI
Bram Moolenaar5b962cf2005-12-12 21:58:40 +00004690 || gui.in_use
Bram Moolenaarb3dc8fd2009-02-22 01:52:59 +00004691# endif
Bram Moolenaar5b962cf2005-12-12 21:58:40 +00004692 )
Bram Moolenaar12033fb2005-12-16 21:49:31 +00004693 && wait_pid == 0
Bram Moolenaarb3dc8fd2009-02-22 01:52:59 +00004694 && (ta_len > 0 || noread_cnt > 4))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004695 {
Bram Moolenaarb3dc8fd2009-02-22 01:52:59 +00004696 if (ta_len == 0)
4697 {
4698 /* Get extra characters when we don't have any.
4699 * Reset the counter and timer. */
4700 noread_cnt = 0;
4701# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
4702 gettimeofday(&start_tv, NULL);
4703# endif
4704 len = ui_inchar(ta_buf, BUFLEN, 10L, 0);
4705 }
4706 if (ta_len > 0 || len > 0)
4707 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004708 /*
4709 * For pipes:
4710 * Check for CTRL-C: send interrupt signal to child.
4711 * Check for CTRL-D: EOF, close pipe to child.
4712 */
4713 if (len == 1 && (pty_master_fd < 0 || cmd != NULL))
4714 {
Bram Moolenaardf177f62005-02-22 08:39:57 +00004715# ifdef SIGINT
Bram Moolenaar071d4272004-06-13 20:20:40 +00004716 /*
4717 * Send SIGINT to the child's group or all
4718 * processes in our group.
4719 */
4720 if (ta_buf[ta_len] == Ctrl_C
4721 || ta_buf[ta_len] == intr_char)
Bram Moolenaardf177f62005-02-22 08:39:57 +00004722 {
4723# ifdef HAVE_SETSID
Bram Moolenaar071d4272004-06-13 20:20:40 +00004724 kill(-pid, SIGINT);
Bram Moolenaardf177f62005-02-22 08:39:57 +00004725# else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004726 kill(0, SIGINT);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004727# endif
Bram Moolenaardf177f62005-02-22 08:39:57 +00004728 if (wpid > 0)
4729 kill(wpid, SIGINT);
4730 }
4731# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004732 if (pty_master_fd < 0 && toshell_fd >= 0
4733 && ta_buf[ta_len] == Ctrl_D)
4734 {
4735 close(toshell_fd);
4736 toshell_fd = -1;
4737 }
4738 }
4739
4740 /* replace K_BS by <BS> and K_DEL by <DEL> */
4741 for (i = ta_len; i < ta_len + len; ++i)
4742 {
4743 if (ta_buf[i] == CSI && len - i > 2)
4744 {
4745 c = TERMCAP2KEY(ta_buf[i + 1], ta_buf[i + 2]);
4746 if (c == K_DEL || c == K_KDEL || c == K_BS)
4747 {
4748 mch_memmove(ta_buf + i + 1, ta_buf + i + 3,
4749 (size_t)(len - i - 2));
4750 if (c == K_DEL || c == K_KDEL)
4751 ta_buf[i] = DEL;
4752 else
4753 ta_buf[i] = Ctrl_H;
4754 len -= 2;
4755 }
4756 }
4757 else if (ta_buf[i] == '\r')
4758 ta_buf[i] = '\n';
Bram Moolenaardf177f62005-02-22 08:39:57 +00004759# ifdef FEAT_MBYTE
Bram Moolenaar071d4272004-06-13 20:20:40 +00004760 if (has_mbyte)
Bram Moolenaarfeba08b2009-06-16 13:12:07 +00004761 i += (*mb_ptr2len_len)(ta_buf + i,
4762 ta_len + len - i) - 1;
Bram Moolenaardf177f62005-02-22 08:39:57 +00004763# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004764 }
4765
4766 /*
4767 * For pipes: echo the typed characters.
4768 * For a pty this does not seem to work.
4769 */
4770 if (pty_master_fd < 0)
4771 {
4772 for (i = ta_len; i < ta_len + len; ++i)
4773 {
4774 if (ta_buf[i] == '\n' || ta_buf[i] == '\b')
4775 msg_putchar(ta_buf[i]);
Bram Moolenaardf177f62005-02-22 08:39:57 +00004776# ifdef FEAT_MBYTE
Bram Moolenaar071d4272004-06-13 20:20:40 +00004777 else if (has_mbyte)
4778 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00004779 int l = (*mb_ptr2len)(ta_buf + i);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004780
4781 msg_outtrans_len(ta_buf + i, l);
4782 i += l - 1;
4783 }
Bram Moolenaardf177f62005-02-22 08:39:57 +00004784# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004785 else
4786 msg_outtrans_len(ta_buf + i, 1);
4787 }
4788 windgoto(msg_row, msg_col);
4789 out_flush();
4790 }
4791
4792 ta_len += len;
4793
4794 /*
4795 * Write the characters to the child, unless EOF has
4796 * been typed for pipes. Write one character at a
Bram Moolenaare37d50a2008-08-06 17:06:04 +00004797 * time, to avoid losing too much typeahead.
Bram Moolenaardf177f62005-02-22 08:39:57 +00004798 * When writing buffer lines, drop the typed
4799 * characters (only check for CTRL-C).
Bram Moolenaar071d4272004-06-13 20:20:40 +00004800 */
Bram Moolenaardf177f62005-02-22 08:39:57 +00004801 if (options & SHELL_WRITE)
4802 ta_len = 0;
4803 else if (toshell_fd >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004804 {
4805 len = write(toshell_fd, (char *)ta_buf, (size_t)1);
4806 if (len > 0)
4807 {
4808 ta_len -= len;
4809 mch_memmove(ta_buf, ta_buf + len, ta_len);
4810 }
4811 }
Bram Moolenaarb3dc8fd2009-02-22 01:52:59 +00004812 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004813 }
4814
Bram Moolenaardf177f62005-02-22 08:39:57 +00004815 if (got_int)
4816 {
4817 /* CTRL-C sends a signal to the child, we ignore it
4818 * ourselves */
4819# ifdef HAVE_SETSID
4820 kill(-pid, SIGINT);
4821# else
4822 kill(0, SIGINT);
4823# endif
4824 if (wpid > 0)
4825 kill(wpid, SIGINT);
4826 got_int = FALSE;
4827 }
4828
Bram Moolenaar071d4272004-06-13 20:20:40 +00004829 /*
4830 * Check if the child has any characters to be printed.
4831 * Read them and write them to our window. Repeat this as
4832 * long as there is something to do, avoid the 10ms wait
4833 * for mch_inchar(), or sending typeahead characters to
4834 * the external process.
4835 * TODO: This should handle escape sequences, compatible
4836 * to some terminal (vt52?).
4837 */
Bram Moolenaardf177f62005-02-22 08:39:57 +00004838 ++noread_cnt;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004839 while (RealWaitForChar(fromshell_fd, 10L, NULL))
4840 {
Bram Moolenaar540fc6f2010-12-17 16:27:16 +01004841 len = read_eintr(fromshell_fd, buffer
Bram Moolenaardf177f62005-02-22 08:39:57 +00004842# ifdef FEAT_MBYTE
Bram Moolenaar071d4272004-06-13 20:20:40 +00004843 + buffer_off, (size_t)(BUFLEN - buffer_off)
Bram Moolenaardf177f62005-02-22 08:39:57 +00004844# else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004845 , (size_t)BUFLEN
Bram Moolenaardf177f62005-02-22 08:39:57 +00004846# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004847 );
4848 if (len <= 0) /* end of file or error */
4849 goto finished;
Bram Moolenaardf177f62005-02-22 08:39:57 +00004850
4851 noread_cnt = 0;
4852 if (options & SHELL_READ)
4853 {
4854 /* Do NUL -> NL translation, append NL separated
4855 * lines to the current buffer. */
4856 for (i = 0; i < len; ++i)
4857 {
4858 if (buffer[i] == NL)
4859 append_ga_line(&ga);
4860 else if (buffer[i] == NUL)
4861 ga_append(&ga, NL);
4862 else
4863 ga_append(&ga, buffer[i]);
4864 }
4865 }
4866# ifdef FEAT_MBYTE
4867 else if (has_mbyte)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004868 {
4869 int l;
4870
Bram Moolenaardf177f62005-02-22 08:39:57 +00004871 len += buffer_off;
4872 buffer[len] = NUL;
4873
Bram Moolenaar071d4272004-06-13 20:20:40 +00004874 /* Check if the last character in buffer[] is
4875 * incomplete, keep these bytes for the next
4876 * round. */
4877 for (p = buffer; p < buffer + len; p += l)
4878 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00004879 l = mb_cptr2len(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004880 if (l == 0)
4881 l = 1; /* NUL byte? */
4882 else if (MB_BYTE2LEN(*p) != l)
4883 break;
4884 }
4885 if (p == buffer) /* no complete character */
4886 {
4887 /* avoid getting stuck at an illegal byte */
4888 if (len >= 12)
4889 ++p;
4890 else
4891 {
4892 buffer_off = len;
4893 continue;
4894 }
4895 }
4896 c = *p;
4897 *p = NUL;
4898 msg_puts(buffer);
4899 if (p < buffer + len)
4900 {
4901 *p = c;
4902 buffer_off = (buffer + len) - p;
4903 mch_memmove(buffer, p, buffer_off);
4904 continue;
4905 }
4906 buffer_off = 0;
4907 }
Bram Moolenaardf177f62005-02-22 08:39:57 +00004908# endif /* FEAT_MBYTE */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004909 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004910 {
4911 buffer[len] = NUL;
4912 msg_puts(buffer);
4913 }
4914
4915 windgoto(msg_row, msg_col);
4916 cursor_on();
4917 out_flush();
4918 if (got_int)
4919 break;
Bram Moolenaarb3dc8fd2009-02-22 01:52:59 +00004920
4921# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
4922 {
4923 struct timeval now_tv;
4924 long msec;
4925
4926 /* Avoid that we keep looping here without
4927 * checking for a CTRL-C for a long time. Don't
4928 * break out too often to avoid losing typeahead. */
4929 gettimeofday(&now_tv, NULL);
4930 msec = (now_tv.tv_sec - start_tv.tv_sec) * 1000L
4931 + (now_tv.tv_usec - start_tv.tv_usec) / 1000L;
4932 if (msec > 2000)
4933 {
4934 noread_cnt = 5;
4935 break;
4936 }
4937 }
4938# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004939 }
4940
Bram Moolenaar12033fb2005-12-16 21:49:31 +00004941 /* If we already detected the child has finished break the
4942 * loop now. */
4943 if (wait_pid == pid)
4944 break;
4945
Bram Moolenaar071d4272004-06-13 20:20:40 +00004946 /*
4947 * Check if the child still exists, before checking for
Bram Moolenaare37d50a2008-08-06 17:06:04 +00004948 * typed characters (otherwise we would lose typeahead).
Bram Moolenaar071d4272004-06-13 20:20:40 +00004949 */
Bram Moolenaardf177f62005-02-22 08:39:57 +00004950# ifdef __NeXT__
Bram Moolenaar205b8862011-09-07 15:04:31 +02004951 wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *)0);
Bram Moolenaardf177f62005-02-22 08:39:57 +00004952# else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004953 wait_pid = waitpid(pid, &status, WNOHANG);
Bram Moolenaardf177f62005-02-22 08:39:57 +00004954# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004955 if ((wait_pid == (pid_t)-1 && errno == ECHILD)
4956 || (wait_pid == pid && WIFEXITED(status)))
4957 {
Bram Moolenaar12033fb2005-12-16 21:49:31 +00004958 /* Don't break the loop yet, try reading more
4959 * characters from "fromshell_fd" first. When using
4960 * pipes there might still be something to read and
4961 * then we'll break the loop at the "break" above. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004962 wait_pid = pid;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004963 }
Bram Moolenaar12033fb2005-12-16 21:49:31 +00004964 else
4965 wait_pid = 0;
Bram Moolenaar090cfc12013-03-19 12:35:42 +01004966
Bram Moolenaar95a51352013-03-21 22:53:50 +01004967# if defined(FEAT_XCLIPBOARD) && defined(FEAT_X11)
Bram Moolenaar090cfc12013-03-19 12:35:42 +01004968 /* Handle any X events, e.g. serving the clipboard. */
4969 clip_update();
4970# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004971 }
4972finished:
4973 p_more = p_more_save;
Bram Moolenaardf177f62005-02-22 08:39:57 +00004974 if (options & SHELL_READ)
4975 {
4976 if (ga.ga_len > 0)
4977 {
4978 append_ga_line(&ga);
4979 /* remember that the NL was missing */
Bram Moolenaarcab35ad2011-02-15 17:39:22 +01004980 curbuf->b_no_eol_lnum = curwin->w_cursor.lnum;
Bram Moolenaardf177f62005-02-22 08:39:57 +00004981 }
4982 else
Bram Moolenaarcab35ad2011-02-15 17:39:22 +01004983 curbuf->b_no_eol_lnum = 0;
Bram Moolenaardf177f62005-02-22 08:39:57 +00004984 ga_clear(&ga);
4985 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004986
Bram Moolenaar071d4272004-06-13 20:20:40 +00004987 /*
4988 * Give all typeahead that wasn't used back to ui_inchar().
4989 */
4990 if (ta_len)
4991 ui_inchar_undo(ta_buf, ta_len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004992 State = old_State;
4993 if (toshell_fd >= 0)
4994 close(toshell_fd);
4995 close(fromshell_fd);
4996 }
Bram Moolenaar95a51352013-03-21 22:53:50 +01004997# if defined(FEAT_XCLIPBOARD) && defined(FEAT_X11)
Bram Moolenaar090cfc12013-03-19 12:35:42 +01004998 else
4999 {
5000 /*
5001 * Similar to the loop above, but only handle X events, no
5002 * I/O.
5003 */
5004 for (;;)
5005 {
5006 if (got_int)
5007 {
5008 /* CTRL-C sends a signal to the child, we ignore it
5009 * ourselves */
5010# ifdef HAVE_SETSID
5011 kill(-pid, SIGINT);
5012# else
5013 kill(0, SIGINT);
5014# endif
5015 got_int = FALSE;
5016 }
5017# ifdef __NeXT__
5018 wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *)0);
5019# else
5020 wait_pid = waitpid(pid, &status, WNOHANG);
5021# endif
5022 if ((wait_pid == (pid_t)-1 && errno == ECHILD)
5023 || (wait_pid == pid && WIFEXITED(status)))
5024 {
5025 wait_pid = pid;
5026 break;
5027 }
5028
5029 /* Handle any X events, e.g. serving the clipboard. */
5030 clip_update();
5031
5032 mch_delay(10L, TRUE);
5033 }
5034 }
5035# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005036
5037 /*
5038 * Wait until our child has exited.
5039 * Ignore wait() returning pids of other children and returning
5040 * because of some signal like SIGWINCH.
5041 * Don't wait if wait_pid was already set above, indicating the
5042 * child already exited.
5043 */
Bram Moolenaar205b8862011-09-07 15:04:31 +02005044 if (wait_pid != pid)
5045 wait_pid = wait4pid(pid, &status);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005046
Bram Moolenaar624891f2010-10-13 16:22:09 +02005047# ifdef FEAT_GUI
5048 /* Close slave side of pty. Only do this after the child has
5049 * exited, otherwise the child may hang when it tries to write on
5050 * the pty. */
5051 if (pty_master_fd >= 0)
5052 close(pty_slave_fd);
5053# endif
5054
Bram Moolenaardf177f62005-02-22 08:39:57 +00005055 /* Make sure the child that writes to the external program is
5056 * dead. */
5057 if (wpid > 0)
Bram Moolenaar205b8862011-09-07 15:04:31 +02005058 {
Bram Moolenaardf177f62005-02-22 08:39:57 +00005059 kill(wpid, SIGKILL);
Bram Moolenaar205b8862011-09-07 15:04:31 +02005060 wait4pid(wpid, NULL);
5061 }
Bram Moolenaardf177f62005-02-22 08:39:57 +00005062
Bram Moolenaar071d4272004-06-13 20:20:40 +00005063 /*
5064 * Set to raw mode right now, otherwise a CTRL-C after
5065 * catch_signals() will kill Vim.
5066 */
5067 if (tmode == TMODE_RAW)
5068 settmode(TMODE_RAW);
5069 did_settmode = TRUE;
5070 set_signals();
5071
5072 if (WIFEXITED(status))
5073 {
Bram Moolenaar9d75c832005-01-25 21:57:23 +00005074 /* LINTED avoid "bitwise operation on signed value" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005075 retval = WEXITSTATUS(status);
Bram Moolenaar75676462013-01-30 14:55:42 +01005076 if (retval != 0 && !emsg_silent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005077 {
5078 if (retval == EXEC_FAILED)
5079 {
5080 MSG_PUTS(_("\nCannot execute shell "));
5081 msg_outtrans(p_sh);
5082 msg_putchar('\n');
5083 }
5084 else if (!(options & SHELL_SILENT))
5085 {
5086 MSG_PUTS(_("\nshell returned "));
5087 msg_outnum((long)retval);
5088 msg_putchar('\n');
5089 }
5090 }
5091 }
5092 else
5093 MSG_PUTS(_("\nCommand terminated\n"));
5094 }
5095 }
5096 vim_free(argv);
Bram Moolenaarea35ef62011-08-04 22:59:28 +02005097 vim_free(p_shcf_copy);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005098
5099error:
5100 if (!did_settmode)
5101 if (tmode == TMODE_RAW)
5102 settmode(TMODE_RAW); /* set to raw mode */
5103# ifdef FEAT_TITLE
5104 resettitle();
5105# endif
5106 vim_free(newcmd);
5107
5108 return retval;
5109
5110#endif /* USE_SYSTEM */
5111}
5112
5113/*
5114 * Check for CTRL-C typed by reading all available characters.
5115 * In cooked mode we should get SIGINT, no need to check.
5116 */
5117 void
5118mch_breakcheck()
5119{
5120 if (curr_tmode == TMODE_RAW && RealWaitForChar(read_cmd_fd, 0L, NULL))
5121 fill_input_buf(FALSE);
5122}
5123
5124/*
5125 * Wait "msec" msec until a character is available from the keyboard or from
5126 * inbuf[]. msec == -1 will block forever.
5127 * When a GUI is being used, this will never get called -- webb
5128 */
5129 static int
5130WaitForChar(msec)
5131 long msec;
5132{
5133#ifdef FEAT_MOUSE_GPM
5134 int gpm_process_wanted;
5135#endif
5136#ifdef FEAT_XCLIPBOARD
5137 int rest;
5138#endif
5139 int avail;
5140
5141 if (input_available()) /* something in inbuf[] */
5142 return 1;
5143
5144#if defined(FEAT_MOUSE_DEC)
5145 /* May need to query the mouse position. */
5146 if (WantQueryMouse)
5147 {
Bram Moolenaar6bb68362005-03-22 23:03:44 +00005148 WantQueryMouse = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005149 mch_write((char_u *)IF_EB("\033[1'|", ESC_STR "[1'|"), 5);
5150 }
5151#endif
5152
5153 /*
5154 * For FEAT_MOUSE_GPM and FEAT_XCLIPBOARD we loop here to process mouse
5155 * events. This is a bit complicated, because they might both be defined.
5156 */
5157#if defined(FEAT_MOUSE_GPM) || defined(FEAT_XCLIPBOARD)
5158# ifdef FEAT_XCLIPBOARD
5159 rest = 0;
5160 if (do_xterm_trace())
5161 rest = msec;
5162# endif
5163 do
5164 {
5165# ifdef FEAT_XCLIPBOARD
5166 if (rest != 0)
5167 {
5168 msec = XT_TRACE_DELAY;
5169 if (rest >= 0 && rest < XT_TRACE_DELAY)
5170 msec = rest;
5171 if (rest >= 0)
5172 rest -= msec;
5173 }
5174# endif
5175# ifdef FEAT_MOUSE_GPM
5176 gpm_process_wanted = 0;
5177 avail = RealWaitForChar(read_cmd_fd, msec, &gpm_process_wanted);
5178# else
5179 avail = RealWaitForChar(read_cmd_fd, msec, NULL);
5180# endif
5181 if (!avail)
5182 {
5183 if (input_available())
5184 return 1;
5185# ifdef FEAT_XCLIPBOARD
5186 if (rest == 0 || !do_xterm_trace())
5187# endif
5188 break;
5189 }
5190 }
5191 while (FALSE
5192# ifdef FEAT_MOUSE_GPM
5193 || (gpm_process_wanted && mch_gpm_process() == 0)
5194# endif
5195# ifdef FEAT_XCLIPBOARD
5196 || (!avail && rest != 0)
5197# endif
5198 );
5199
5200#else
5201 avail = RealWaitForChar(read_cmd_fd, msec, NULL);
5202#endif
5203 return avail;
5204}
5205
Bram Moolenaar4ffa0702013-12-11 17:12:37 +01005206#ifndef VMS
Bram Moolenaar071d4272004-06-13 20:20:40 +00005207/*
5208 * Wait "msec" msec until a character is available from file descriptor "fd".
Bram Moolenaar493c7a82011-09-07 14:06:47 +02005209 * "msec" == 0 will check for characters once.
5210 * "msec" == -1 will block until a character is available.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005211 * When a GUI is being used, this will not be used for input -- webb
5212 * Returns also, when a request from Sniff is waiting -- toni.
5213 * Or when a Linux GPM mouse event is waiting.
Bram Moolenaar93c88e02015-09-15 14:12:05 +02005214 * Or when a clientserver message is on the queue.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005215 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005216#if defined(__BEOS__)
5217 int
5218#else
5219 static int
5220#endif
5221RealWaitForChar(fd, msec, check_for_gpm)
5222 int fd;
5223 long msec;
Bram Moolenaar78a15312009-05-15 19:33:18 +00005224 int *check_for_gpm UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005225{
5226 int ret;
Bram Moolenaar67c53842010-05-22 18:28:27 +02005227#ifdef FEAT_NETBEANS_INTG
Bram Moolenaarb26e6322010-05-22 21:34:09 +02005228 int nb_fd = netbeans_filedesc();
Bram Moolenaar67c53842010-05-22 18:28:27 +02005229#endif
Bram Moolenaar325b7a22004-07-05 15:58:32 +00005230#if defined(FEAT_XCLIPBOARD) || defined(USE_XSMP) || defined(FEAT_MZSCHEME)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005231 static int busy = FALSE;
5232
5233 /* May retry getting characters after an event was handled. */
5234# define MAY_LOOP
5235
5236# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
5237 /* Remember at what time we started, so that we know how much longer we
5238 * should wait after being interrupted. */
5239# define USE_START_TV
5240 struct timeval start_tv;
5241
5242 if (msec > 0 && (
5243# ifdef FEAT_XCLIPBOARD
5244 xterm_Shell != (Widget)0
Bram Moolenaar325b7a22004-07-05 15:58:32 +00005245# if defined(USE_XSMP) || defined(FEAT_MZSCHEME)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005246 ||
5247# endif
5248# endif
5249# ifdef USE_XSMP
5250 xsmp_icefd != -1
Bram Moolenaar325b7a22004-07-05 15:58:32 +00005251# ifdef FEAT_MZSCHEME
5252 ||
5253# endif
5254# endif
5255# ifdef FEAT_MZSCHEME
5256 (mzthreads_allowed() && p_mzq > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005257# endif
5258 ))
5259 gettimeofday(&start_tv, NULL);
5260# endif
5261
5262 /* Handle being called recursively. This may happen for the session
5263 * manager stuff, it may save the file, which does a breakcheck. */
5264 if (busy)
5265 return 0;
5266#endif
5267
5268#ifdef MAY_LOOP
Bram Moolenaar35fdbb52005-07-09 21:08:57 +00005269 for (;;)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005270#endif
5271 {
5272#ifdef MAY_LOOP
5273 int finished = TRUE; /* default is to 'loop' just once */
Bram Moolenaar325b7a22004-07-05 15:58:32 +00005274# ifdef FEAT_MZSCHEME
5275 int mzquantum_used = FALSE;
5276# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005277#endif
5278#ifndef HAVE_SELECT
Bram Moolenaar67c53842010-05-22 18:28:27 +02005279 struct pollfd fds[6];
Bram Moolenaar071d4272004-06-13 20:20:40 +00005280 int nfd;
5281# ifdef FEAT_XCLIPBOARD
5282 int xterm_idx = -1;
5283# endif
5284# ifdef FEAT_MOUSE_GPM
5285 int gpm_idx = -1;
5286# endif
5287# ifdef USE_XSMP
5288 int xsmp_idx = -1;
5289# endif
Bram Moolenaar67c53842010-05-22 18:28:27 +02005290# ifdef FEAT_NETBEANS_INTG
5291 int nb_idx = -1;
5292# endif
Bram Moolenaar325b7a22004-07-05 15:58:32 +00005293 int towait = (int)msec;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005294
Bram Moolenaar325b7a22004-07-05 15:58:32 +00005295# ifdef FEAT_MZSCHEME
5296 mzvim_check_threads();
5297 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
5298 {
5299 towait = (int)p_mzq; /* don't wait longer than 'mzquantum' */
5300 mzquantum_used = TRUE;
5301 }
5302# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005303 fds[0].fd = fd;
5304 fds[0].events = POLLIN;
5305 nfd = 1;
5306
5307# ifdef FEAT_SNIFF
5308# define SNIFF_IDX 1
5309 if (want_sniff_request)
5310 {
5311 fds[SNIFF_IDX].fd = fd_from_sniff;
5312 fds[SNIFF_IDX].events = POLLIN;
5313 nfd++;
5314 }
5315# endif
5316# ifdef FEAT_XCLIPBOARD
Bram Moolenaarb1e26502014-11-19 18:48:46 +01005317 may_restore_clipboard();
Bram Moolenaar071d4272004-06-13 20:20:40 +00005318 if (xterm_Shell != (Widget)0)
5319 {
5320 xterm_idx = nfd;
5321 fds[nfd].fd = ConnectionNumber(xterm_dpy);
5322 fds[nfd].events = POLLIN;
5323 nfd++;
5324 }
5325# endif
5326# ifdef FEAT_MOUSE_GPM
5327 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
5328 {
5329 gpm_idx = nfd;
5330 fds[nfd].fd = gpm_fd;
5331 fds[nfd].events = POLLIN;
5332 nfd++;
5333 }
5334# endif
5335# ifdef USE_XSMP
5336 if (xsmp_icefd != -1)
5337 {
5338 xsmp_idx = nfd;
5339 fds[nfd].fd = xsmp_icefd;
5340 fds[nfd].events = POLLIN;
5341 nfd++;
5342 }
5343# endif
Bram Moolenaar67c53842010-05-22 18:28:27 +02005344#ifdef FEAT_NETBEANS_INTG
5345 if (nb_fd != -1)
5346 {
5347 nb_idx = nfd;
5348 fds[nfd].fd = nb_fd;
5349 fds[nfd].events = POLLIN;
5350 nfd++;
5351 }
5352#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005353
Bram Moolenaar325b7a22004-07-05 15:58:32 +00005354 ret = poll(fds, nfd, towait);
5355# ifdef FEAT_MZSCHEME
5356 if (ret == 0 && mzquantum_used)
Bram Moolenaarc2a27c32007-12-01 16:19:33 +00005357 /* MzThreads scheduling is required and timeout occurred */
Bram Moolenaar325b7a22004-07-05 15:58:32 +00005358 finished = FALSE;
5359# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005360
5361# ifdef FEAT_SNIFF
5362 if (ret < 0)
5363 sniff_disconnect(1);
5364 else if (want_sniff_request)
5365 {
5366 if (fds[SNIFF_IDX].revents & POLLHUP)
5367 sniff_disconnect(1);
5368 if (fds[SNIFF_IDX].revents & POLLIN)
5369 sniff_request_waiting = 1;
5370 }
5371# endif
5372# ifdef FEAT_XCLIPBOARD
5373 if (xterm_Shell != (Widget)0 && (fds[xterm_idx].revents & POLLIN))
5374 {
5375 xterm_update(); /* Maybe we should hand out clipboard */
5376 if (--ret == 0 && !input_available())
5377 /* Try again */
5378 finished = FALSE;
5379 }
5380# endif
5381# ifdef FEAT_MOUSE_GPM
5382 if (gpm_idx >= 0 && (fds[gpm_idx].revents & POLLIN))
5383 {
5384 *check_for_gpm = 1;
5385 }
5386# endif
5387# ifdef USE_XSMP
5388 if (xsmp_idx >= 0 && (fds[xsmp_idx].revents & (POLLIN | POLLHUP)))
5389 {
5390 if (fds[xsmp_idx].revents & POLLIN)
5391 {
5392 busy = TRUE;
5393 xsmp_handle_requests();
5394 busy = FALSE;
5395 }
5396 else if (fds[xsmp_idx].revents & POLLHUP)
5397 {
5398 if (p_verbose > 0)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00005399 verb_msg((char_u *)_("XSMP lost ICE connection"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005400 xsmp_close();
5401 }
5402 if (--ret == 0)
Bram Moolenaar325b7a22004-07-05 15:58:32 +00005403 finished = FALSE; /* Try again */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005404 }
5405# endif
Bram Moolenaar67c53842010-05-22 18:28:27 +02005406#ifdef FEAT_NETBEANS_INTG
5407 if (ret > 0 && nb_idx != -1 && fds[nb_idx].revents & POLLIN)
5408 {
5409 netbeans_read();
5410 --ret;
5411 }
5412#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005413
5414
5415#else /* HAVE_SELECT */
5416
5417 struct timeval tv;
Bram Moolenaar325b7a22004-07-05 15:58:32 +00005418 struct timeval *tvp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005419 fd_set rfds, efds;
5420 int maxfd;
Bram Moolenaar325b7a22004-07-05 15:58:32 +00005421 long towait = msec;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005422
Bram Moolenaar325b7a22004-07-05 15:58:32 +00005423# ifdef FEAT_MZSCHEME
5424 mzvim_check_threads();
5425 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
5426 {
5427 towait = p_mzq; /* don't wait longer than 'mzquantum' */
5428 mzquantum_used = TRUE;
5429 }
5430# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005431# ifdef __EMX__
5432 /* don't check for incoming chars if not in raw mode, because select()
5433 * always returns TRUE then (in some version of emx.dll) */
5434 if (curr_tmode != TMODE_RAW)
5435 return 0;
5436# endif
5437
Bram Moolenaar325b7a22004-07-05 15:58:32 +00005438 if (towait >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005439 {
Bram Moolenaar325b7a22004-07-05 15:58:32 +00005440 tv.tv_sec = towait / 1000;
5441 tv.tv_usec = (towait % 1000) * (1000000/1000);
5442 tvp = &tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005443 }
Bram Moolenaar325b7a22004-07-05 15:58:32 +00005444 else
5445 tvp = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005446
5447 /*
5448 * Select on ready for reading and exceptional condition (end of file).
5449 */
Bram Moolenaar493c7a82011-09-07 14:06:47 +02005450select_eintr:
5451 FD_ZERO(&rfds);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005452 FD_ZERO(&efds);
5453 FD_SET(fd, &rfds);
5454# if !defined(__QNX__) && !defined(__CYGWIN32__)
5455 /* For QNX select() always returns 1 if this is set. Why? */
5456 FD_SET(fd, &efds);
5457# endif
5458 maxfd = fd;
5459
5460# ifdef FEAT_SNIFF
5461 if (want_sniff_request)
5462 {
5463 FD_SET(fd_from_sniff, &rfds);
5464 FD_SET(fd_from_sniff, &efds);
5465 if (maxfd < fd_from_sniff)
5466 maxfd = fd_from_sniff;
5467 }
5468# endif
5469# ifdef FEAT_XCLIPBOARD
Bram Moolenaarb1e26502014-11-19 18:48:46 +01005470 may_restore_clipboard();
Bram Moolenaar071d4272004-06-13 20:20:40 +00005471 if (xterm_Shell != (Widget)0)
5472 {
5473 FD_SET(ConnectionNumber(xterm_dpy), &rfds);
5474 if (maxfd < ConnectionNumber(xterm_dpy))
5475 maxfd = ConnectionNumber(xterm_dpy);
Bram Moolenaardd82d692012-08-15 17:26:57 +02005476
5477 /* An event may have already been read but not handled. In
5478 * particulary, XFlush may cause this. */
5479 xterm_update();
Bram Moolenaar071d4272004-06-13 20:20:40 +00005480 }
5481# endif
5482# ifdef FEAT_MOUSE_GPM
5483 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
5484 {
5485 FD_SET(gpm_fd, &rfds);
5486 FD_SET(gpm_fd, &efds);
5487 if (maxfd < gpm_fd)
5488 maxfd = gpm_fd;
5489 }
5490# endif
5491# ifdef USE_XSMP
5492 if (xsmp_icefd != -1)
5493 {
5494 FD_SET(xsmp_icefd, &rfds);
5495 FD_SET(xsmp_icefd, &efds);
5496 if (maxfd < xsmp_icefd)
5497 maxfd = xsmp_icefd;
5498 }
5499# endif
Bram Moolenaardd82d692012-08-15 17:26:57 +02005500# ifdef FEAT_NETBEANS_INTG
Bram Moolenaar67c53842010-05-22 18:28:27 +02005501 if (nb_fd != -1)
5502 {
5503 FD_SET(nb_fd, &rfds);
5504 if (maxfd < nb_fd)
5505 maxfd = nb_fd;
5506 }
Bram Moolenaardd82d692012-08-15 17:26:57 +02005507# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005508
Bram Moolenaar325b7a22004-07-05 15:58:32 +00005509 ret = select(maxfd + 1, &rfds, NULL, &efds, tvp);
Bram Moolenaar493c7a82011-09-07 14:06:47 +02005510# ifdef EINTR
5511 if (ret == -1 && errno == EINTR)
Bram Moolenaar2e7b1df2011-10-12 21:04:20 +02005512 {
5513 /* Check whether window has been resized, EINTR may be caused by
5514 * SIGWINCH. */
5515 if (do_resize)
5516 handle_resize();
5517
Bram Moolenaar493c7a82011-09-07 14:06:47 +02005518 /* Interrupted by a signal, need to try again. We ignore msec
5519 * here, because we do want to check even after a timeout if
5520 * characters are available. Needed for reading output of an
5521 * external command after the process has finished. */
5522 goto select_eintr;
Bram Moolenaar2e7b1df2011-10-12 21:04:20 +02005523 }
Bram Moolenaar493c7a82011-09-07 14:06:47 +02005524# endif
Bram Moolenaar311d9822007-02-27 15:48:28 +00005525# ifdef __TANDEM
5526 if (ret == -1 && errno == ENOTSUP)
5527 {
5528 FD_ZERO(&rfds);
5529 FD_ZERO(&efds);
5530 ret = 0;
5531 }
Bram Moolenaar493c7a82011-09-07 14:06:47 +02005532# endif
Bram Moolenaar325b7a22004-07-05 15:58:32 +00005533# ifdef FEAT_MZSCHEME
5534 if (ret == 0 && mzquantum_used)
Bram Moolenaarc2a27c32007-12-01 16:19:33 +00005535 /* loop if MzThreads must be scheduled and timeout occurred */
Bram Moolenaar325b7a22004-07-05 15:58:32 +00005536 finished = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005537# endif
5538
5539# ifdef FEAT_SNIFF
5540 if (ret < 0 )
5541 sniff_disconnect(1);
5542 else if (ret > 0 && want_sniff_request)
5543 {
5544 if (FD_ISSET(fd_from_sniff, &efds))
5545 sniff_disconnect(1);
5546 if (FD_ISSET(fd_from_sniff, &rfds))
5547 sniff_request_waiting = 1;
5548 }
5549# endif
5550# ifdef FEAT_XCLIPBOARD
5551 if (ret > 0 && xterm_Shell != (Widget)0
5552 && FD_ISSET(ConnectionNumber(xterm_dpy), &rfds))
5553 {
5554 xterm_update(); /* Maybe we should hand out clipboard */
5555 /* continue looping when we only got the X event and the input
5556 * buffer is empty */
5557 if (--ret == 0 && !input_available())
5558 {
5559 /* Try again */
5560 finished = FALSE;
5561 }
5562 }
5563# endif
5564# ifdef FEAT_MOUSE_GPM
5565 if (ret > 0 && gpm_flag && check_for_gpm != NULL && gpm_fd >= 0)
5566 {
5567 if (FD_ISSET(gpm_fd, &efds))
5568 gpm_close();
5569 else if (FD_ISSET(gpm_fd, &rfds))
5570 *check_for_gpm = 1;
5571 }
5572# endif
5573# ifdef USE_XSMP
5574 if (ret > 0 && xsmp_icefd != -1)
5575 {
5576 if (FD_ISSET(xsmp_icefd, &efds))
5577 {
5578 if (p_verbose > 0)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00005579 verb_msg((char_u *)_("XSMP lost ICE connection"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005580 xsmp_close();
5581 if (--ret == 0)
5582 finished = FALSE; /* keep going if event was only one */
5583 }
5584 else if (FD_ISSET(xsmp_icefd, &rfds))
5585 {
5586 busy = TRUE;
5587 xsmp_handle_requests();
5588 busy = FALSE;
5589 if (--ret == 0)
5590 finished = FALSE; /* keep going if event was only one */
5591 }
5592 }
5593# endif
Bram Moolenaar67c53842010-05-22 18:28:27 +02005594#ifdef FEAT_NETBEANS_INTG
5595 if (ret > 0 && nb_fd != -1 && FD_ISSET(nb_fd, &rfds))
5596 {
5597 netbeans_read();
5598 --ret;
5599 }
5600#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005601
5602#endif /* HAVE_SELECT */
5603
5604#ifdef MAY_LOOP
5605 if (finished || msec == 0)
5606 break;
5607
Bram Moolenaar93c88e02015-09-15 14:12:05 +02005608# ifdef FEAT_CLIENTSERVER
5609 if (server_waiting())
5610 break;
5611# endif
5612
Bram Moolenaar071d4272004-06-13 20:20:40 +00005613 /* We're going to loop around again, find out for how long */
5614 if (msec > 0)
5615 {
5616# ifdef USE_START_TV
5617 struct timeval mtv;
5618
5619 /* Compute remaining wait time. */
5620 gettimeofday(&mtv, NULL);
5621 msec -= (mtv.tv_sec - start_tv.tv_sec) * 1000L
5622 + (mtv.tv_usec - start_tv.tv_usec) / 1000L;
5623# else
5624 /* Guess we got interrupted halfway. */
5625 msec = msec / 2;
5626# endif
5627 if (msec <= 0)
5628 break; /* waited long enough */
5629 }
5630#endif
5631 }
5632
5633 return (ret > 0);
5634}
5635
Bram Moolenaar071d4272004-06-13 20:20:40 +00005636#ifndef NO_EXPANDPATH
Bram Moolenaar071d4272004-06-13 20:20:40 +00005637/*
Bram Moolenaar02743632005-07-25 20:42:36 +00005638 * Expand a path into all matching files and/or directories. Handles "*",
5639 * "?", "[a-z]", "**", etc.
5640 * "path" has backslashes before chars that are not to be expanded.
5641 * Returns the number of matches found.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005642 */
5643 int
5644mch_expandpath(gap, path, flags)
5645 garray_T *gap;
5646 char_u *path;
5647 int flags; /* EW_* flags */
5648{
Bram Moolenaar02743632005-07-25 20:42:36 +00005649 return unix_expandpath(gap, path, 0, flags, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005650}
5651#endif
5652
5653/*
5654 * mch_expand_wildcards() - this code does wild-card pattern matching using
5655 * the shell
5656 *
5657 * return OK for success, FAIL for error (you may lose some memory) and put
5658 * an error message in *file.
5659 *
5660 * num_pat is number of input patterns
5661 * pat is array of pointers to input patterns
5662 * num_file is pointer to number of matched file names
5663 * file is pointer to array of pointers to matched file names
5664 */
5665
5666#ifndef SEEK_SET
5667# define SEEK_SET 0
5668#endif
5669#ifndef SEEK_END
5670# define SEEK_END 2
5671#endif
5672
Bram Moolenaar5555acc2006-04-07 21:33:12 +00005673#define SHELL_SPECIAL (char_u *)"\t \"&'$;<>()\\|"
Bram Moolenaar316059c2006-01-14 21:18:42 +00005674
Bram Moolenaar071d4272004-06-13 20:20:40 +00005675 int
5676mch_expand_wildcards(num_pat, pat, num_file, file, flags)
5677 int num_pat;
5678 char_u **pat;
5679 int *num_file;
5680 char_u ***file;
5681 int flags; /* EW_* flags */
5682{
5683 int i;
5684 size_t len;
5685 char_u *p;
5686 int dir;
5687#ifdef __EMX__
Bram Moolenaarc7247912008-01-13 12:54:11 +00005688 /*
5689 * This is the OS/2 implementation.
5690 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005691# define EXPL_ALLOC_INC 16
5692 char_u **expl_files;
5693 size_t files_alloced, files_free;
5694 char_u *buf;
5695 int has_wildcard;
5696
5697 *num_file = 0; /* default: no files found */
5698 files_alloced = EXPL_ALLOC_INC; /* how much space is allocated */
5699 files_free = EXPL_ALLOC_INC; /* how much space is not used */
5700 *file = (char_u **)alloc(sizeof(char_u **) * files_alloced);
5701 if (*file == NULL)
5702 return FAIL;
5703
5704 for (; num_pat > 0; num_pat--, pat++)
5705 {
5706 expl_files = NULL;
5707 if (vim_strchr(*pat, '$') || vim_strchr(*pat, '~'))
5708 /* expand environment var or home dir */
5709 buf = expand_env_save(*pat);
5710 else
5711 buf = vim_strsave(*pat);
5712 expl_files = NULL;
Bram Moolenaard8b02732005-01-14 21:48:43 +00005713 has_wildcard = mch_has_exp_wildcard(buf); /* (still) wildcards? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005714 if (has_wildcard) /* yes, so expand them */
5715 expl_files = (char_u **)_fnexplode(buf);
5716
5717 /*
5718 * return value of buf if no wildcards left,
5719 * OR if no match AND EW_NOTFOUND is set.
5720 */
5721 if ((!has_wildcard && ((flags & EW_NOTFOUND) || mch_getperm(buf) >= 0))
5722 || (expl_files == NULL && (flags & EW_NOTFOUND)))
5723 { /* simply save the current contents of *buf */
5724 expl_files = (char_u **)alloc(sizeof(char_u **) * 2);
5725 if (expl_files != NULL)
5726 {
5727 expl_files[0] = vim_strsave(buf);
5728 expl_files[1] = NULL;
5729 }
5730 }
5731 vim_free(buf);
5732
5733 /*
5734 * Count number of names resulting from expansion,
5735 * At the same time add a backslash to the end of names that happen to
5736 * be directories, and replace slashes with backslashes.
5737 */
5738 if (expl_files)
5739 {
5740 for (i = 0; (p = expl_files[i]) != NULL; i++)
5741 {
5742 dir = mch_isdir(p);
5743 /* If we don't want dirs and this is one, skip it */
5744 if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
5745 continue;
5746
Bram Moolenaara2031822006-03-07 22:29:51 +00005747 /* Skip files that are not executable if we check for that. */
Bram Moolenaarb5971142015-03-21 17:32:19 +01005748 if (!dir && (flags & EW_EXEC)
5749 && !mch_can_exe(p, NULL, !(flags & EW_SHELLCMD)))
Bram Moolenaara2031822006-03-07 22:29:51 +00005750 continue;
5751
Bram Moolenaar071d4272004-06-13 20:20:40 +00005752 if (--files_free == 0)
5753 {
5754 /* need more room in table of pointers */
5755 files_alloced += EXPL_ALLOC_INC;
5756 *file = (char_u **)vim_realloc(*file,
5757 sizeof(char_u **) * files_alloced);
5758 if (*file == NULL)
5759 {
5760 EMSG(_(e_outofmem));
5761 *num_file = 0;
5762 return FAIL;
5763 }
5764 files_free = EXPL_ALLOC_INC;
5765 }
5766 slash_adjust(p);
5767 if (dir)
5768 {
5769 /* For a directory we add a '/', unless it's already
5770 * there. */
5771 len = STRLEN(p);
5772 if (((*file)[*num_file] = alloc(len + 2)) != NULL)
5773 {
5774 STRCPY((*file)[*num_file], p);
Bram Moolenaar654b5b52006-06-22 17:47:10 +00005775 if (!after_pathsep((*file)[*num_file],
5776 (*file)[*num_file] + len))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005777 {
5778 (*file)[*num_file][len] = psepc;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00005779 (*file)[*num_file][len + 1] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005780 }
5781 }
5782 }
5783 else
5784 {
5785 (*file)[*num_file] = vim_strsave(p);
5786 }
5787
5788 /*
5789 * Error message already given by either alloc or vim_strsave.
5790 * Should return FAIL, but returning OK works also.
5791 */
5792 if ((*file)[*num_file] == NULL)
5793 break;
5794 (*num_file)++;
5795 }
5796 _fnexplodefree((char **)expl_files);
5797 }
5798 }
5799 return OK;
5800
5801#else /* __EMX__ */
Bram Moolenaarc7247912008-01-13 12:54:11 +00005802 /*
5803 * This is the non-OS/2 implementation (really Unix).
5804 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005805 int j;
5806 char_u *tempname;
5807 char_u *command;
5808 FILE *fd;
5809 char_u *buffer;
Bram Moolenaarc7247912008-01-13 12:54:11 +00005810#define STYLE_ECHO 0 /* use "echo", the default */
5811#define STYLE_GLOB 1 /* use "glob", for csh */
5812#define STYLE_VIMGLOB 2 /* use "vimglob", for Posix sh */
5813#define STYLE_PRINT 3 /* use "print -N", for zsh */
5814#define STYLE_BT 4 /* `cmd` expansion, execute the pattern
5815 * directly */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005816 int shell_style = STYLE_ECHO;
5817 int check_spaces;
5818 static int did_find_nul = FALSE;
5819 int ampersent = FALSE;
Bram Moolenaarc7247912008-01-13 12:54:11 +00005820 /* vimglob() function to define for Posix shell */
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00005821 static char *sh_vimglob_func = "vimglob() { while [ $# -ge 1 ]; do echo \"$1\"; shift; done }; vimglob >";
Bram Moolenaar071d4272004-06-13 20:20:40 +00005822
5823 *num_file = 0; /* default: no files found */
5824 *file = NULL;
5825
5826 /*
5827 * If there are no wildcards, just copy the names to allocated memory.
5828 * Saves a lot of time, because we don't have to start a new shell.
5829 */
5830 if (!have_wildcard(num_pat, pat))
5831 return save_patterns(num_pat, pat, num_file, file);
5832
Bram Moolenaar0e634da2005-07-20 21:57:28 +00005833# ifdef HAVE_SANDBOX
5834 /* Don't allow any shell command in the sandbox. */
5835 if (sandbox != 0 && check_secure())
5836 return FAIL;
5837# endif
5838
Bram Moolenaar071d4272004-06-13 20:20:40 +00005839 /*
5840 * Don't allow the use of backticks in secure and restricted mode.
5841 */
Bram Moolenaar0e634da2005-07-20 21:57:28 +00005842 if (secure || restricted)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005843 for (i = 0; i < num_pat; ++i)
5844 if (vim_strchr(pat[i], '`') != NULL
5845 && (check_restricted() || check_secure()))
5846 return FAIL;
5847
5848 /*
5849 * get a name for the temp file
5850 */
Bram Moolenaare5c421c2015-03-31 13:33:08 +02005851 if ((tempname = vim_tempname('o', FALSE)) == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005852 {
5853 EMSG(_(e_notmp));
5854 return FAIL;
5855 }
5856
5857 /*
5858 * Let the shell expand the patterns and write the result into the temp
Bram Moolenaarc7247912008-01-13 12:54:11 +00005859 * file.
5860 * STYLE_BT: NL separated
5861 * If expanding `cmd` execute it directly.
5862 * STYLE_GLOB: NUL separated
5863 * If we use *csh, "glob" will work better than "echo".
5864 * STYLE_PRINT: NL or NUL separated
5865 * If we use *zsh, "print -N" will work better than "glob".
5866 * STYLE_VIMGLOB: NL separated
5867 * If we use *sh*, we define "vimglob()".
5868 * STYLE_ECHO: space separated.
5869 * A shell we don't know, stay safe and use "echo".
Bram Moolenaar071d4272004-06-13 20:20:40 +00005870 */
5871 if (num_pat == 1 && *pat[0] == '`'
5872 && (len = STRLEN(pat[0])) > 2
5873 && *(pat[0] + len - 1) == '`')
5874 shell_style = STYLE_BT;
5875 else if ((len = STRLEN(p_sh)) >= 3)
5876 {
5877 if (STRCMP(p_sh + len - 3, "csh") == 0)
5878 shell_style = STYLE_GLOB;
5879 else if (STRCMP(p_sh + len - 3, "zsh") == 0)
5880 shell_style = STYLE_PRINT;
5881 }
Bram Moolenaarc7247912008-01-13 12:54:11 +00005882 if (shell_style == STYLE_ECHO && strstr((char *)gettail(p_sh),
5883 "sh") != NULL)
5884 shell_style = STYLE_VIMGLOB;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005885
Bram Moolenaarc7247912008-01-13 12:54:11 +00005886 /* Compute the length of the command. We need 2 extra bytes: for the
5887 * optional '&' and for the NUL.
5888 * Worst case: "unset nonomatch; print -N >" plus two is 29 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005889 len = STRLEN(tempname) + 29;
Bram Moolenaarc7247912008-01-13 12:54:11 +00005890 if (shell_style == STYLE_VIMGLOB)
5891 len += STRLEN(sh_vimglob_func);
5892
Bram Moolenaarb23c3382005-01-31 19:09:12 +00005893 for (i = 0; i < num_pat; ++i)
5894 {
5895 /* Count the length of the patterns in the same way as they are put in
5896 * "command" below. */
5897#ifdef USE_SYSTEM
Bram Moolenaar071d4272004-06-13 20:20:40 +00005898 len += STRLEN(pat[i]) + 3; /* add space and two quotes */
Bram Moolenaarb23c3382005-01-31 19:09:12 +00005899#else
5900 ++len; /* add space */
Bram Moolenaar316059c2006-01-14 21:18:42 +00005901 for (j = 0; pat[i][j] != NUL; ++j)
5902 {
5903 if (vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL)
5904 ++len; /* may add a backslash */
5905 ++len;
5906 }
Bram Moolenaarb23c3382005-01-31 19:09:12 +00005907#endif
5908 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005909 command = alloc(len);
5910 if (command == NULL)
5911 {
5912 /* out of memory */
5913 vim_free(tempname);
5914 return FAIL;
5915 }
5916
5917 /*
5918 * Build the shell command:
5919 * - Set $nonomatch depending on EW_NOTFOUND (hopefully the shell
5920 * recognizes this).
5921 * - Add the shell command to print the expanded names.
5922 * - Add the temp file name.
5923 * - Add the file name patterns.
5924 */
5925 if (shell_style == STYLE_BT)
5926 {
Bram Moolenaar316059c2006-01-14 21:18:42 +00005927 /* change `command; command& ` to (command; command ) */
5928 STRCPY(command, "(");
5929 STRCAT(command, pat[0] + 1); /* exclude first backtick */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005930 p = command + STRLEN(command) - 1;
Bram Moolenaar316059c2006-01-14 21:18:42 +00005931 *p-- = ')'; /* remove last backtick */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005932 while (p > command && vim_iswhite(*p))
5933 --p;
5934 if (*p == '&') /* remove trailing '&' */
5935 {
5936 ampersent = TRUE;
5937 *p = ' ';
5938 }
5939 STRCAT(command, ">");
5940 }
5941 else
5942 {
5943 if (flags & EW_NOTFOUND)
5944 STRCPY(command, "set nonomatch; ");
5945 else
5946 STRCPY(command, "unset nonomatch; ");
5947 if (shell_style == STYLE_GLOB)
5948 STRCAT(command, "glob >");
5949 else if (shell_style == STYLE_PRINT)
5950 STRCAT(command, "print -N >");
Bram Moolenaarc7247912008-01-13 12:54:11 +00005951 else if (shell_style == STYLE_VIMGLOB)
5952 STRCAT(command, sh_vimglob_func);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005953 else
5954 STRCAT(command, "echo >");
5955 }
Bram Moolenaarc7247912008-01-13 12:54:11 +00005956
Bram Moolenaar071d4272004-06-13 20:20:40 +00005957 STRCAT(command, tempname);
Bram Moolenaarc7247912008-01-13 12:54:11 +00005958
Bram Moolenaar071d4272004-06-13 20:20:40 +00005959 if (shell_style != STYLE_BT)
5960 for (i = 0; i < num_pat; ++i)
5961 {
5962 /* When using system() always add extra quotes, because the shell
Bram Moolenaar316059c2006-01-14 21:18:42 +00005963 * is started twice. Otherwise put a backslash before special
Bram Moolenaarc2a27c32007-12-01 16:19:33 +00005964 * characters, except inside ``. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005965#ifdef USE_SYSTEM
5966 STRCAT(command, " \"");
5967 STRCAT(command, pat[i]);
5968 STRCAT(command, "\"");
5969#else
Bram Moolenaar582fd852005-03-28 20:58:01 +00005970 int intick = FALSE;
5971
Bram Moolenaar071d4272004-06-13 20:20:40 +00005972 p = command + STRLEN(command);
5973 *p++ = ' ';
Bram Moolenaar316059c2006-01-14 21:18:42 +00005974 for (j = 0; pat[i][j] != NUL; ++j)
Bram Moolenaar582fd852005-03-28 20:58:01 +00005975 {
5976 if (pat[i][j] == '`')
Bram Moolenaar582fd852005-03-28 20:58:01 +00005977 intick = !intick;
Bram Moolenaar316059c2006-01-14 21:18:42 +00005978 else if (pat[i][j] == '\\' && pat[i][j + 1] != NUL)
5979 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +00005980 /* Remove a backslash, take char literally. But keep
Bram Moolenaar49315f62006-02-04 00:54:59 +00005981 * backslash inside backticks, before a special character
5982 * and before a backtick. */
Bram Moolenaard12f5c12006-01-25 22:10:52 +00005983 if (intick
Bram Moolenaar49315f62006-02-04 00:54:59 +00005984 || vim_strchr(SHELL_SPECIAL, pat[i][j + 1]) != NULL
5985 || pat[i][j + 1] == '`')
Bram Moolenaard12f5c12006-01-25 22:10:52 +00005986 *p++ = '\\';
Bram Moolenaar280f1262006-01-30 00:14:18 +00005987 ++j;
Bram Moolenaar316059c2006-01-14 21:18:42 +00005988 }
Bram Moolenaare4df1642014-08-29 12:58:44 +02005989 else if (!intick
5990 && ((flags & EW_KEEPDOLLAR) == 0 || pat[i][j] != '$')
5991 && vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL)
Bram Moolenaar316059c2006-01-14 21:18:42 +00005992 /* Put a backslash before a special character, but not
Bram Moolenaare4df1642014-08-29 12:58:44 +02005993 * when inside ``. And not for $var when EW_KEEPDOLLAR is
5994 * set. */
Bram Moolenaar316059c2006-01-14 21:18:42 +00005995 *p++ = '\\';
Bram Moolenaar280f1262006-01-30 00:14:18 +00005996
5997 /* Copy one character. */
5998 *p++ = pat[i][j];
Bram Moolenaar582fd852005-03-28 20:58:01 +00005999 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006000 *p = NUL;
6001#endif
6002 }
6003 if (flags & EW_SILENT)
6004 show_shell_mess = FALSE;
6005 if (ampersent)
Bram Moolenaarc7247912008-01-13 12:54:11 +00006006 STRCAT(command, "&"); /* put the '&' after the redirection */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006007
6008 /*
6009 * Using zsh -G: If a pattern has no matches, it is just deleted from
6010 * the argument list, otherwise zsh gives an error message and doesn't
6011 * expand any other pattern.
6012 */
6013 if (shell_style == STYLE_PRINT)
6014 extra_shell_arg = (char_u *)"-G"; /* Use zsh NULL_GLOB option */
6015
6016 /*
6017 * If we use -f then shell variables set in .cshrc won't get expanded.
6018 * vi can do it, so we will too, but it is only necessary if there is a "$"
6019 * in one of the patterns, otherwise we can still use the fast option.
6020 */
6021 else if (shell_style == STYLE_GLOB && !have_dollars(num_pat, pat))
6022 extra_shell_arg = (char_u *)"-f"; /* Use csh fast option */
6023
6024 /*
6025 * execute the shell command
6026 */
6027 i = call_shell(command, SHELL_EXPAND | SHELL_SILENT);
6028
6029 /* When running in the background, give it some time to create the temp
6030 * file, but don't wait for it to finish. */
6031 if (ampersent)
6032 mch_delay(10L, TRUE);
6033
6034 extra_shell_arg = NULL; /* cleanup */
6035 show_shell_mess = TRUE;
6036 vim_free(command);
6037
Bram Moolenaarc7247912008-01-13 12:54:11 +00006038 if (i != 0) /* mch_call_shell() failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006039 {
6040 mch_remove(tempname);
6041 vim_free(tempname);
6042 /*
6043 * With interactive completion, the error message is not printed.
6044 * However with USE_SYSTEM, I don't know how to turn off error messages
6045 * from the shell, so screen may still get messed up -- webb.
6046 */
6047#ifndef USE_SYSTEM
6048 if (!(flags & EW_SILENT))
6049#endif
6050 {
6051 redraw_later_clear(); /* probably messed up screen */
6052 msg_putchar('\n'); /* clear bottom line quickly */
6053 cmdline_row = Rows - 1; /* continue on last line */
6054#ifdef USE_SYSTEM
6055 if (!(flags & EW_SILENT))
6056#endif
6057 {
6058 MSG(_(e_wildexpand));
6059 msg_start(); /* don't overwrite this message */
6060 }
6061 }
6062 /* If a `cmd` expansion failed, don't list `cmd` as a match, even when
6063 * EW_NOTFOUND is given */
6064 if (shell_style == STYLE_BT)
6065 return FAIL;
6066 goto notfound;
6067 }
6068
6069 /*
6070 * read the names from the file into memory
6071 */
6072 fd = fopen((char *)tempname, READBIN);
6073 if (fd == NULL)
6074 {
6075 /* Something went wrong, perhaps a file name with a special char. */
6076 if (!(flags & EW_SILENT))
6077 {
6078 MSG(_(e_wildexpand));
6079 msg_start(); /* don't overwrite this message */
6080 }
6081 vim_free(tempname);
6082 goto notfound;
6083 }
6084 fseek(fd, 0L, SEEK_END);
6085 len = ftell(fd); /* get size of temp file */
6086 fseek(fd, 0L, SEEK_SET);
6087 buffer = alloc(len + 1);
6088 if (buffer == NULL)
6089 {
6090 /* out of memory */
6091 mch_remove(tempname);
6092 vim_free(tempname);
6093 fclose(fd);
6094 return FAIL;
6095 }
6096 i = fread((char *)buffer, 1, len, fd);
6097 fclose(fd);
6098 mch_remove(tempname);
Bram Moolenaar78a15312009-05-15 19:33:18 +00006099 if (i != (int)len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006100 {
6101 /* unexpected read error */
6102 EMSG2(_(e_notread), tempname);
6103 vim_free(tempname);
6104 vim_free(buffer);
6105 return FAIL;
6106 }
6107 vim_free(tempname);
6108
Bram Moolenaarc7247912008-01-13 12:54:11 +00006109# if defined(__CYGWIN__) || defined(__CYGWIN32__)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006110 /* Translate <CR><NL> into <NL>. Caution, buffer may contain NUL. */
6111 p = buffer;
Bram Moolenaarfe17e762013-06-29 14:17:02 +02006112 for (i = 0; i < (int)len; ++i)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006113 if (!(buffer[i] == CAR && buffer[i + 1] == NL))
6114 *p++ = buffer[i];
6115 len = p - buffer;
6116# endif
6117
6118
6119 /* file names are separated with Space */
6120 if (shell_style == STYLE_ECHO)
6121 {
6122 buffer[len] = '\n'; /* make sure the buffer ends in NL */
6123 p = buffer;
6124 for (i = 0; *p != '\n'; ++i) /* count number of entries */
6125 {
6126 while (*p != ' ' && *p != '\n')
6127 ++p;
6128 p = skipwhite(p); /* skip to next entry */
6129 }
6130 }
6131 /* file names are separated with NL */
Bram Moolenaarc7247912008-01-13 12:54:11 +00006132 else if (shell_style == STYLE_BT || shell_style == STYLE_VIMGLOB)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006133 {
6134 buffer[len] = NUL; /* make sure the buffer ends in NUL */
6135 p = buffer;
6136 for (i = 0; *p != NUL; ++i) /* count number of entries */
6137 {
6138 while (*p != '\n' && *p != NUL)
6139 ++p;
6140 if (*p != NUL)
6141 ++p;
6142 p = skipwhite(p); /* skip leading white space */
6143 }
6144 }
6145 /* file names are separated with NUL */
6146 else
6147 {
6148 /*
6149 * Some versions of zsh use spaces instead of NULs to separate
6150 * results. Only do this when there is no NUL before the end of the
6151 * buffer, otherwise we would never be able to use file names with
6152 * embedded spaces when zsh does use NULs.
6153 * When we found a NUL once, we know zsh is OK, set did_find_nul and
6154 * don't check for spaces again.
6155 */
6156 check_spaces = FALSE;
6157 if (shell_style == STYLE_PRINT && !did_find_nul)
6158 {
6159 /* If there is a NUL, set did_find_nul, else set check_spaces */
Bram Moolenaaref9d6aa2011-04-11 16:56:35 +02006160 buffer[len] = NUL;
Bram Moolenaarb011af92013-12-11 13:21:51 +01006161 if (len && (int)STRLEN(buffer) < (int)len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006162 did_find_nul = TRUE;
6163 else
6164 check_spaces = TRUE;
6165 }
6166
6167 /*
6168 * Make sure the buffer ends with a NUL. For STYLE_PRINT there
6169 * already is one, for STYLE_GLOB it needs to be added.
6170 */
6171 if (len && buffer[len - 1] == NUL)
6172 --len;
6173 else
6174 buffer[len] = NUL;
6175 i = 0;
6176 for (p = buffer; p < buffer + len; ++p)
6177 if (*p == NUL || (*p == ' ' && check_spaces)) /* count entry */
6178 {
6179 ++i;
6180 *p = NUL;
6181 }
6182 if (len)
6183 ++i; /* count last entry */
6184 }
6185 if (i == 0)
6186 {
6187 /*
6188 * Can happen when using /bin/sh and typing ":e $NO_SUCH_VAR^I".
6189 * /bin/sh will happily expand it to nothing rather than returning an
6190 * error; and hey, it's good to check anyway -- webb.
6191 */
6192 vim_free(buffer);
6193 goto notfound;
6194 }
6195 *num_file = i;
6196 *file = (char_u **)alloc(sizeof(char_u *) * i);
6197 if (*file == NULL)
6198 {
6199 /* out of memory */
6200 vim_free(buffer);
6201 return FAIL;
6202 }
6203
6204 /*
6205 * Isolate the individual file names.
6206 */
6207 p = buffer;
6208 for (i = 0; i < *num_file; ++i)
6209 {
6210 (*file)[i] = p;
6211 /* Space or NL separates */
Bram Moolenaarc7247912008-01-13 12:54:11 +00006212 if (shell_style == STYLE_ECHO || shell_style == STYLE_BT
6213 || shell_style == STYLE_VIMGLOB)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006214 {
Bram Moolenaar49315f62006-02-04 00:54:59 +00006215 while (!(shell_style == STYLE_ECHO && *p == ' ')
6216 && *p != '\n' && *p != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006217 ++p;
6218 if (p == buffer + len) /* last entry */
6219 *p = NUL;
6220 else
6221 {
6222 *p++ = NUL;
6223 p = skipwhite(p); /* skip to next entry */
6224 }
6225 }
6226 else /* NUL separates */
6227 {
6228 while (*p && p < buffer + len) /* skip entry */
6229 ++p;
6230 ++p; /* skip NUL */
6231 }
6232 }
6233
6234 /*
6235 * Move the file names to allocated memory.
6236 */
6237 for (j = 0, i = 0; i < *num_file; ++i)
6238 {
6239 /* Require the files to exist. Helps when using /bin/sh */
6240 if (!(flags & EW_NOTFOUND) && mch_getperm((*file)[i]) < 0)
6241 continue;
6242
6243 /* check if this entry should be included */
6244 dir = (mch_isdir((*file)[i]));
6245 if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
6246 continue;
6247
Bram Moolenaara2031822006-03-07 22:29:51 +00006248 /* Skip files that are not executable if we check for that. */
Bram Moolenaarb5971142015-03-21 17:32:19 +01006249 if (!dir && (flags & EW_EXEC)
6250 && !mch_can_exe((*file)[i], NULL, !(flags & EW_SHELLCMD)))
Bram Moolenaara2031822006-03-07 22:29:51 +00006251 continue;
6252
Bram Moolenaar071d4272004-06-13 20:20:40 +00006253 p = alloc((unsigned)(STRLEN((*file)[i]) + 1 + dir));
6254 if (p)
6255 {
6256 STRCPY(p, (*file)[i]);
6257 if (dir)
Bram Moolenaarb2389092008-01-03 17:56:04 +00006258 add_pathsep(p); /* add '/' to a directory name */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006259 (*file)[j++] = p;
6260 }
6261 }
6262 vim_free(buffer);
6263 *num_file = j;
6264
6265 if (*num_file == 0) /* rejected all entries */
6266 {
6267 vim_free(*file);
6268 *file = NULL;
6269 goto notfound;
6270 }
6271
6272 return OK;
6273
6274notfound:
6275 if (flags & EW_NOTFOUND)
6276 return save_patterns(num_pat, pat, num_file, file);
6277 return FAIL;
6278
6279#endif /* __EMX__ */
6280}
6281
6282#endif /* VMS */
6283
6284#ifndef __EMX__
6285 static int
6286save_patterns(num_pat, pat, num_file, file)
6287 int num_pat;
6288 char_u **pat;
6289 int *num_file;
6290 char_u ***file;
6291{
6292 int i;
Bram Moolenaard8b02732005-01-14 21:48:43 +00006293 char_u *s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006294
6295 *file = (char_u **)alloc(num_pat * sizeof(char_u *));
6296 if (*file == NULL)
6297 return FAIL;
6298 for (i = 0; i < num_pat; i++)
Bram Moolenaard8b02732005-01-14 21:48:43 +00006299 {
6300 s = vim_strsave(pat[i]);
6301 if (s != NULL)
6302 /* Be compatible with expand_filename(): halve the number of
6303 * backslashes. */
6304 backslash_halve(s);
6305 (*file)[i] = s;
6306 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006307 *num_file = num_pat;
6308 return OK;
6309}
6310#endif
6311
Bram Moolenaar071d4272004-06-13 20:20:40 +00006312/*
6313 * Return TRUE if the string "p" contains a wildcard that mch_expandpath() can
6314 * expand.
6315 */
6316 int
6317mch_has_exp_wildcard(p)
6318 char_u *p;
6319{
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00006320 for ( ; *p; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006321 {
6322#ifndef OS2
6323 if (*p == '\\' && p[1] != NUL)
6324 ++p;
6325 else
6326#endif
6327 if (vim_strchr((char_u *)
6328#ifdef VMS
6329 "*?%"
6330#else
6331# ifdef OS2
6332 "*?"
6333# else
6334 "*?[{'"
6335# endif
6336#endif
6337 , *p) != NULL)
6338 return TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006339 }
6340 return FALSE;
6341}
6342
6343/*
6344 * Return TRUE if the string "p" contains a wildcard.
6345 * Don't recognize '~' at the end as a wildcard.
6346 */
6347 int
6348mch_has_wildcard(p)
6349 char_u *p;
6350{
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00006351 for ( ; *p; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006352 {
6353#ifndef OS2
6354 if (*p == '\\' && p[1] != NUL)
6355 ++p;
6356 else
6357#endif
6358 if (vim_strchr((char_u *)
6359#ifdef VMS
6360 "*?%$"
6361#else
6362# ifdef OS2
6363# ifdef VIM_BACKTICK
6364 "*?$`"
6365# else
6366 "*?$"
6367# endif
6368# else
6369 "*?[{`'$"
6370# endif
6371#endif
6372 , *p) != NULL
6373 || (*p == '~' && p[1] != NUL))
6374 return TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006375 }
6376 return FALSE;
6377}
6378
6379#ifndef __EMX__
6380 static int
6381have_wildcard(num, file)
6382 int num;
6383 char_u **file;
6384{
6385 int i;
6386
6387 for (i = 0; i < num; i++)
6388 if (mch_has_wildcard(file[i]))
6389 return 1;
6390 return 0;
6391}
6392
6393 static int
6394have_dollars(num, file)
6395 int num;
6396 char_u **file;
6397{
6398 int i;
6399
6400 for (i = 0; i < num; i++)
6401 if (vim_strchr(file[i], '$') != NULL)
6402 return TRUE;
6403 return FALSE;
6404}
6405#endif /* ifndef __EMX__ */
6406
6407#ifndef HAVE_RENAME
6408/*
6409 * Scaled-down version of rename(), which is missing in Xenix.
6410 * This version can only move regular files and will fail if the
6411 * destination exists.
6412 */
6413 int
6414mch_rename(src, dest)
6415 const char *src, *dest;
6416{
6417 struct stat st;
6418
6419 if (stat(dest, &st) >= 0) /* fail if destination exists */
6420 return -1;
6421 if (link(src, dest) != 0) /* link file to new name */
6422 return -1;
6423 if (mch_remove(src) == 0) /* delete link to old name */
6424 return 0;
6425 return -1;
6426}
6427#endif /* !HAVE_RENAME */
6428
6429#ifdef FEAT_MOUSE_GPM
6430/*
6431 * Initializes connection with gpm (if it isn't already opened)
6432 * Return 1 if succeeded (or connection already opened), 0 if failed
6433 */
6434 static int
6435gpm_open()
6436{
6437 static Gpm_Connect gpm_connect; /* Must it be kept till closing ? */
6438
6439 if (!gpm_flag)
6440 {
6441 gpm_connect.eventMask = (GPM_UP | GPM_DRAG | GPM_DOWN);
6442 gpm_connect.defaultMask = ~GPM_HARD;
6443 /* Default handling for mouse move*/
6444 gpm_connect.minMod = 0; /* Handle any modifier keys */
6445 gpm_connect.maxMod = 0xffff;
6446 if (Gpm_Open(&gpm_connect, 0) > 0)
6447 {
6448 /* gpm library tries to handling TSTP causes
6449 * problems. Anyways, we close connection to Gpm whenever
6450 * we are going to suspend or starting an external process
Bram Moolenaarc2a27c32007-12-01 16:19:33 +00006451 * so we shouldn't have problem with this
Bram Moolenaar071d4272004-06-13 20:20:40 +00006452 */
Bram Moolenaar76243bd2009-03-02 01:47:02 +00006453# ifdef SIGTSTP
Bram Moolenaar071d4272004-06-13 20:20:40 +00006454 signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
Bram Moolenaar76243bd2009-03-02 01:47:02 +00006455# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006456 return 1; /* succeed */
6457 }
6458 if (gpm_fd == -2)
6459 Gpm_Close(); /* We don't want to talk to xterm via gpm */
6460 return 0;
6461 }
6462 return 1; /* already open */
6463}
6464
6465/*
6466 * Closes connection to gpm
Bram Moolenaar071d4272004-06-13 20:20:40 +00006467 */
6468 static void
6469gpm_close()
6470{
6471 if (gpm_flag && gpm_fd >= 0) /* if Open */
6472 Gpm_Close();
6473}
6474
6475/* Reads gpm event and adds special keys to input buf. Returns length of
6476 * generated key sequence.
Bram Moolenaarc7f02552014-04-01 21:00:59 +02006477 * This function is styled after gui_send_mouse_event().
Bram Moolenaar071d4272004-06-13 20:20:40 +00006478 */
6479 static int
6480mch_gpm_process()
6481{
6482 int button;
6483 static Gpm_Event gpm_event;
6484 char_u string[6];
6485 int_u vim_modifiers;
6486 int row,col;
6487 unsigned char buttons_mask;
6488 unsigned char gpm_modifiers;
6489 static unsigned char old_buttons = 0;
6490
6491 Gpm_GetEvent(&gpm_event);
6492
6493#ifdef FEAT_GUI
6494 /* Don't put events in the input queue now. */
6495 if (hold_gui_events)
6496 return 0;
6497#endif
6498
6499 row = gpm_event.y - 1;
6500 col = gpm_event.x - 1;
6501
6502 string[0] = ESC; /* Our termcode */
6503 string[1] = 'M';
6504 string[2] = 'G';
6505 switch (GPM_BARE_EVENTS(gpm_event.type))
6506 {
6507 case GPM_DRAG:
6508 string[3] = MOUSE_DRAG;
6509 break;
6510 case GPM_DOWN:
6511 buttons_mask = gpm_event.buttons & ~old_buttons;
6512 old_buttons = gpm_event.buttons;
6513 switch (buttons_mask)
6514 {
6515 case GPM_B_LEFT:
6516 button = MOUSE_LEFT;
6517 break;
6518 case GPM_B_MIDDLE:
6519 button = MOUSE_MIDDLE;
6520 break;
6521 case GPM_B_RIGHT:
6522 button = MOUSE_RIGHT;
6523 break;
6524 default:
6525 return 0;
6526 /*Don't know what to do. Can more than one button be
6527 * reported in one event? */
6528 }
6529 string[3] = (char_u)(button | 0x20);
6530 SET_NUM_MOUSE_CLICKS(string[3], gpm_event.clicks + 1);
6531 break;
6532 case GPM_UP:
6533 string[3] = MOUSE_RELEASE;
6534 old_buttons &= ~gpm_event.buttons;
6535 break;
6536 default:
6537 return 0;
6538 }
6539 /*This code is based on gui_x11_mouse_cb in gui_x11.c */
6540 gpm_modifiers = gpm_event.modifiers;
6541 vim_modifiers = 0x0;
6542 /* I ignore capslock stats. Aren't we all just hate capslock mixing with
6543 * Vim commands ? Besides, gpm_event.modifiers is unsigned char, and
6544 * K_CAPSSHIFT is defined 8, so it probably isn't even reported
6545 */
6546 if (gpm_modifiers & ((1 << KG_SHIFT) | (1 << KG_SHIFTR) | (1 << KG_SHIFTL)))
6547 vim_modifiers |= MOUSE_SHIFT;
6548
6549 if (gpm_modifiers & ((1 << KG_CTRL) | (1 << KG_CTRLR) | (1 << KG_CTRLL)))
6550 vim_modifiers |= MOUSE_CTRL;
6551 if (gpm_modifiers & ((1 << KG_ALT) | (1 << KG_ALTGR)))
6552 vim_modifiers |= MOUSE_ALT;
6553 string[3] |= vim_modifiers;
6554 string[4] = (char_u)(col + ' ' + 1);
6555 string[5] = (char_u)(row + ' ' + 1);
6556 add_to_input_buf(string, 6);
6557 return 6;
6558}
6559#endif /* FEAT_MOUSE_GPM */
6560
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00006561#ifdef FEAT_SYSMOUSE
6562/*
6563 * Initialize connection with sysmouse.
6564 * Let virtual console inform us with SIGUSR2 for pending sysmouse
6565 * output, any sysmouse output than will be processed via sig_sysmouse().
6566 * Return OK if succeeded, FAIL if failed.
6567 */
6568 static int
6569sysmouse_open()
6570{
6571 struct mouse_info mouse;
6572
6573 mouse.operation = MOUSE_MODE;
6574 mouse.u.mode.mode = 0;
6575 mouse.u.mode.signal = SIGUSR2;
6576 if (ioctl(1, CONS_MOUSECTL, &mouse) != -1)
6577 {
6578 signal(SIGUSR2, (RETSIGTYPE (*)())sig_sysmouse);
6579 mouse.operation = MOUSE_SHOW;
6580 ioctl(1, CONS_MOUSECTL, &mouse);
6581 return OK;
6582 }
6583 return FAIL;
6584}
6585
6586/*
6587 * Stop processing SIGUSR2 signals, and also make sure that
6588 * virtual console do not send us any sysmouse related signal.
6589 */
6590 static void
6591sysmouse_close()
6592{
6593 struct mouse_info mouse;
6594
6595 signal(SIGUSR2, restricted ? SIG_IGN : SIG_DFL);
6596 mouse.operation = MOUSE_MODE;
6597 mouse.u.mode.mode = 0;
6598 mouse.u.mode.signal = 0;
6599 ioctl(1, CONS_MOUSECTL, &mouse);
6600}
6601
6602/*
6603 * Gets info from sysmouse and adds special keys to input buf.
6604 */
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00006605 static RETSIGTYPE
6606sig_sysmouse SIGDEFARG(sigarg)
6607{
6608 struct mouse_info mouse;
6609 struct video_info video;
6610 char_u string[6];
6611 int row, col;
6612 int button;
6613 int buttons;
6614 static int oldbuttons = 0;
6615
6616#ifdef FEAT_GUI
6617 /* Don't put events in the input queue now. */
6618 if (hold_gui_events)
6619 return;
6620#endif
6621
6622 mouse.operation = MOUSE_GETINFO;
6623 if (ioctl(1, FBIO_GETMODE, &video.vi_mode) != -1
6624 && ioctl(1, FBIO_MODEINFO, &video) != -1
6625 && ioctl(1, CONS_MOUSECTL, &mouse) != -1
6626 && video.vi_cheight > 0 && video.vi_cwidth > 0)
6627 {
6628 row = mouse.u.data.y / video.vi_cheight;
6629 col = mouse.u.data.x / video.vi_cwidth;
6630 buttons = mouse.u.data.buttons;
6631 string[0] = ESC; /* Our termcode */
6632 string[1] = 'M';
6633 string[2] = 'S';
6634 if (oldbuttons == buttons && buttons != 0)
6635 {
6636 button = MOUSE_DRAG;
6637 }
6638 else
6639 {
6640 switch (buttons)
6641 {
6642 case 0:
6643 button = MOUSE_RELEASE;
6644 break;
6645 case 1:
6646 button = MOUSE_LEFT;
6647 break;
6648 case 2:
6649 button = MOUSE_MIDDLE;
6650 break;
6651 case 4:
6652 button = MOUSE_RIGHT;
6653 break;
6654 default:
6655 return;
6656 }
6657 oldbuttons = buttons;
6658 }
6659 string[3] = (char_u)(button);
6660 string[4] = (char_u)(col + ' ' + 1);
6661 string[5] = (char_u)(row + ' ' + 1);
6662 add_to_input_buf(string, 6);
6663 }
6664 return;
6665}
6666#endif /* FEAT_SYSMOUSE */
6667
Bram Moolenaar071d4272004-06-13 20:20:40 +00006668#if defined(FEAT_LIBCALL) || defined(PROTO)
6669typedef char_u * (*STRPROCSTR)__ARGS((char_u *));
6670typedef char_u * (*INTPROCSTR)__ARGS((int));
6671typedef int (*STRPROCINT)__ARGS((char_u *));
6672typedef int (*INTPROCINT)__ARGS((int));
6673
6674/*
6675 * Call a DLL routine which takes either a string or int param
6676 * and returns an allocated string.
6677 */
6678 int
6679mch_libcall(libname, funcname, argstring, argint, string_result, number_result)
6680 char_u *libname;
6681 char_u *funcname;
6682 char_u *argstring; /* NULL when using a argint */
6683 int argint;
6684 char_u **string_result;/* NULL when using number_result */
6685 int *number_result;
6686{
6687# if defined(USE_DLOPEN)
6688 void *hinstLib;
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00006689 char *dlerr = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006690# else
6691 shl_t hinstLib;
6692# endif
6693 STRPROCSTR ProcAdd;
6694 INTPROCSTR ProcAddI;
6695 char_u *retval_str = NULL;
6696 int retval_int = 0;
6697 int success = FALSE;
6698
Bram Moolenaarb39ef122006-06-22 16:19:31 +00006699 /*
6700 * Get a handle to the DLL module.
6701 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006702# if defined(USE_DLOPEN)
Bram Moolenaarb39ef122006-06-22 16:19:31 +00006703 /* First clear any error, it's not cleared by the dlopen() call. */
6704 (void)dlerror();
6705
Bram Moolenaar071d4272004-06-13 20:20:40 +00006706 hinstLib = dlopen((char *)libname, RTLD_LAZY
6707# ifdef RTLD_LOCAL
6708 | RTLD_LOCAL
6709# endif
6710 );
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00006711 if (hinstLib == NULL)
6712 {
6713 /* "dlerr" must be used before dlclose() */
6714 dlerr = (char *)dlerror();
6715 if (dlerr != NULL)
6716 EMSG2(_("dlerror = \"%s\""), dlerr);
6717 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006718# else
6719 hinstLib = shl_load((const char*)libname, BIND_IMMEDIATE|BIND_VERBOSE, 0L);
6720# endif
6721
6722 /* If the handle is valid, try to get the function address. */
6723 if (hinstLib != NULL)
6724 {
6725# ifdef HAVE_SETJMP_H
6726 /*
6727 * Catch a crash when calling the library function. For example when
6728 * using a number where a string pointer is expected.
6729 */
6730 mch_startjmp();
6731 if (SETJMP(lc_jump_env) != 0)
6732 {
6733 success = FALSE;
Bram Moolenaard68071d2006-05-02 22:08:30 +00006734# if defined(USE_DLOPEN)
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00006735 dlerr = NULL;
Bram Moolenaard68071d2006-05-02 22:08:30 +00006736# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006737 mch_didjmp();
6738 }
6739 else
6740# endif
6741 {
6742 retval_str = NULL;
6743 retval_int = 0;
6744
6745 if (argstring != NULL)
6746 {
6747# if defined(USE_DLOPEN)
6748 ProcAdd = (STRPROCSTR)dlsym(hinstLib, (const char *)funcname);
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00006749 dlerr = (char *)dlerror();
Bram Moolenaar071d4272004-06-13 20:20:40 +00006750# else
6751 if (shl_findsym(&hinstLib, (const char *)funcname,
6752 TYPE_PROCEDURE, (void *)&ProcAdd) < 0)
6753 ProcAdd = NULL;
6754# endif
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00006755 if ((success = (ProcAdd != NULL
6756# if defined(USE_DLOPEN)
6757 && dlerr == NULL
6758# endif
6759 )))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006760 {
6761 if (string_result == NULL)
6762 retval_int = ((STRPROCINT)ProcAdd)(argstring);
6763 else
6764 retval_str = (ProcAdd)(argstring);
6765 }
6766 }
6767 else
6768 {
6769# if defined(USE_DLOPEN)
6770 ProcAddI = (INTPROCSTR)dlsym(hinstLib, (const char *)funcname);
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00006771 dlerr = (char *)dlerror();
Bram Moolenaar071d4272004-06-13 20:20:40 +00006772# else
6773 if (shl_findsym(&hinstLib, (const char *)funcname,
6774 TYPE_PROCEDURE, (void *)&ProcAddI) < 0)
6775 ProcAddI = NULL;
6776# endif
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00006777 if ((success = (ProcAddI != NULL
6778# if defined(USE_DLOPEN)
6779 && dlerr == NULL
6780# endif
6781 )))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006782 {
6783 if (string_result == NULL)
6784 retval_int = ((INTPROCINT)ProcAddI)(argint);
6785 else
6786 retval_str = (ProcAddI)(argint);
6787 }
6788 }
6789
6790 /* Save the string before we free the library. */
6791 /* Assume that a "1" or "-1" result is an illegal pointer. */
6792 if (string_result == NULL)
6793 *number_result = retval_int;
6794 else if (retval_str != NULL
6795 && retval_str != (char_u *)1
6796 && retval_str != (char_u *)-1)
6797 *string_result = vim_strsave(retval_str);
6798 }
6799
6800# ifdef HAVE_SETJMP_H
6801 mch_endjmp();
6802# ifdef SIGHASARG
6803 if (lc_signal != 0)
6804 {
6805 int i;
6806
6807 /* try to find the name of this signal */
6808 for (i = 0; signal_info[i].sig != -1; i++)
6809 if (lc_signal == signal_info[i].sig)
6810 break;
6811 EMSG2("E368: got SIG%s in libcall()", signal_info[i].name);
6812 }
6813# endif
6814# endif
6815
Bram Moolenaar071d4272004-06-13 20:20:40 +00006816# if defined(USE_DLOPEN)
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00006817 /* "dlerr" must be used before dlclose() */
6818 if (dlerr != NULL)
6819 EMSG2(_("dlerror = \"%s\""), dlerr);
6820
6821 /* Free the DLL module. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006822 (void)dlclose(hinstLib);
6823# else
6824 (void)shl_unload(hinstLib);
6825# endif
6826 }
6827
6828 if (!success)
6829 {
6830 EMSG2(_(e_libcall), funcname);
6831 return FAIL;
6832 }
6833
6834 return OK;
6835}
6836#endif
6837
6838#if (defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) || defined(PROTO)
6839static int xterm_trace = -1; /* default: disabled */
6840static int xterm_button;
6841
6842/*
6843 * Setup a dummy window for X selections in a terminal.
6844 */
6845 void
6846setup_term_clip()
6847{
6848 int z = 0;
6849 char *strp = "";
6850 Widget AppShell;
6851
6852 if (!x_connect_to_server())
6853 return;
6854
6855 open_app_context();
6856 if (app_context != NULL && xterm_Shell == (Widget)0)
6857 {
6858 int (*oldhandler)();
6859#if defined(HAVE_SETJMP_H)
6860 int (*oldIOhandler)();
6861#endif
6862# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
6863 struct timeval start_tv;
6864
6865 if (p_verbose > 0)
6866 gettimeofday(&start_tv, NULL);
6867# endif
6868
6869 /* Ignore X errors while opening the display */
6870 oldhandler = XSetErrorHandler(x_error_check);
6871
6872#if defined(HAVE_SETJMP_H)
6873 /* Ignore X IO errors while opening the display */
6874 oldIOhandler = XSetIOErrorHandler(x_IOerror_check);
6875 mch_startjmp();
6876 if (SETJMP(lc_jump_env) != 0)
6877 {
6878 mch_didjmp();
6879 xterm_dpy = NULL;
6880 }
6881 else
6882#endif
6883 {
6884 xterm_dpy = XtOpenDisplay(app_context, xterm_display,
6885 "vim_xterm", "Vim_xterm", NULL, 0, &z, &strp);
6886#if defined(HAVE_SETJMP_H)
6887 mch_endjmp();
6888#endif
6889 }
6890
6891#if defined(HAVE_SETJMP_H)
6892 /* Now handle X IO errors normally. */
6893 (void)XSetIOErrorHandler(oldIOhandler);
6894#endif
6895 /* Now handle X errors normally. */
6896 (void)XSetErrorHandler(oldhandler);
6897
6898 if (xterm_dpy == NULL)
6899 {
6900 if (p_verbose > 0)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00006901 verb_msg((char_u *)_("Opening the X display failed"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006902 return;
6903 }
6904
6905 /* Catch terminating error of the X server connection. */
6906 (void)XSetIOErrorHandler(x_IOerror_handler);
6907
6908# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
6909 if (p_verbose > 0)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00006910 {
6911 verbose_enter();
Bram Moolenaar071d4272004-06-13 20:20:40 +00006912 xopen_message(&start_tv);
Bram Moolenaara04f10b2005-05-31 22:09:46 +00006913 verbose_leave();
6914 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006915# endif
6916
6917 /* Create a Shell to make converters work. */
6918 AppShell = XtVaAppCreateShell("vim_xterm", "Vim_xterm",
6919 applicationShellWidgetClass, xterm_dpy,
6920 NULL);
6921 if (AppShell == (Widget)0)
6922 return;
6923 xterm_Shell = XtVaCreatePopupShell("VIM",
6924 topLevelShellWidgetClass, AppShell,
6925 XtNmappedWhenManaged, 0,
6926 XtNwidth, 1,
6927 XtNheight, 1,
6928 NULL);
6929 if (xterm_Shell == (Widget)0)
6930 return;
6931
6932 x11_setup_atoms(xterm_dpy);
Bram Moolenaar7cfea752010-06-22 06:07:12 +02006933 x11_setup_selection(xterm_Shell);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006934 if (x11_display == NULL)
6935 x11_display = xterm_dpy;
6936
6937 XtRealizeWidget(xterm_Shell);
6938 XSync(xterm_dpy, False);
6939 xterm_update();
6940 }
6941 if (xterm_Shell != (Widget)0)
6942 {
6943 clip_init(TRUE);
6944 if (x11_window == 0 && (strp = getenv("WINDOWID")) != NULL)
6945 x11_window = (Window)atol(strp);
6946 /* Check if $WINDOWID is valid. */
6947 if (test_x11_window(xterm_dpy) == FAIL)
6948 x11_window = 0;
6949 if (x11_window != 0)
6950 xterm_trace = 0;
6951 }
6952}
6953
6954 void
6955start_xterm_trace(button)
6956 int button;
6957{
6958 if (x11_window == 0 || xterm_trace < 0 || xterm_Shell == (Widget)0)
6959 return;
6960 xterm_trace = 1;
6961 xterm_button = button;
6962 do_xterm_trace();
6963}
6964
6965
6966 void
6967stop_xterm_trace()
6968{
6969 if (xterm_trace < 0)
6970 return;
6971 xterm_trace = 0;
6972}
6973
6974/*
6975 * Query the xterm pointer and generate mouse termcodes if necessary
6976 * return TRUE if dragging is active, else FALSE
6977 */
6978 static int
6979do_xterm_trace()
6980{
6981 Window root, child;
6982 int root_x, root_y;
6983 int win_x, win_y;
6984 int row, col;
6985 int_u mask_return;
6986 char_u buf[50];
6987 char_u *strp;
6988 long got_hints;
6989 static char_u *mouse_code;
6990 static char_u mouse_name[2] = {KS_MOUSE, KE_FILLER};
6991 static int prev_row = 0, prev_col = 0;
6992 static XSizeHints xterm_hints;
6993
6994 if (xterm_trace <= 0)
6995 return FALSE;
6996
6997 if (xterm_trace == 1)
6998 {
6999 /* Get the hints just before tracking starts. The font size might
Bram Moolenaara6c2c912008-01-13 15:31:00 +00007000 * have changed recently. */
7001 if (!XGetWMNormalHints(xterm_dpy, x11_window, &xterm_hints, &got_hints)
7002 || !(got_hints & PResizeInc)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007003 || xterm_hints.width_inc <= 1
7004 || xterm_hints.height_inc <= 1)
7005 {
7006 xterm_trace = -1; /* Not enough data -- disable tracing */
7007 return FALSE;
7008 }
7009
7010 /* Rely on the same mouse code for the duration of this */
7011 mouse_code = find_termcode(mouse_name);
7012 prev_row = mouse_row;
Bram Moolenaarcde88542015-08-11 19:14:00 +02007013 prev_col = mouse_col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007014 xterm_trace = 2;
7015
7016 /* Find the offset of the chars, there might be a scrollbar on the
7017 * left of the window and/or a menu on the top (eterm etc.) */
7018 XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
7019 &win_x, &win_y, &mask_return);
7020 xterm_hints.y = win_y - (xterm_hints.height_inc * mouse_row)
7021 - (xterm_hints.height_inc / 2);
7022 if (xterm_hints.y <= xterm_hints.height_inc / 2)
7023 xterm_hints.y = 2;
7024 xterm_hints.x = win_x - (xterm_hints.width_inc * mouse_col)
7025 - (xterm_hints.width_inc / 2);
7026 if (xterm_hints.x <= xterm_hints.width_inc / 2)
7027 xterm_hints.x = 2;
7028 return TRUE;
7029 }
Bram Moolenaaref9d6aa2011-04-11 16:56:35 +02007030 if (mouse_code == NULL || STRLEN(mouse_code) > 45)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007031 {
7032 xterm_trace = 0;
7033 return FALSE;
7034 }
7035
7036 XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
7037 &win_x, &win_y, &mask_return);
7038
7039 row = check_row((win_y - xterm_hints.y) / xterm_hints.height_inc);
7040 col = check_col((win_x - xterm_hints.x) / xterm_hints.width_inc);
7041 if (row == prev_row && col == prev_col)
7042 return TRUE;
7043
7044 STRCPY(buf, mouse_code);
7045 strp = buf + STRLEN(buf);
7046 *strp++ = (xterm_button | MOUSE_DRAG) & ~0x20;
7047 *strp++ = (char_u)(col + ' ' + 1);
7048 *strp++ = (char_u)(row + ' ' + 1);
7049 *strp = 0;
7050 add_to_input_buf(buf, STRLEN(buf));
7051
7052 prev_row = row;
7053 prev_col = col;
7054 return TRUE;
7055}
7056
7057# if defined(FEAT_GUI) || defined(PROTO)
7058/*
7059 * Destroy the display, window and app_context. Required for GTK.
7060 */
7061 void
7062clear_xterm_clip()
7063{
7064 if (xterm_Shell != (Widget)0)
7065 {
7066 XtDestroyWidget(xterm_Shell);
7067 xterm_Shell = (Widget)0;
7068 }
7069 if (xterm_dpy != NULL)
7070 {
Bram Moolenaare8208012008-06-20 09:59:25 +00007071# if 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00007072 /* Lesstif and Solaris crash here, lose some memory */
7073 XtCloseDisplay(xterm_dpy);
Bram Moolenaare8208012008-06-20 09:59:25 +00007074# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007075 if (x11_display == xterm_dpy)
7076 x11_display = NULL;
7077 xterm_dpy = NULL;
7078 }
Bram Moolenaare8208012008-06-20 09:59:25 +00007079# if 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00007080 if (app_context != (XtAppContext)NULL)
7081 {
7082 /* Lesstif and Solaris crash here, lose some memory */
7083 XtDestroyApplicationContext(app_context);
7084 app_context = (XtAppContext)NULL;
7085 }
Bram Moolenaare8208012008-06-20 09:59:25 +00007086# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007087}
7088# endif
7089
7090/*
Bram Moolenaar090cfc12013-03-19 12:35:42 +01007091 * Catch up with GUI or X events.
7092 */
7093 static void
7094clip_update()
7095{
7096# ifdef FEAT_GUI
7097 if (gui.in_use)
7098 gui_mch_update();
7099 else
7100# endif
7101 if (xterm_Shell != (Widget)0)
7102 xterm_update();
7103}
7104
7105/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007106 * Catch up with any queued X events. This may put keyboard input into the
7107 * input buffer, call resize call-backs, trigger timers etc. If there is
7108 * nothing in the X event queue (& no timers pending), then we return
7109 * immediately.
7110 */
7111 static void
7112xterm_update()
7113{
7114 XEvent event;
7115
Bram Moolenaarb1fc2bf2015-03-20 16:26:54 +01007116 for (;;)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007117 {
Bram Moolenaar93c88e02015-09-15 14:12:05 +02007118 XtInputMask mask = XtAppPending(app_context);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007119
Bram Moolenaar93c88e02015-09-15 14:12:05 +02007120 if (mask == 0 || vim_is_input_buf_full())
Bram Moolenaarb1fc2bf2015-03-20 16:26:54 +01007121 break;
7122
Bram Moolenaar93c88e02015-09-15 14:12:05 +02007123 if (mask & XtIMXEvent)
Bram Moolenaarb1fc2bf2015-03-20 16:26:54 +01007124 {
7125 /* There is an event to process. */
Bram Moolenaar93c88e02015-09-15 14:12:05 +02007126 XtAppNextEvent(app_context, &event);
Bram Moolenaarb1fc2bf2015-03-20 16:26:54 +01007127#ifdef FEAT_CLIENTSERVER
7128 {
7129 XPropertyEvent *e = (XPropertyEvent *)&event;
7130
7131 if (e->type == PropertyNotify && e->window == commWindow
Bram Moolenaar071d4272004-06-13 20:20:40 +00007132 && e->atom == commProperty && e->state == PropertyNewValue)
Bram Moolenaar93c88e02015-09-15 14:12:05 +02007133 serverEventProc(xterm_dpy, &event, 0);
Bram Moolenaarb1fc2bf2015-03-20 16:26:54 +01007134 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007135#endif
Bram Moolenaar93c88e02015-09-15 14:12:05 +02007136 XtDispatchEvent(&event);
7137 }
Bram Moolenaarb1fc2bf2015-03-20 16:26:54 +01007138 else
7139 {
7140 /* There is something else than an event to process. */
Bram Moolenaar93c88e02015-09-15 14:12:05 +02007141 XtAppProcessEvent(app_context, mask);
7142 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007143 }
7144}
7145
7146 int
7147clip_xterm_own_selection(cbd)
7148 VimClipboard *cbd;
7149{
7150 if (xterm_Shell != (Widget)0)
7151 return clip_x11_own_selection(xterm_Shell, cbd);
7152 return FAIL;
7153}
7154
7155 void
7156clip_xterm_lose_selection(cbd)
7157 VimClipboard *cbd;
7158{
7159 if (xterm_Shell != (Widget)0)
7160 clip_x11_lose_selection(xterm_Shell, cbd);
7161}
7162
7163 void
7164clip_xterm_request_selection(cbd)
7165 VimClipboard *cbd;
7166{
7167 if (xterm_Shell != (Widget)0)
7168 clip_x11_request_selection(xterm_Shell, xterm_dpy, cbd);
7169}
7170
7171 void
7172clip_xterm_set_selection(cbd)
7173 VimClipboard *cbd;
7174{
7175 clip_x11_set_selection(cbd);
7176}
7177#endif
7178
7179
7180#if defined(USE_XSMP) || defined(PROTO)
7181/*
7182 * Code for X Session Management Protocol.
7183 */
7184static void xsmp_handle_save_yourself __ARGS((SmcConn smc_conn, SmPointer client_data, int save_type, Bool shutdown, int interact_style, Bool fast));
7185static void xsmp_die __ARGS((SmcConn smc_conn, SmPointer client_data));
7186static void xsmp_save_complete __ARGS((SmcConn smc_conn, SmPointer client_data));
7187static void xsmp_shutdown_cancelled __ARGS((SmcConn smc_conn, SmPointer client_data));
7188static void xsmp_ice_connection __ARGS((IceConn iceConn, IcePointer clientData, Bool opening, IcePointer *watchData));
7189
7190
7191# if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
7192static void xsmp_handle_interaction __ARGS((SmcConn smc_conn, SmPointer client_data));
7193
7194/*
7195 * This is our chance to ask the user if they want to save,
7196 * or abort the logout
7197 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007198 static void
7199xsmp_handle_interaction(smc_conn, client_data)
7200 SmcConn smc_conn;
Bram Moolenaar2c4278f2009-05-17 11:33:22 +00007201 SmPointer client_data UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007202{
7203 cmdmod_T save_cmdmod;
7204 int cancel_shutdown = False;
7205
7206 save_cmdmod = cmdmod;
7207 cmdmod.confirm = TRUE;
7208 if (check_changed_any(FALSE))
7209 /* Mustn't logout */
7210 cancel_shutdown = True;
7211 cmdmod = save_cmdmod;
7212 setcursor(); /* position cursor */
7213 out_flush();
7214
7215 /* Done interaction */
7216 SmcInteractDone(smc_conn, cancel_shutdown);
7217
7218 /* Finish off
7219 * Only end save-yourself here if we're not cancelling shutdown;
7220 * we'll get a cancelled callback later in which we'll end it.
7221 * Hopefully get around glitchy SMs (like GNOME-1)
7222 */
7223 if (!cancel_shutdown)
7224 {
7225 xsmp.save_yourself = False;
7226 SmcSaveYourselfDone(smc_conn, True);
7227 }
7228}
7229# endif
7230
7231/*
7232 * Callback that starts save-yourself.
7233 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007234 static void
7235xsmp_handle_save_yourself(smc_conn, client_data, save_type,
7236 shutdown, interact_style, fast)
7237 SmcConn smc_conn;
Bram Moolenaar2c4278f2009-05-17 11:33:22 +00007238 SmPointer client_data UNUSED;
7239 int save_type UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007240 Bool shutdown;
Bram Moolenaar2c4278f2009-05-17 11:33:22 +00007241 int interact_style UNUSED;
7242 Bool fast UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007243{
7244 /* Handle already being in saveyourself */
7245 if (xsmp.save_yourself)
7246 SmcSaveYourselfDone(smc_conn, True);
7247 xsmp.save_yourself = True;
7248 xsmp.shutdown = shutdown;
7249
7250 /* First up, preserve all files */
7251 out_flush();
7252 ml_sync_all(FALSE, FALSE); /* preserve all swap files */
7253
7254 if (p_verbose > 0)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00007255 verb_msg((char_u *)_("XSMP handling save-yourself request"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007256
7257# if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
7258 /* Now see if we can ask about unsaved files */
7259 if (shutdown && !fast && gui.in_use)
7260 /* Need to interact with user, but need SM's permission */
7261 SmcInteractRequest(smc_conn, SmDialogError,
7262 xsmp_handle_interaction, client_data);
7263 else
7264# endif
7265 {
7266 /* Can stop the cycle here */
7267 SmcSaveYourselfDone(smc_conn, True);
7268 xsmp.save_yourself = False;
7269 }
7270}
7271
7272
7273/*
7274 * Callback to warn us of imminent death.
7275 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007276 static void
7277xsmp_die(smc_conn, client_data)
Bram Moolenaar2c4278f2009-05-17 11:33:22 +00007278 SmcConn smc_conn UNUSED;
7279 SmPointer client_data UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007280{
7281 xsmp_close();
7282
7283 /* quit quickly leaving swapfiles for modified buffers behind */
7284 getout_preserve_modified(0);
7285}
7286
7287
7288/*
7289 * Callback to tell us that save-yourself has completed.
7290 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007291 static void
7292xsmp_save_complete(smc_conn, client_data)
Bram Moolenaar2c4278f2009-05-17 11:33:22 +00007293 SmcConn smc_conn UNUSED;
7294 SmPointer client_data UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007295{
7296 xsmp.save_yourself = False;
7297}
7298
7299
7300/*
7301 * Callback to tell us that an instigated shutdown was cancelled
7302 * (maybe even by us)
7303 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007304 static void
7305xsmp_shutdown_cancelled(smc_conn, client_data)
7306 SmcConn smc_conn;
Bram Moolenaar2c4278f2009-05-17 11:33:22 +00007307 SmPointer client_data UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007308{
7309 if (xsmp.save_yourself)
7310 SmcSaveYourselfDone(smc_conn, True);
7311 xsmp.save_yourself = False;
7312 xsmp.shutdown = False;
7313}
7314
7315
7316/*
7317 * Callback to tell us that a new ICE connection has been established.
7318 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007319 static void
7320xsmp_ice_connection(iceConn, clientData, opening, watchData)
7321 IceConn iceConn;
Bram Moolenaar2c4278f2009-05-17 11:33:22 +00007322 IcePointer clientData UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007323 Bool opening;
Bram Moolenaar2c4278f2009-05-17 11:33:22 +00007324 IcePointer *watchData UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007325{
7326 /* Intercept creation of ICE connection fd */
7327 if (opening)
7328 {
7329 xsmp_icefd = IceConnectionNumber(iceConn);
7330 IceRemoveConnectionWatch(xsmp_ice_connection, NULL);
7331 }
7332}
7333
7334
7335/* Handle any ICE processing that's required; return FAIL if SM lost */
7336 int
7337xsmp_handle_requests()
7338{
7339 Bool rep;
7340
7341 if (IceProcessMessages(xsmp.iceconn, NULL, &rep)
7342 == IceProcessMessagesIOError)
7343 {
7344 /* Lost ICE */
7345 if (p_verbose > 0)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00007346 verb_msg((char_u *)_("XSMP lost ICE connection"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007347 xsmp_close();
7348 return FAIL;
7349 }
7350 else
7351 return OK;
7352}
7353
7354static int dummy;
7355
7356/* Set up X Session Management Protocol */
7357 void
7358xsmp_init(void)
7359{
7360 char errorstring[80];
Bram Moolenaar071d4272004-06-13 20:20:40 +00007361 SmcCallbacks smcallbacks;
7362#if 0
7363 SmPropValue smname;
7364 SmProp smnameprop;
7365 SmProp *smprops[1];
7366#endif
7367
7368 if (p_verbose > 0)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00007369 verb_msg((char_u *)_("XSMP opening connection"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007370
7371 xsmp.save_yourself = xsmp.shutdown = False;
7372
7373 /* Set up SM callbacks - must have all, even if they're not used */
7374 smcallbacks.save_yourself.callback = xsmp_handle_save_yourself;
7375 smcallbacks.save_yourself.client_data = NULL;
7376 smcallbacks.die.callback = xsmp_die;
7377 smcallbacks.die.client_data = NULL;
7378 smcallbacks.save_complete.callback = xsmp_save_complete;
7379 smcallbacks.save_complete.client_data = NULL;
7380 smcallbacks.shutdown_cancelled.callback = xsmp_shutdown_cancelled;
7381 smcallbacks.shutdown_cancelled.client_data = NULL;
7382
7383 /* Set up a watch on ICE connection creations. The "dummy" argument is
7384 * apparently required for FreeBSD (we get a BUS error when using NULL). */
7385 if (IceAddConnectionWatch(xsmp_ice_connection, &dummy) == 0)
7386 {
7387 if (p_verbose > 0)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00007388 verb_msg((char_u *)_("XSMP ICE connection watch failed"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007389 return;
7390 }
7391
7392 /* Create an SM connection */
7393 xsmp.smcconn = SmcOpenConnection(
7394 NULL,
7395 NULL,
7396 SmProtoMajor,
7397 SmProtoMinor,
7398 SmcSaveYourselfProcMask | SmcDieProcMask
7399 | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask,
7400 &smcallbacks,
7401 NULL,
Bram Moolenaare8208012008-06-20 09:59:25 +00007402 &xsmp.clientid,
Bram Moolenaar071d4272004-06-13 20:20:40 +00007403 sizeof(errorstring),
7404 errorstring);
7405 if (xsmp.smcconn == NULL)
7406 {
7407 char errorreport[132];
Bram Moolenaar051b7822005-05-19 21:00:46 +00007408
Bram Moolenaar071d4272004-06-13 20:20:40 +00007409 if (p_verbose > 0)
Bram Moolenaara04f10b2005-05-31 22:09:46 +00007410 {
7411 vim_snprintf(errorreport, sizeof(errorreport),
7412 _("XSMP SmcOpenConnection failed: %s"), errorstring);
7413 verb_msg((char_u *)errorreport);
7414 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007415 return;
7416 }
7417 xsmp.iceconn = SmcGetIceConnection(xsmp.smcconn);
7418
7419#if 0
7420 /* ID ourselves */
7421 smname.value = "vim";
7422 smname.length = 3;
7423 smnameprop.name = "SmProgram";
7424 smnameprop.type = "SmARRAY8";
7425 smnameprop.num_vals = 1;
7426 smnameprop.vals = &smname;
7427
7428 smprops[0] = &smnameprop;
7429 SmcSetProperties(xsmp.smcconn, 1, smprops);
7430#endif
7431}
7432
7433
7434/* Shut down XSMP comms. */
7435 void
7436xsmp_close()
7437{
7438 if (xsmp_icefd != -1)
7439 {
7440 SmcCloseConnection(xsmp.smcconn, 0, NULL);
Bram Moolenaar5a221812008-11-12 12:08:45 +00007441 if (xsmp.clientid != NULL)
7442 free(xsmp.clientid);
Bram Moolenaare8208012008-06-20 09:59:25 +00007443 xsmp.clientid = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007444 xsmp_icefd = -1;
7445 }
7446}
7447#endif /* USE_XSMP */
7448
7449
7450#ifdef EBCDIC
7451/* Translate character to its CTRL- value */
7452char CtrlTable[] =
7453{
7454/* 00 - 5E */
7455 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7456 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7457 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7458 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7459 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7460 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7461/* ^ */ 0x1E,
7462/* - */ 0x1F,
7463/* 61 - 6C */
7464 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7465/* _ */ 0x1F,
7466/* 6E - 80 */
7467 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7468/* a */ 0x01,
7469/* b */ 0x02,
7470/* c */ 0x03,
7471/* d */ 0x37,
7472/* e */ 0x2D,
7473/* f */ 0x2E,
7474/* g */ 0x2F,
7475/* h */ 0x16,
7476/* i */ 0x05,
7477/* 8A - 90 */
7478 0, 0, 0, 0, 0, 0, 0,
7479/* j */ 0x15,
7480/* k */ 0x0B,
7481/* l */ 0x0C,
7482/* m */ 0x0D,
7483/* n */ 0x0E,
7484/* o */ 0x0F,
7485/* p */ 0x10,
7486/* q */ 0x11,
7487/* r */ 0x12,
7488/* 9A - A1 */
7489 0, 0, 0, 0, 0, 0, 0, 0,
7490/* s */ 0x13,
7491/* t */ 0x3C,
7492/* u */ 0x3D,
7493/* v */ 0x32,
7494/* w */ 0x26,
7495/* x */ 0x18,
7496/* y */ 0x19,
7497/* z */ 0x3F,
7498/* AA - AC */
7499 0, 0, 0,
7500/* [ */ 0x27,
7501/* AE - BC */
7502 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7503/* ] */ 0x1D,
7504/* BE - C0 */ 0, 0, 0,
7505/* A */ 0x01,
7506/* B */ 0x02,
7507/* C */ 0x03,
7508/* D */ 0x37,
7509/* E */ 0x2D,
7510/* F */ 0x2E,
7511/* G */ 0x2F,
7512/* H */ 0x16,
7513/* I */ 0x05,
7514/* CA - D0 */ 0, 0, 0, 0, 0, 0, 0,
7515/* J */ 0x15,
7516/* K */ 0x0B,
7517/* L */ 0x0C,
7518/* M */ 0x0D,
7519/* N */ 0x0E,
7520/* O */ 0x0F,
7521/* P */ 0x10,
7522/* Q */ 0x11,
7523/* R */ 0x12,
7524/* DA - DF */ 0, 0, 0, 0, 0, 0,
7525/* \ */ 0x1C,
7526/* E1 */ 0,
7527/* S */ 0x13,
7528/* T */ 0x3C,
7529/* U */ 0x3D,
7530/* V */ 0x32,
7531/* W */ 0x26,
7532/* X */ 0x18,
7533/* Y */ 0x19,
7534/* Z */ 0x3F,
7535/* EA - FF*/ 0, 0, 0, 0, 0, 0,
7536 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7537};
7538
7539char MetaCharTable[]=
7540{/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
7541 0, 0, 0, 0,'\\', 0,'F', 0,'W','M','N', 0, 0, 0, 0, 0,
7542 0, 0, 0, 0,']', 0, 0,'G', 0, 0,'R','O', 0, 0, 0, 0,
7543 '@','A','B','C','D','E', 0, 0,'H','I','J','K','L', 0, 0, 0,
7544 'P','Q', 0,'S','T','U','V', 0,'X','Y','Z','[', 0, 0,'^', 0
7545};
7546
7547
7548/* TODO: Use characters NOT numbers!!! */
7549char CtrlCharTable[]=
7550{/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
7551 124,193,194,195, 0,201, 0, 0, 0, 0, 0,210,211,212,213,214,
7552 215,216,217,226, 0,209,200, 0,231,232, 0, 0,224,189, 95,109,
7553 0, 0, 0, 0, 0, 0,230,173, 0, 0, 0, 0, 0,197,198,199,
7554 0, 0,229, 0, 0, 0, 0,196, 0, 0, 0, 0,227,228, 0,233,
7555};
7556
7557
7558#endif