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