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