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