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