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