Annotation of src/usr.bin/vim/unix.c, Revision 1.1
1.1 ! downsj 1: /* $OpenBSD$ */
! 2: /* vi:set ts=4 sw=4:
! 3: *
! 4: * VIM - Vi IMproved by Bram Moolenaar
! 5: * OS/2 port by Paul Slootman
! 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: */
! 10:
! 11: /*
! 12: * unix.c -- code for all flavors of Unix (BSD, SYSV, SVR4, POSIX, ...)
! 13: * Also for OS/2, using the excellent EMX package!!!
! 14: *
! 15: * A lot of this file was originally written by Juergen Weigert and later
! 16: * changed beyond recognition.
! 17: */
! 18:
! 19: /*
! 20: * Some systems have a prototype for select() that has (int *) instead of
! 21: * (fd_set *), which is wrong. This define removes that prototype. We include
! 22: * our own prototype in osdef.h.
! 23: */
! 24: #define select select_declared_wrong
! 25:
! 26: #include "vim.h"
! 27: #include "globals.h"
! 28: #include "option.h"
! 29: #include "proto.h"
! 30:
! 31: #ifdef HAVE_FCNTL_H
! 32: # include <fcntl.h>
! 33: #endif
! 34:
! 35: #include "unixunix.h" /* unix includes for unix.c only */
! 36:
! 37: /*
! 38: * Use this prototype for select, some include files have a wrong prototype
! 39: */
! 40: #undef select
! 41:
! 42: #if defined(HAVE_SELECT)
! 43: extern int select __ARGS((int, fd_set *, fd_set *, fd_set *, struct timeval *));
! 44: #endif
! 45:
! 46: /*
! 47: * end of autoconf section. To be extended...
! 48: */
! 49:
! 50: /* Are the following #ifdefs still required? And why? Is that for X11? */
! 51:
! 52: #if defined(ESIX) || defined(M_UNIX) && !defined(SCO)
! 53: # ifdef SIGWINCH
! 54: # undef SIGWINCH
! 55: # endif
! 56: # ifdef TIOCGWINSZ
! 57: # undef TIOCGWINSZ
! 58: # endif
! 59: #endif
! 60:
! 61: #if defined(SIGWINDOW) && !defined(SIGWINCH) /* hpux 9.01 has it */
! 62: # define SIGWINCH SIGWINDOW
! 63: #endif
! 64:
! 65: #if defined(HAVE_X11) && defined(WANT_X11)
! 66: # include <X11/Xlib.h>
! 67: # include <X11/Xutil.h>
! 68: # include <X11/Xatom.h>
! 69:
! 70: Window x11_window = 0;
! 71: Display *x11_display = NULL;
! 72: int got_x_error = FALSE;
! 73:
! 74: static int get_x11_windis __ARGS((void));
! 75: static void set_x11_title __ARGS((char_u *));
! 76: static void set_x11_icon __ARGS((char_u *));
! 77: #endif
! 78:
! 79: static int get_x11_title __ARGS((int));
! 80: static int get_x11_icon __ARGS((int));
! 81:
! 82: static void may_core_dump __ARGS((void));
! 83:
! 84: static int Read __ARGS((char_u *, long));
! 85: static int WaitForChar __ARGS((long));
! 86: static int RealWaitForChar __ARGS((int, long));
! 87: static void fill_inbuf __ARGS((int));
! 88:
! 89: #if defined(SIGWINCH)
! 90: static RETSIGTYPE sig_winch __ARGS(SIGPROTOARG);
! 91: #endif
! 92: #if defined(SIGALRM) && defined(HAVE_X11) && defined(WANT_X11)
! 93: static RETSIGTYPE sig_alarm __ARGS(SIGPROTOARG);
! 94: #endif
! 95: static RETSIGTYPE deathtrap __ARGS(SIGPROTOARG);
! 96:
! 97: static void catch_signals __ARGS((RETSIGTYPE (*func)()));
! 98: #ifndef __EMX__
! 99: static int have_wildcard __ARGS((int, char_u **));
! 100: static int have_dollars __ARGS((int, char_u **));
! 101: #endif
! 102:
! 103: static int do_resize = FALSE;
! 104: static char_u *oldtitle = NULL;
! 105: static char_u *fixedtitle = (char_u *)"Thanks for flying Vim";
! 106: static char_u *oldicon = NULL;
! 107: #ifndef __EMX__
! 108: static char_u *extra_shell_arg = NULL;
! 109: static int show_shell_mess = TRUE;
! 110: #endif
! 111: static int core_dump = FALSE; /* core dump in mch_windexit() */
! 112:
! 113: #ifdef SYS_SIGLIST_DECLARED
! 114: /*
! 115: * I have seen
! 116: * extern char *_sys_siglist[NSIG];
! 117: * on Irix, Linux, NetBSD and Solaris. It contains a nice list of strings
! 118: * that describe the signals. That is nearly what we want here. But
! 119: * autoconf does only check for sys_siglist (without the underscore), I
! 120: * do not want to change everything today.... jw.
! 121: * This is why AC_DECL_SYS_SIGLIST is commented out in configure.in
! 122: */
! 123: #endif
! 124:
! 125: static struct
! 126: {
! 127: int sig; /* Signal number, eg. SIGSEGV etc */
! 128: char *name; /* Signal name (not char_u!). */
! 129: int dump; /* Should this signal cause a core dump? */
! 130: } signal_info[] =
! 131: {
! 132: #ifdef SIGHUP
! 133: {SIGHUP, "HUP", FALSE},
! 134: #endif
! 135: #ifdef SIGINT
! 136: {SIGINT, "INT", FALSE},
! 137: #endif
! 138: #ifdef SIGQUIT
! 139: {SIGQUIT, "QUIT", TRUE},
! 140: #endif
! 141: #ifdef SIGILL
! 142: {SIGILL, "ILL", TRUE},
! 143: #endif
! 144: #ifdef SIGTRAP
! 145: {SIGTRAP, "TRAP", TRUE},
! 146: #endif
! 147: #ifdef SIGABRT
! 148: {SIGABRT, "ABRT", TRUE},
! 149: #endif
! 150: #ifdef SIGEMT
! 151: {SIGEMT, "EMT", TRUE},
! 152: #endif
! 153: #ifdef SIGFPE
! 154: {SIGFPE, "FPE", TRUE},
! 155: #endif
! 156: #ifdef SIGBUS
! 157: {SIGBUS, "BUS", TRUE},
! 158: #endif
! 159: #ifdef SIGSEGV
! 160: {SIGSEGV, "SEGV", TRUE},
! 161: #endif
! 162: #ifdef SIGSYS
! 163: {SIGSYS, "SYS", TRUE},
! 164: #endif
! 165: #ifdef SIGALRM
! 166: {SIGALRM, "ALRM", FALSE},
! 167: #endif
! 168: #ifdef SIGTERM
! 169: {SIGTERM, "TERM", FALSE},
! 170: #endif
! 171: #ifdef SIGVTALRM
! 172: {SIGVTALRM, "VTALRM", FALSE},
! 173: #endif
! 174: #ifdef SIGPROF
! 175: {SIGPROF, "PROF", FALSE},
! 176: #endif
! 177: #ifdef SIGXCPU
! 178: {SIGXCPU, "XCPU", TRUE},
! 179: #endif
! 180: #ifdef SIGXFSZ
! 181: {SIGXFSZ, "XFSZ", TRUE},
! 182: #endif
! 183: #ifdef SIGUSR1
! 184: {SIGUSR1, "USR1", FALSE},
! 185: #endif
! 186: #ifdef SIGUSR2
! 187: {SIGUSR2, "USR2", FALSE},
! 188: #endif
! 189: {-1, "Unknown!", -1}
! 190: };
! 191:
! 192: void
! 193: mch_write(s, len)
! 194: char_u *s;
! 195: int len;
! 196: {
! 197: #ifdef USE_GUI
! 198: if (gui.in_use && !gui.dying)
! 199: {
! 200: gui_write(s, len);
! 201: if (p_wd)
! 202: gui_mch_wait_for_chars(p_wd);
! 203: }
! 204: else
! 205: #endif
! 206: {
! 207: write(1, (char *)s, len);
! 208: if (p_wd) /* Unix is too fast, slow down a bit more */
! 209: RealWaitForChar(0, p_wd);
! 210: }
! 211: }
! 212:
! 213: /*
! 214: * mch_inchar(): low level input funcion.
! 215: * Get a characters from the keyboard.
! 216: * Return the number of characters that are available.
! 217: * If wtime == 0 do not wait for characters.
! 218: * If wtime == n wait a short time for characters.
! 219: * If wtime == -1 wait forever for characters.
! 220: */
! 221: int
! 222: mch_inchar(buf, maxlen, wtime)
! 223: char_u *buf;
! 224: int maxlen;
! 225: long wtime; /* don't use "time", MIPS cannot handle it */
! 226: {
! 227: int len;
! 228:
! 229: #ifdef USE_GUI
! 230: if (gui.in_use)
! 231: {
! 232: if (!gui_mch_wait_for_chars(wtime))
! 233: return 0;
! 234: return Read(buf, (long)maxlen);
! 235: }
! 236: #endif
! 237:
! 238: if (wtime >= 0)
! 239: {
! 240: while (WaitForChar(wtime) == 0) /* no character available */
! 241: {
! 242: if (!do_resize) /* return if not interrupted by resize */
! 243: return 0;
! 244: set_winsize(0, 0, FALSE);
! 245: do_resize = FALSE;
! 246: }
! 247: }
! 248: else /* wtime == -1 */
! 249: {
! 250: /*
! 251: * If there is no character available within 'updatetime' seconds
! 252: * flush all the swap files to disk
! 253: * Also done when interrupted by SIGWINCH.
! 254: */
! 255: if (WaitForChar(p_ut) == 0)
! 256: updatescript(0);
! 257: }
! 258:
! 259: for (;;) /* repeat until we got a character */
! 260: {
! 261: if (do_resize) /* window changed size */
! 262: {
! 263: set_winsize(0, 0, FALSE);
! 264: do_resize = FALSE;
! 265: }
! 266: /*
! 267: * we want to be interrupted by the winch signal
! 268: */
! 269: WaitForChar(-1L);
! 270: if (do_resize) /* interrupted by SIGWINCHsignal */
! 271: continue;
! 272:
! 273: /*
! 274: * For some terminals we only get one character at a time.
! 275: * We want the get all available characters, so we could keep on
! 276: * trying until none is available
! 277: * For some other terminals this is quite slow, that's why we don't do
! 278: * it.
! 279: */
! 280: len = Read(buf, (long)maxlen);
! 281: if (len > 0)
! 282: {
! 283: #ifdef OS2
! 284: int i;
! 285:
! 286: for (i = 0; i < len; i++)
! 287: if (buf[i] == 0)
! 288: buf[i] = K_NUL;
! 289: #endif
! 290: return len;
! 291: }
! 292: }
! 293: }
! 294:
! 295: /*
! 296: * return non-zero if a character is available
! 297: */
! 298: int
! 299: mch_char_avail()
! 300: {
! 301: #ifdef USE_GUI
! 302: if (gui.in_use)
! 303: {
! 304: gui_mch_update();
! 305: return !is_input_buf_empty();
! 306: }
! 307: #endif
! 308: return WaitForChar(0L);
! 309: }
! 310:
! 311: long
! 312: mch_avail_mem(special)
! 313: int special;
! 314: {
! 315: #ifdef __EMX__
! 316: return ulimit(3, 0L); /* always 32MB? */
! 317: #else
! 318: return 0x7fffffff; /* virtual memory eh */
! 319: #endif
! 320: }
! 321:
! 322: void
! 323: mch_delay(msec, ignoreinput)
! 324: long msec;
! 325: int ignoreinput;
! 326: {
! 327: if (ignoreinput)
! 328: #ifndef HAVE_SELECT
! 329: poll(NULL, 0, (int)msec);
! 330: #else
! 331: # ifdef __EMX__
! 332: _sleep2(msec);
! 333: # else
! 334: {
! 335: struct timeval tv;
! 336:
! 337: tv.tv_sec = msec / 1000;
! 338: tv.tv_usec = (msec % 1000) * 1000;
! 339: select(0, NULL, NULL, NULL, &tv);
! 340: }
! 341: # endif /* __EMX__ */
! 342: #endif /* HAVE_SELECT */
! 343: else
! 344: #ifdef USE_GUI
! 345: if (gui.in_use)
! 346: gui_mch_wait_for_chars(msec);
! 347: else
! 348: #endif
! 349: WaitForChar(msec);
! 350: }
! 351:
! 352: #if defined(SIGWINCH)
! 353: /*
! 354: * We need correct potatotypes, otherwise mean compilers will barf when the
! 355: * second argument to signal() is ``wrong''.
! 356: * Let me try it with a few tricky defines from my own osdef.h (jw).
! 357: */
! 358: static RETSIGTYPE
! 359: sig_winch SIGDEFARG(sigarg)
! 360: {
! 361: /* this is not required on all systems, but it doesn't hurt anybody */
! 362: signal(SIGWINCH, (RETSIGTYPE (*)())sig_winch);
! 363: do_resize = TRUE;
! 364: SIGRETURN;
! 365: }
! 366: #endif
! 367:
! 368: #if defined(SIGALRM) && defined(HAVE_X11) && defined(WANT_X11)
! 369: /*
! 370: * signal function for alarm().
! 371: */
! 372: static RETSIGTYPE
! 373: sig_alarm SIGDEFARG(sigarg)
! 374: {
! 375: /* doesn't do anything, just to break a system call */
! 376: SIGRETURN;
! 377: }
! 378: #endif
! 379:
! 380: void
! 381: mch_resize()
! 382: {
! 383: do_resize = TRUE;
! 384: }
! 385:
! 386: /*
! 387: * This function handles deadly signals.
! 388: * It tries to preserve any swap file and exit properly.
! 389: * (partly from Elvis).
! 390: */
! 391: static RETSIGTYPE
! 392: deathtrap SIGDEFARG(sigarg)
! 393: {
! 394: static int entered = 0;
! 395: #ifdef SIGHASARG
! 396: int i;
! 397:
! 398: for (i = 0; signal_info[i].dump != -1; i++)
! 399: {
! 400: if (sigarg == signal_info[i].sig)
! 401: {
! 402: if (signal_info[i].dump)
! 403: core_dump = TRUE;
! 404: break;
! 405: }
! 406: }
! 407: #endif
! 408:
! 409: /*
! 410: * If something goes wrong after entering here, we may get here again.
! 411: * When this happens, give a message and try to exit nicely (resetting the
! 412: * terminal mode, etc.)
! 413: * When this happens twice, just exit, don't even try to give a message,
! 414: * stack may be corrupt or something weird.
! 415: */
! 416: if (entered == 2)
! 417: {
! 418: may_core_dump();
! 419: exit(7);
! 420: }
! 421: if (entered)
! 422: {
! 423: OUTSTR("Vim: Double signal, exiting\n");
! 424: flushbuf();
! 425: getout(1);
! 426: }
! 427: ++entered;
! 428:
! 429: sprintf((char *)IObuff, "Vim: Caught %s %s\n",
! 430: #ifdef SIGHASARG
! 431: "deadly signal", signal_info[i].name);
! 432: #else
! 433: "some", "deadly signal");
! 434: #endif
! 435:
! 436: preserve_exit(); /* preserve files and exit */
! 437:
! 438: SIGRETURN;
! 439: }
! 440:
! 441: /*
! 442: * If the machine has job control, use it to suspend the program,
! 443: * otherwise fake it by starting a new shell.
! 444: * When running the GUI iconify the window.
! 445: */
! 446: void
! 447: mch_suspend()
! 448: {
! 449: #ifdef USE_GUI
! 450: if (gui.in_use)
! 451: {
! 452: gui_mch_iconify();
! 453: return;
! 454: }
! 455: #endif
! 456: #ifdef SIGTSTP
! 457: flushbuf(); /* needed to make cursor visible on some systems */
! 458: settmode(0);
! 459: flushbuf(); /* needed to disable mouse on some systems */
! 460: kill(0, SIGTSTP); /* send ourselves a STOP signal */
! 461:
! 462: /*
! 463: * Set oldtitle to NULL, so the current title is obtained again.
! 464: */
! 465: if (oldtitle != fixedtitle)
! 466: {
! 467: vim_free(oldtitle);
! 468: oldtitle = NULL;
! 469: }
! 470: settmode(1);
! 471: #else
! 472: MSG_OUTSTR("new shell started\n");
! 473: (void)call_shell(NULL, SHELL_COOKED);
! 474: #endif
! 475: need_check_timestamps = TRUE;
! 476: }
! 477:
! 478: void
! 479: mch_windinit()
! 480: {
! 481: Columns = 80;
! 482: Rows = 24;
! 483:
! 484: flushbuf();
! 485:
! 486: (void)mch_get_winsize();
! 487:
! 488: #if defined(SIGWINCH)
! 489: /*
! 490: * WINDOW CHANGE signal is handled with sig_winch().
! 491: */
! 492: signal(SIGWINCH, (RETSIGTYPE (*)())sig_winch);
! 493: #endif
! 494:
! 495: /*
! 496: * We want the STOP signal to work, to make mch_suspend() work
! 497: */
! 498: #ifdef SIGTSTP
! 499: signal(SIGTSTP, SIG_DFL);
! 500: #endif
! 501:
! 502: /*
! 503: * We want to ignore breaking of PIPEs.
! 504: */
! 505: #ifdef SIGPIPE
! 506: signal(SIGPIPE, SIG_IGN);
! 507: #endif
! 508:
! 509: /*
! 510: * Arrange for other signals to gracefully shutdown Vim.
! 511: */
! 512: catch_signals(deathtrap);
! 513: }
! 514:
! 515: static void
! 516: catch_signals(func)
! 517: RETSIGTYPE (*func)();
! 518: {
! 519: int i;
! 520:
! 521: for (i = 0; signal_info[i].dump != -1; i++)
! 522: signal(signal_info[i].sig, func);
! 523: }
! 524:
! 525: void
! 526: reset_signals()
! 527: {
! 528: catch_signals(SIG_DFL);
! 529: }
! 530:
! 531: /*
! 532: * Check_win checks whether we have an interactive window.
! 533: */
! 534: int
! 535: mch_check_win(argc, argv)
! 536: int argc;
! 537: char **argv;
! 538: {
! 539: if (isatty(1))
! 540: return OK;
! 541: return FAIL;
! 542: }
! 543:
! 544: int
! 545: mch_check_input()
! 546: {
! 547: if (isatty(0))
! 548: return OK;
! 549: return FAIL;
! 550: }
! 551:
! 552: #if defined(HAVE_X11) && defined(WANT_X11)
! 553: /*
! 554: * X Error handler, otherwise X just exits! (very rude) -- webb
! 555: */
! 556: static int
! 557: x_error_handler(dpy, error_event)
! 558: Display *dpy;
! 559: XErrorEvent *error_event;
! 560: {
! 561: XGetErrorText(dpy, error_event->error_code, (char *)IObuff, IOSIZE);
! 562: STRCAT(IObuff, "\nVim: Got X error\n");
! 563:
! 564: #if 1
! 565: preserve_exit(); /* preserve files and exit */
! 566: #else
! 567: printf(IObuff); /* print error message and continue */
! 568: /* Makes my system hang */
! 569: #endif
! 570:
! 571: return 0; /* NOTREACHED */
! 572: }
! 573:
! 574: /*
! 575: * Another X Error handler, just used to check for errors.
! 576: */
! 577: static int
! 578: x_error_check(dpy, error_event)
! 579: Display *dpy;
! 580: XErrorEvent *error_event;
! 581: {
! 582: got_x_error = TRUE;
! 583: return 0;
! 584: }
! 585:
! 586: /*
! 587: * try to get x11 window and display
! 588: *
! 589: * return FAIL for failure, OK otherwise
! 590: */
! 591: static int
! 592: get_x11_windis()
! 593: {
! 594: char *winid;
! 595: XTextProperty text_prop;
! 596: int (*old_handler)();
! 597: static int result = -1;
! 598: static int x11_display_opened_here = FALSE;
! 599:
! 600: /* X just exits if it finds an error otherwise! */
! 601: XSetErrorHandler(x_error_handler);
! 602:
! 603: #ifdef USE_GUI_X11
! 604: if (gui.in_use)
! 605: {
! 606: /*
! 607: * If the X11 display was opened here before, for the window where Vim
! 608: * was started, close that one now to avoid a memory leak.
! 609: */
! 610: if (x11_display_opened_here && x11_display != NULL)
! 611: {
! 612: XCloseDisplay(x11_display);
! 613: x11_display = NULL;
! 614: x11_display_opened_here = FALSE;
! 615: }
! 616: return gui_get_x11_windis(&x11_window, &x11_display);
! 617: }
! 618: #endif
! 619:
! 620: if (result != -1) /* Have already been here and set this */
! 621: return result; /* Don't do all these X calls again */
! 622:
! 623: /*
! 624: * If WINDOWID not set, should try another method to find out
! 625: * what the current window number is. The only code I know for
! 626: * this is very complicated.
! 627: * We assume that zero is invalid for WINDOWID.
! 628: */
! 629: if (x11_window == 0 && (winid = getenv("WINDOWID")) != NULL)
! 630: x11_window = (Window)atol(winid);
! 631: if (x11_window != 0 && x11_display == NULL)
! 632: {
! 633: #ifdef SIGALRM
! 634: RETSIGTYPE (*sig_save)();
! 635:
! 636: /*
! 637: * Opening the Display may hang if the DISPLAY setting is wrong, or
! 638: * the network connection is bad. Set an alarm timer to get out.
! 639: */
! 640: sig_save = (RETSIGTYPE (*)())signal(SIGALRM,
! 641: (RETSIGTYPE (*)())sig_alarm);
! 642: alarm(2);
! 643: #endif
! 644: x11_display = XOpenDisplay(NULL);
! 645: #ifdef SIGALRM
! 646: alarm(0);
! 647: signal(SIGALRM, (RETSIGTYPE (*)())sig_save);
! 648: #endif
! 649: if (x11_display != NULL)
! 650: {
! 651: /*
! 652: * Try to get the window title. I don't actually want it yet, so
! 653: * there may be a simpler call to use, but this will cause the
! 654: * error handler x_error_check() to be called if anything is wrong,
! 655: * such as the window pointer being invalid (as can happen when the
! 656: * user changes his DISPLAY, but not his WINDOWID) -- webb
! 657: */
! 658: old_handler = XSetErrorHandler(x_error_check);
! 659: got_x_error = FALSE;
! 660: if (XGetWMName(x11_display, x11_window, &text_prop))
! 661: XFree((void *)text_prop.value);
! 662: XSync(x11_display, False);
! 663: if (got_x_error)
! 664: {
! 665: /* Maybe window id is bad */
! 666: x11_window = 0;
! 667: XCloseDisplay(x11_display);
! 668: x11_display = NULL;
! 669: }
! 670: else
! 671: x11_display_opened_here = TRUE;
! 672: XSetErrorHandler(old_handler);
! 673: }
! 674: }
! 675: if (x11_window == 0 || x11_display == NULL)
! 676: return (result = FAIL);
! 677: return (result = OK);
! 678: }
! 679:
! 680: /*
! 681: * Determine original x11 Window Title
! 682: */
! 683: static int
! 684: get_x11_title(test_only)
! 685: int test_only;
! 686: {
! 687: XTextProperty text_prop;
! 688: int retval = FALSE;
! 689:
! 690: if (get_x11_windis() == OK)
! 691: {
! 692: /* Get window name if any */
! 693: if (XGetWMName(x11_display, x11_window, &text_prop))
! 694: {
! 695: if (text_prop.value != NULL)
! 696: {
! 697: retval = TRUE;
! 698: if (!test_only)
! 699: oldtitle = strsave((char_u *)text_prop.value);
! 700: }
! 701: XFree((void *)text_prop.value);
! 702: }
! 703: }
! 704: if (oldtitle == NULL && !test_only) /* could not get old title */
! 705: oldtitle = fixedtitle;
! 706:
! 707: return retval;
! 708: }
! 709:
! 710: /*
! 711: * Determine original x11 Window icon
! 712: */
! 713:
! 714: static int
! 715: get_x11_icon(test_only)
! 716: int test_only;
! 717: {
! 718: XTextProperty text_prop;
! 719: int retval = FALSE;
! 720:
! 721: if (get_x11_windis() == OK)
! 722: {
! 723: /* Get icon name if any */
! 724: if (XGetWMIconName(x11_display, x11_window, &text_prop))
! 725: {
! 726: if (text_prop.value != NULL)
! 727: {
! 728: retval = TRUE;
! 729: if (!test_only)
! 730: oldicon = strsave((char_u *)text_prop.value);
! 731: }
! 732: XFree((void *)text_prop.value);
! 733: }
! 734: }
! 735:
! 736: /* could not get old icon, use terminal name */
! 737: if (oldicon == NULL && !test_only)
! 738: {
! 739: if (STRNCMP(term_strings[KS_NAME], "builtin_", 8) == 0)
! 740: oldicon = term_strings[KS_NAME] + 8;
! 741: else
! 742: oldicon = term_strings[KS_NAME];
! 743: }
! 744:
! 745: return retval;
! 746: }
! 747:
! 748: /*
! 749: * Set x11 Window Title
! 750: *
! 751: * get_x11_windis() must be called before this and have returned OK
! 752: */
! 753: static void
! 754: set_x11_title(title)
! 755: char_u *title;
! 756: {
! 757: #if XtSpecificationRelease >= 4
! 758: XTextProperty text_prop;
! 759:
! 760: text_prop.value = title;
! 761: text_prop.nitems = STRLEN(title);
! 762: text_prop.encoding = XA_STRING;
! 763: text_prop.format = 8;
! 764: XSetWMName(x11_display, x11_window, &text_prop);
! 765: #else
! 766: XStoreName(x11_display, x11_window, (char *)title);
! 767: #endif
! 768: XFlush(x11_display);
! 769: }
! 770:
! 771: /*
! 772: * Set x11 Window icon
! 773: *
! 774: * get_x11_windis() must be called before this and have returned OK
! 775: */
! 776: static void
! 777: set_x11_icon(icon)
! 778: char_u *icon;
! 779: {
! 780: #if XtSpecificationRelease >= 4
! 781: XTextProperty text_prop;
! 782:
! 783: text_prop.value = icon;
! 784: text_prop.nitems = STRLEN(icon);
! 785: text_prop.encoding = XA_STRING;
! 786: text_prop.format = 8;
! 787: XSetWMIconName(x11_display, x11_window, &text_prop);
! 788: #else
! 789: XSetIconName(x11_display, x11_window, (char *)icon);
! 790: #endif
! 791: XFlush(x11_display);
! 792: }
! 793:
! 794: #else /* HAVE_X11 && WANT_X11 */
! 795:
! 796: static int
! 797: get_x11_title(test_only)
! 798: int test_only;
! 799: {
! 800: if (!test_only)
! 801: oldtitle = fixedtitle;
! 802: return FALSE;
! 803: }
! 804:
! 805: static int
! 806: get_x11_icon(test_only)
! 807: int test_only;
! 808: {
! 809: if (!test_only)
! 810: {
! 811: if (STRNCMP(term_strings[KS_NAME], "builtin_", 8) == 0)
! 812: oldicon = term_strings[KS_NAME] + 8;
! 813: else
! 814: oldicon = term_strings[KS_NAME];
! 815: }
! 816: return FALSE;
! 817: }
! 818:
! 819: #endif /* HAVE_X11 && WANT_X11 */
! 820:
! 821: int
! 822: mch_can_restore_title()
! 823: {
! 824: #ifdef USE_GUI
! 825: /*
! 826: * If GUI is (going to be) used, we can always set the window title.
! 827: * Saves a bit of time, because the X11 display server does not need to be
! 828: * contacted.
! 829: */
! 830: if (gui.starting || gui.in_use)
! 831: return TRUE;
! 832: #endif
! 833: return get_x11_title(TRUE);
! 834: }
! 835:
! 836: int
! 837: mch_can_restore_icon()
! 838: {
! 839: #ifdef USE_GUI
! 840: /*
! 841: * If GUI is (going to be) used, we can always set the icon name.
! 842: * Saves a bit of time, because the X11 display server does not need to be
! 843: * contacted.
! 844: */
! 845: if (gui.starting || gui.in_use)
! 846: return TRUE;
! 847: #endif
! 848: return get_x11_icon(TRUE);
! 849: }
! 850:
! 851: /*
! 852: * Set the window title and icon.
! 853: * Currently only works for x11.
! 854: */
! 855: void
! 856: mch_settitle(title, icon)
! 857: char_u *title;
! 858: char_u *icon;
! 859: {
! 860: int type = 0;
! 861:
! 862: if (term_strings[KS_NAME] == NULL) /* no terminal name (yet) */
! 863: return;
! 864: if (title == NULL && icon == NULL) /* nothing to do */
! 865: return;
! 866:
! 867: /*
! 868: * if the window ID and the display is known, we may use X11 calls
! 869: */
! 870: #if defined(HAVE_X11) && defined(WANT_X11)
! 871: if (get_x11_windis() == OK)
! 872: type = 1;
! 873: #endif
! 874:
! 875: /*
! 876: * Note: if terminal is xterm, title is set with escape sequence rather
! 877: * than x11 calls, because the x11 calls don't always work
! 878: * Check only if the start of the terminal name is "xterm", also catch
! 879: * "xterms".
! 880: */
! 881: if (is_xterm(term_strings[KS_NAME]))
! 882: type = 2;
! 883:
! 884: if (is_iris_ansi(term_strings[KS_NAME]))
! 885: type = 3;
! 886:
! 887: if (type)
! 888: {
! 889: if (title != NULL)
! 890: {
! 891: if (oldtitle == NULL) /* first call, save title */
! 892: (void)get_x11_title(FALSE);
! 893:
! 894: switch(type)
! 895: {
! 896: #if defined(HAVE_X11) && defined(WANT_X11)
! 897: case 1: set_x11_title(title); /* x11 */
! 898: break;
! 899: #endif
! 900: case 2: outstrn((char_u *)"\033]2;"); /* xterm */
! 901: outstrn(title);
! 902: outchar(Ctrl('G'));
! 903: flushbuf();
! 904: break;
! 905:
! 906: case 3: outstrn((char_u *)"\033P1.y"); /* iris-ansi */
! 907: outstrn(title);
! 908: outstrn((char_u *)"\234");
! 909: flushbuf();
! 910: break;
! 911: }
! 912: }
! 913:
! 914: if (icon != NULL)
! 915: {
! 916: if (oldicon == NULL) /* first call, save icon */
! 917: get_x11_icon(FALSE);
! 918:
! 919: switch(type)
! 920: {
! 921: #if defined(HAVE_X11) && defined(WANT_X11)
! 922: case 1: set_x11_icon(icon); /* x11 */
! 923: break;
! 924: #endif
! 925: case 2: outstrn((char_u *)"\033]1;"); /* xterm */
! 926: outstrn(icon);
! 927: outchar(Ctrl('G'));
! 928: flushbuf();
! 929: break;
! 930:
! 931: case 3: outstrn((char_u *)"\033P3.y"); /* iris-ansi */
! 932: outstrn(icon);
! 933: outstrn((char_u *)"\234");
! 934: flushbuf();
! 935: break;
! 936: }
! 937: }
! 938: }
! 939: }
! 940:
! 941: int
! 942: is_xterm(name)
! 943: char_u *name;
! 944: {
! 945: if (name == NULL)
! 946: return FALSE;
! 947: return (vim_strnicmp(name, (char_u *)"xterm", (size_t)5) == 0 ||
! 948: STRCMP(name, "builtin_xterm") == 0);
! 949: }
! 950:
! 951: int
! 952: is_iris_ansi(name)
! 953: char_u *name;
! 954: {
! 955: if (name == NULL)
! 956: return FALSE;
! 957: return (vim_strnicmp(name, (char_u *)"iris-ansi", (size_t)9) == 0 ||
! 958: STRCMP(name, "builtin_iris-ansi") == 0);
! 959: }
! 960:
! 961: /*
! 962: * Return TRUE if "name" is a terminal for which 'ttyfast' should be set.
! 963: * This should include all windowed terminal emulators.
! 964: */
! 965: int
! 966: is_fastterm(name)
! 967: char_u *name;
! 968: {
! 969: if (name == NULL)
! 970: return FALSE;
! 971: if (is_xterm(name) || is_iris_ansi(name))
! 972: return TRUE;
! 973: return (vim_strnicmp(name, (char_u *)"hpterm", (size_t)6) == 0 ||
! 974: vim_strnicmp(name, (char_u *)"sun-cmd", (size_t)7) == 0 ||
! 975: vim_strnicmp(name, (char_u *)"screen", (size_t)6) == 0 ||
! 976: vim_strnicmp(name, (char_u *)"dtterm", (size_t)6) == 0);
! 977: }
! 978:
! 979: /*
! 980: * Restore the window/icon title.
! 981: * which is one of:
! 982: * 1 Just restore title
! 983: * 2 Just restore icon
! 984: * 3 Restore title and icon
! 985: */
! 986: void
! 987: mch_restore_title(which)
! 988: int which;
! 989: {
! 990: mch_settitle((which & 1) ? oldtitle : NULL, (which & 2) ? oldicon : NULL);
! 991: }
! 992:
! 993: /*
! 994: * Insert user name in s[len].
! 995: * Return OK if a name found.
! 996: */
! 997: int
! 998: mch_get_user_name(s, len)
! 999: char_u *s;
! 1000: int len;
! 1001: {
! 1002: #if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
! 1003: struct passwd *pw;
! 1004: #endif
! 1005: uid_t uid;
! 1006:
! 1007: uid = getuid();
! 1008: #if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
! 1009: if ((pw = getpwuid(uid)) != NULL &&
! 1010: pw->pw_name != NULL && *pw->pw_name != NUL)
! 1011: {
! 1012: STRNCPY(s, pw->pw_name, len);
! 1013: return OK;
! 1014: }
! 1015: #endif
! 1016: sprintf((char *)s, "%d", (int)uid); /* assumes s is long enough */
! 1017: return FAIL; /* a number is not a name */
! 1018: }
! 1019:
! 1020: /*
! 1021: * Insert host name is s[len].
! 1022: */
! 1023:
! 1024: #ifdef HAVE_SYS_UTSNAME_H
! 1025: void
! 1026: mch_get_host_name(s, len)
! 1027: char_u *s;
! 1028: int len;
! 1029: {
! 1030: struct utsname vutsname;
! 1031:
! 1032: uname(&vutsname);
! 1033: STRNCPY(s, vutsname.nodename, len);
! 1034: }
! 1035: #else /* HAVE_SYS_UTSNAME_H */
! 1036:
! 1037: # ifdef HAVE_SYS_SYSTEMINFO_H
! 1038: # define gethostname(nam, len) sysinfo(SI_HOSTNAME, nam, len)
! 1039: # endif
! 1040:
! 1041: void
! 1042: mch_get_host_name(s, len)
! 1043: char_u *s;
! 1044: int len;
! 1045: {
! 1046: gethostname((char *)s, len);
! 1047: }
! 1048: #endif /* HAVE_SYS_UTSNAME_H */
! 1049:
! 1050: /*
! 1051: * return process ID
! 1052: */
! 1053: long
! 1054: mch_get_pid()
! 1055: {
! 1056: return (long)getpid();
! 1057: }
! 1058:
! 1059: #if !defined(HAVE_STRERROR) && defined(USE_GETCWD)
! 1060: static char *strerror __ARGS((int));
! 1061:
! 1062: static char *
! 1063: strerror(err)
! 1064: int err;
! 1065: {
! 1066: extern int sys_nerr;
! 1067: extern char *sys_errlist[];
! 1068: static char er[20];
! 1069:
! 1070: if (err > 0 && err < sys_nerr)
! 1071: return (sys_errlist[err]);
! 1072: sprintf(er, "Error %d", err);
! 1073: return er;
! 1074: }
! 1075: #endif
! 1076:
! 1077: /*
! 1078: * Get name of current directory into buffer 'buf' of length 'len' bytes.
! 1079: * Return OK for success, FAIL for failure.
! 1080: */
! 1081: int
! 1082: mch_dirname(buf, len)
! 1083: char_u *buf;
! 1084: int len;
! 1085: {
! 1086: #if defined(USE_GETCWD)
! 1087: if (getcwd((char *)buf, len) == NULL)
! 1088: {
! 1089: STRCPY(buf, strerror(errno));
! 1090: return FAIL;
! 1091: }
! 1092: return OK;
! 1093: #else
! 1094: return (getwd((char *)buf) != NULL ? OK : FAIL);
! 1095: #endif
! 1096: }
! 1097:
! 1098: #ifdef __EMX__
! 1099: /*
! 1100: * Replace all slashes by backslashes.
! 1101: */
! 1102: static void
! 1103: slash_adjust(p)
! 1104: char_u *p;
! 1105: {
! 1106: while (*p)
! 1107: {
! 1108: if (*p == '/')
! 1109: *p = '\\';
! 1110: ++p;
! 1111: }
! 1112: }
! 1113: #endif
! 1114:
! 1115: /*
! 1116: * Get absolute filename into buffer 'buf' of length 'len' bytes.
! 1117: *
! 1118: * return FAIL for failure, OK for success
! 1119: */
! 1120: int
! 1121: FullName(fname, buf, len, force)
! 1122: char_u *fname, *buf;
! 1123: int len;
! 1124: int force; /* also expand when already absolute path name */
! 1125: {
! 1126: int l;
! 1127: #ifdef OS2
! 1128: int only_drive; /* only a drive letter is specified in file name */
! 1129: #endif
! 1130: #ifdef HAVE_FCHDIR
! 1131: int fd = -1;
! 1132: static int dont_fchdir = FALSE; /* TRUE when fchdir() doesn't work */
! 1133: #endif
! 1134: char_u olddir[MAXPATHL];
! 1135: char_u *p;
! 1136: char_u c;
! 1137: int retval = OK;
! 1138:
! 1139: if (fname == NULL) /* always fail */
! 1140: {
! 1141: *buf = NUL;
! 1142: return FAIL;
! 1143: }
! 1144:
! 1145: *buf = 0;
! 1146: if (force || !isFullName(fname)) /* if forced or not an absolute path */
! 1147: {
! 1148: /*
! 1149: * If the file name has a path, change to that directory for a moment,
! 1150: * and then do the getwd() (and get back to where we were).
! 1151: * This will get the correct path name with "../" things.
! 1152: */
! 1153: #ifdef OS2
! 1154: only_drive = 0;
! 1155: if (((p = vim_strrchr(fname, '/')) != NULL) ||
! 1156: ((p = vim_strrchr(fname, '\\')) != NULL) ||
! 1157: (((p = vim_strchr(fname, ':')) != NULL) && ++only_drive))
! 1158: #else
! 1159: if ((p = vim_strrchr(fname, '/')) != NULL)
! 1160: #endif
! 1161: {
! 1162: #ifdef HAVE_FCHDIR
! 1163: /*
! 1164: * Use fchdir() if possible, it's said to be faster and more
! 1165: * reliable. But on SunOS 4 it might not work. Check this by
! 1166: * doing a fchdir() right now.
! 1167: */
! 1168: if (!dont_fchdir)
! 1169: {
! 1170: fd = open(".", O_RDONLY | O_EXTRA);
! 1171: if (fd >= 0 && fchdir(fd) < 0)
! 1172: {
! 1173: close(fd);
! 1174: fd = -1;
! 1175: dont_fchdir = TRUE; /* don't try again */
! 1176: }
! 1177: }
! 1178: #endif
! 1179: if (
! 1180: #ifdef HAVE_FCHDIR
! 1181: fd < 0 &&
! 1182: #endif
! 1183: mch_dirname(olddir, MAXPATHL) == FAIL)
! 1184: {
! 1185: p = NULL; /* can't get current dir: don't chdir */
! 1186: retval = FAIL;
! 1187: }
! 1188: else
! 1189: {
! 1190: #ifdef OS2
! 1191: /*
! 1192: * compensate for case where ':' from "D:" was the only
! 1193: * path separator detected in the file name; the _next_
! 1194: * character has to be removed, and then restored later.
! 1195: */
! 1196: if (only_drive)
! 1197: p++;
! 1198: #endif
! 1199: c = *p;
! 1200: *p = NUL;
! 1201: if (vim_chdir((char *)fname))
! 1202: retval = FAIL;
! 1203: else
! 1204: fname = p + 1;
! 1205: *p = c;
! 1206: #ifdef OS2
! 1207: if (only_drive)
! 1208: {
! 1209: p--;
! 1210: if (retval != FAIL)
! 1211: fname--;
! 1212: }
! 1213: #endif
! 1214: }
! 1215: }
! 1216: if (mch_dirname(buf, len) == FAIL)
! 1217: {
! 1218: retval = FAIL;
! 1219: *buf = NUL;
! 1220: }
! 1221: l = STRLEN(buf);
! 1222: if (l && buf[l - 1] != '/')
! 1223: STRCAT(buf, "/");
! 1224: if (p != NULL)
! 1225: {
! 1226: #ifdef HAVE_FCHDIR
! 1227: if (fd >= 0)
! 1228: {
! 1229: fchdir(fd);
! 1230: close(fd);
! 1231: }
! 1232: else
! 1233: #endif
! 1234: vim_chdir((char *)olddir);
! 1235: }
! 1236: }
! 1237: STRCAT(buf, fname);
! 1238: #ifdef OS2
! 1239: slash_adjust(buf);
! 1240: #endif
! 1241: return retval;
! 1242: }
! 1243:
! 1244: /*
! 1245: * return TRUE is fname is an absolute path name
! 1246: */
! 1247: int
! 1248: isFullName(fname)
! 1249: char_u *fname;
! 1250: {
! 1251: #ifdef __EMX__
! 1252: return _fnisabs(fname);
! 1253: #else
! 1254: return (*fname == '/' || *fname == '~');
! 1255: #endif
! 1256: }
! 1257:
! 1258: /*
! 1259: * get file permissions for 'name'
! 1260: */
! 1261: long
! 1262: getperm(name)
! 1263: char_u *name;
! 1264: {
! 1265: struct stat statb;
! 1266:
! 1267: if (stat((char *)name, &statb))
! 1268: return -1;
! 1269: return statb.st_mode;
! 1270: }
! 1271:
! 1272: /*
! 1273: * set file permission for 'name' to 'perm'
! 1274: *
! 1275: * return FAIL for failure, OK otherwise
! 1276: */
! 1277: int
! 1278: setperm(name, perm)
! 1279: char_u *name;
! 1280: int perm;
! 1281: {
! 1282: return (chmod((char *)name, (mode_t)perm) == 0 ? OK : FAIL);
! 1283: }
! 1284:
! 1285: /*
! 1286: * return TRUE if "name" is a directory
! 1287: * return FALSE if "name" is not a directory
! 1288: * return FALSE for error
! 1289: */
! 1290: int
! 1291: mch_isdir(name)
! 1292: char_u *name;
! 1293: {
! 1294: struct stat statb;
! 1295:
! 1296: if (stat((char *)name, &statb))
! 1297: return FALSE;
! 1298: #ifdef _POSIX_SOURCE
! 1299: return (S_ISDIR(statb.st_mode) ? TRUE : FALSE);
! 1300: #else
! 1301: return ((statb.st_mode & S_IFMT) == S_IFDIR ? TRUE : FALSE);
! 1302: #endif
! 1303: }
! 1304:
! 1305: void
! 1306: mch_windexit(r)
! 1307: int r;
! 1308: {
! 1309: settmode(0);
! 1310: exiting = TRUE;
! 1311: mch_settitle(oldtitle, oldicon); /* restore xterm title */
! 1312: stoptermcap();
! 1313: flushbuf();
! 1314: ml_close_all(TRUE); /* remove all memfiles */
! 1315: may_core_dump();
! 1316: exit(r);
! 1317: }
! 1318:
! 1319: static void
! 1320: may_core_dump()
! 1321: {
! 1322: #ifdef SIGQUIT
! 1323: signal(SIGQUIT, SIG_DFL);
! 1324: if (core_dump)
! 1325: kill(getpid(), SIGQUIT); /* force a core dump */
! 1326: #endif
! 1327: }
! 1328:
! 1329: static int curr_tmode = 0; /* contains current raw/cooked mode (0 = cooked) */
! 1330:
! 1331: void
! 1332: mch_settmode(raw)
! 1333: int raw;
! 1334: {
! 1335: static int first = TRUE;
! 1336:
! 1337: /* Why is NeXT excluded here (and not in unixunix.h)? */
! 1338: #if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
! 1339: /* for "new" tty systems */
! 1340: # ifdef HAVE_TERMIOS_H
! 1341: static struct termios told;
! 1342: struct termios tnew;
! 1343: # else
! 1344: static struct termio told;
! 1345: struct termio tnew;
! 1346: # endif
! 1347:
! 1348: # ifdef TIOCLGET
! 1349: static unsigned long tty_local;
! 1350: # endif
! 1351:
! 1352: if (raw)
! 1353: {
! 1354: if (first)
! 1355: {
! 1356: first = FALSE;
! 1357: # ifdef TIOCLGET
! 1358: ioctl(0, TIOCLGET, &tty_local);
! 1359: # endif
! 1360: # if defined(HAVE_TERMIOS_H)
! 1361: tcgetattr(0, &told);
! 1362: # else
! 1363: ioctl(0, TCGETA, &told);
! 1364: # endif
! 1365: }
! 1366: tnew = told;
! 1367: /*
! 1368: * ICRNL enables typing ^V^M
! 1369: */
! 1370: tnew.c_iflag &= ~ICRNL;
! 1371: tnew.c_lflag &= ~(ICANON | ECHO | ISIG | ECHOE
! 1372: # if defined(IEXTEN) && !defined(MINT)
! 1373: | IEXTEN /* IEXTEN enables typing ^V on SOLARIS */
! 1374: /* but it breaks function keys on MINT */
! 1375: # endif
! 1376: );
! 1377: tnew.c_cc[VMIN] = 1; /* return after 1 char */
! 1378: tnew.c_cc[VTIME] = 0; /* don't wait */
! 1379: # if defined(HAVE_TERMIOS_H)
! 1380: tcsetattr(0, TCSANOW, &tnew);
! 1381: # else
! 1382: ioctl(0, TCSETA, &tnew);
! 1383: # endif
! 1384: }
! 1385: else
! 1386: {
! 1387: # if defined(HAVE_TERMIOS_H)
! 1388: tcsetattr(0, TCSANOW, &told);
! 1389: # else
! 1390: ioctl(0, TCSETA, &told);
! 1391: # endif
! 1392: # ifdef TIOCLGET
! 1393: ioctl(0, TIOCLSET, &tty_local);
! 1394: # endif
! 1395: }
! 1396: #else
! 1397: # ifndef TIOCSETN
! 1398: # define TIOCSETN TIOCSETP /* for hpux 9.0 */
! 1399: # endif
! 1400: /* for "old" tty systems */
! 1401: static struct sgttyb ttybold;
! 1402: struct sgttyb ttybnew;
! 1403:
! 1404: if (raw)
! 1405: {
! 1406: if (first)
! 1407: {
! 1408: first = FALSE;
! 1409: ioctl(0, TIOCGETP, &ttybold);
! 1410: }
! 1411: ttybnew = ttybold;
! 1412: ttybnew.sg_flags &= ~(CRMOD | ECHO);
! 1413: ttybnew.sg_flags |= RAW;
! 1414: ioctl(0, TIOCSETN, &ttybnew);
! 1415: }
! 1416: else
! 1417: ioctl(0, TIOCSETN, &ttybold);
! 1418: #endif
! 1419: curr_tmode = raw;
! 1420: }
! 1421:
! 1422: /*
! 1423: * Try to get the code for "t_kb" from the stty setting
! 1424: *
! 1425: * Even if termcap claims a backspace key, the user's setting *should*
! 1426: * prevail. stty knows more about reality than termcap does, and if
! 1427: * somebody's usual erase key is DEL (which, for most BSD users, it will
! 1428: * be), they're going to get really annoyed if their erase key starts
! 1429: * doing forward deletes for no reason. (Eric Fischer)
! 1430: */
! 1431: void
! 1432: get_stty()
! 1433: {
! 1434: char_u buf[2];
! 1435: char_u *p;
! 1436:
! 1437: /* Why is NeXT excluded here (and not in unixunix.h)? */
! 1438: #if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
! 1439: /* for "new" tty systems */
! 1440: # ifdef HAVE_TERMIOS_H
! 1441: struct termios keys;
! 1442: # else
! 1443: struct termio keys;
! 1444: # endif
! 1445:
! 1446: # if defined(HAVE_TERMIOS_H)
! 1447: if (tcgetattr(0, &keys) != -1)
! 1448: # else
! 1449: if (ioctl(0, TCGETA, &keys) != -1)
! 1450: # endif
! 1451: {
! 1452: buf[0] = keys.c_cc[VERASE];
! 1453: #else
! 1454: /* for "old" tty systems */
! 1455: struct sgttyb keys;
! 1456:
! 1457: if (ioctl(0, TIOCGETP, &keys) != -1)
! 1458: {
! 1459: buf[0] = keys.sg_erase;
! 1460: #endif
! 1461: buf[1] = NUL;
! 1462: add_termcode((char_u *)"kb", buf);
! 1463:
! 1464: /*
! 1465: * If <BS> and <DEL> are now the same, redefine <DEL>.
! 1466: */
! 1467: p = find_termcode((char_u *)"kD");
! 1468: if (p != NULL && p[0] == buf[0] && p[1] == buf[1])
! 1469: do_fixdel();
! 1470: }
! 1471: #if 0
! 1472: } /* to keep cindent happy */
! 1473: #endif
! 1474: }
! 1475:
! 1476: #ifdef USE_MOUSE
! 1477: /*
! 1478: * set mouse clicks on or off (only works for xterms)
! 1479: */
! 1480: void
! 1481: mch_setmouse(on)
! 1482: int on;
! 1483: {
! 1484: static int ison = FALSE;
! 1485:
! 1486: if (on == ison) /* return quickly if nothing to do */
! 1487: return;
! 1488:
! 1489: if (is_xterm(term_strings[KS_NAME]))
! 1490: {
! 1491: if (on)
! 1492: outstrn((char_u *)"\033[?1000h"); /* xterm: enable mouse events */
! 1493: else
! 1494: outstrn((char_u *)"\033[?1000l"); /* xterm: disable mouse events */
! 1495: }
! 1496: ison = on;
! 1497: }
! 1498: #endif
! 1499:
! 1500: /*
! 1501: * set screen mode, always fails.
! 1502: */
! 1503: int
! 1504: mch_screenmode(arg)
! 1505: char_u *arg;
! 1506: {
! 1507: EMSG("Screen mode setting not supported");
! 1508: return FAIL;
! 1509: }
! 1510:
! 1511: /*
! 1512: * Try to get the current window size:
! 1513: * 1. with an ioctl(), most accurate method
! 1514: * 2. from the environment variables LINES and COLUMNS
! 1515: * 3. from the termcap
! 1516: * 4. keep using the old values
! 1517: */
! 1518: int
! 1519: mch_get_winsize()
! 1520: {
! 1521: int old_Rows = Rows;
! 1522: int old_Columns = Columns;
! 1523: char_u *p;
! 1524:
! 1525: #ifdef USE_GUI
! 1526: if (gui.in_use)
! 1527: return gui_mch_get_winsize();
! 1528: #endif
! 1529:
! 1530: Columns = 0;
! 1531: Rows = 0;
! 1532:
! 1533: /*
! 1534: * For OS/2 use _scrsize().
! 1535: */
! 1536: # ifdef __EMX__
! 1537: {
! 1538: int s[2];
! 1539: _scrsize(s);
! 1540: Columns = s[0];
! 1541: Rows = s[1];
! 1542: }
! 1543: # endif
! 1544:
! 1545: /*
! 1546: * 1. try using an ioctl. It is the most accurate method.
! 1547: *
! 1548: * Try using TIOCGWINSZ first, some systems that have it also define TIOCGSIZE
! 1549: * but don't have a struct ttysize.
! 1550: */
! 1551: # ifdef TIOCGWINSZ
! 1552: {
! 1553: struct winsize ws;
! 1554:
! 1555: if (ioctl(0, TIOCGWINSZ, &ws) == 0)
! 1556: {
! 1557: Columns = ws.ws_col;
! 1558: Rows = ws.ws_row;
! 1559: }
! 1560: }
! 1561: # else /* TIOCGWINSZ */
! 1562: # ifdef TIOCGSIZE
! 1563: {
! 1564: struct ttysize ts;
! 1565:
! 1566: if (ioctl(0, TIOCGSIZE, &ts) == 0)
! 1567: {
! 1568: Columns = ts.ts_cols;
! 1569: Rows = ts.ts_lines;
! 1570: }
! 1571: }
! 1572: # endif /* TIOCGSIZE */
! 1573: # endif /* TIOCGWINSZ */
! 1574:
! 1575: /*
! 1576: * 2. get size from environment
! 1577: */
! 1578: if (Columns == 0 || Rows == 0)
! 1579: {
! 1580: if ((p = (char_u *)getenv("LINES")))
! 1581: Rows = atoi((char *)p);
! 1582: if ((p = (char_u *)getenv("COLUMNS")))
! 1583: Columns = atoi((char *)p);
! 1584: }
! 1585:
! 1586: #ifdef HAVE_TGETENT
! 1587: /*
! 1588: * 3. try reading the termcap
! 1589: */
! 1590: if (Columns == 0 || Rows == 0)
! 1591: getlinecol(); /* get "co" and "li" entries from termcap */
! 1592: #endif
! 1593:
! 1594: /*
! 1595: * 4. If everything fails, use the old values
! 1596: */
! 1597: if (Columns <= 0 || Rows <= 0)
! 1598: {
! 1599: Columns = old_Columns;
! 1600: Rows = old_Rows;
! 1601: return FAIL;
! 1602: }
! 1603:
! 1604: check_winsize();
! 1605:
! 1606: /* if size changed: screenalloc will allocate new screen buffers */
! 1607: return OK;
! 1608: }
! 1609:
! 1610: void
! 1611: mch_set_winsize()
! 1612: {
! 1613: char_u string[10];
! 1614:
! 1615: #ifdef USE_GUI
! 1616: if (gui.in_use)
! 1617: {
! 1618: gui_mch_set_winsize();
! 1619: return;
! 1620: }
! 1621: #endif
! 1622:
! 1623: /* try to set the window size to Rows and Columns */
! 1624: if (is_iris_ansi(term_strings[KS_NAME]))
! 1625: {
! 1626: sprintf((char *)string, "\033[203;%ld;%ld/y", Rows, Columns);
! 1627: outstrn(string);
! 1628: flushbuf();
! 1629: screen_start(); /* don't know where cursor is now */
! 1630: }
! 1631: }
! 1632:
! 1633: int
! 1634: call_shell(cmd, options)
! 1635: char_u *cmd;
! 1636: int options; /* SHELL_FILTER if called by do_filter() */
! 1637: /* SHELL_COOKED if term needs cooked mode */
! 1638: /* SHELL_EXPAND if called by ExpandWildCards() */
! 1639: {
! 1640: #ifdef USE_SYSTEM /* use system() to start the shell: simple but slow */
! 1641:
! 1642: int x;
! 1643: #ifndef __EMX__
! 1644: char_u newcmd[1024]; /* only needed for unix */
! 1645: #else /* __EMX__ */
! 1646: /*
! 1647: * Set the preferred shell in the EMXSHELL environment variable (but
! 1648: * only if it is different from what is already in the environment).
! 1649: * Emx then takes care of whether to use "/c" or "-c" in an
! 1650: * intelligent way. Simply pass the whole thing to emx's system() call.
! 1651: * Emx also starts an interactive shell if system() is passed an empty
! 1652: * string.
! 1653: */
! 1654: char_u *p, *old;
! 1655:
! 1656: if (((old = getenv("EMXSHELL")) == NULL) || strcmp(old, p_sh))
! 1657: {
! 1658: /* should check HAVE_SETENV, but I know we don't have it. */
! 1659: p = alloc(10 + strlen(p_sh));
! 1660: if (p)
! 1661: {
! 1662: sprintf(p, "EMXSHELL=%s", p_sh);
! 1663: putenv(p); /* don't free the pointer! */
! 1664: }
! 1665: }
! 1666: #endif
! 1667:
! 1668: flushbuf();
! 1669:
! 1670: if (options & SHELL_COOKED)
! 1671: settmode(0); /* set to cooked mode */
! 1672:
! 1673: #ifdef __EMX__
! 1674: if (cmd == NULL)
! 1675: x = system(""); /* this starts an interactive shell in emx */
! 1676: else
! 1677: x = system(cmd);
! 1678: if (x == -1) /* system() returns -1 when error occurs in starting shell */
! 1679: {
! 1680: MSG_OUTSTR("\nCannot execute shell ");
! 1681: msg_outstr(p_sh);
! 1682: msg_outchar('\n');
! 1683: }
! 1684: #else /* not __EMX__ */
! 1685: if (cmd == NULL)
! 1686: x = system(p_sh);
! 1687: else
! 1688: {
! 1689: sprintf(newcmd, "%s %s -c \"%s\"", p_sh,
! 1690: extra_shell_arg == NULL ? "" : (char *)extra_shell_arg,
! 1691: (char *)cmd);
! 1692: x = system(newcmd);
! 1693: }
! 1694: if (x == 127)
! 1695: {
! 1696: MSG_OUTSTR("\nCannot execute shell sh\n");
! 1697: }
! 1698: #endif /* __EMX__ */
! 1699: else if (x && !expand_interactively)
! 1700: {
! 1701: msg_outchar('\n');
! 1702: msg_outnum((long)x);
! 1703: MSG_OUTSTR(" returned\n");
! 1704: }
! 1705:
! 1706: settmode(1); /* set to raw mode */
! 1707: #ifdef OS2
! 1708: /* external command may change the window size in OS/2, so check it */
! 1709: mch_get_winsize();
! 1710: #endif
! 1711: resettitle();
! 1712: return (x ? FAIL : OK);
! 1713:
! 1714: #else /* USE_SYSTEM */ /* don't use system(), use fork()/exec() */
! 1715:
! 1716: #define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
! 1717: 127, some shell use that already */
! 1718:
! 1719: char_u newcmd[1024];
! 1720: int pid;
! 1721: #ifdef HAVE_UNION_WAIT
! 1722: union wait status;
! 1723: #else
! 1724: int status = -1;
! 1725: #endif
! 1726: int retval = FAIL;
! 1727: char **argv = NULL;
! 1728: int argc;
! 1729: int i;
! 1730: char_u *p;
! 1731: int inquote;
! 1732: #ifdef USE_GUI
! 1733: int pty_master_fd = -1; /* for pty's */
! 1734: int pty_slave_fd = -1;
! 1735: char *tty_name;
! 1736: int fd_toshell[2]; /* for pipes */
! 1737: int fd_fromshell[2];
! 1738: int pipe_error = FALSE;
! 1739: # ifdef HAVE_SETENV
! 1740: char envbuf[50];
! 1741: # else
! 1742: static char envbuf_Rows[20];
! 1743: static char envbuf_Columns[20];
! 1744: # endif
! 1745: #endif
! 1746: int did_settmode = FALSE; /* TRUE when settmode(1) called */
! 1747:
! 1748: flushbuf();
! 1749: if (options & SHELL_COOKED)
! 1750: settmode(0); /* set to cooked mode */
! 1751:
! 1752: /*
! 1753: * 1: find number of arguments
! 1754: * 2: separate them and built argv[]
! 1755: */
! 1756: STRCPY(newcmd, p_sh);
! 1757: for (i = 0; i < 2; ++i)
! 1758: {
! 1759: p = newcmd;
! 1760: inquote = FALSE;
! 1761: argc = 0;
! 1762: for (;;)
! 1763: {
! 1764: if (i == 1)
! 1765: argv[argc] = (char *)p;
! 1766: ++argc;
! 1767: while (*p && (inquote || (*p != ' ' && *p != TAB)))
! 1768: {
! 1769: if (*p == '"')
! 1770: inquote = !inquote;
! 1771: ++p;
! 1772: }
! 1773: if (*p == NUL)
! 1774: break;
! 1775: if (i == 1)
! 1776: *p++ = NUL;
! 1777: p = skipwhite(p);
! 1778: }
! 1779: if (i == 0)
! 1780: {
! 1781: argv = (char **)alloc((unsigned)((argc + 4) * sizeof(char *)));
! 1782: if (argv == NULL) /* out of memory */
! 1783: goto error;
! 1784: }
! 1785: }
! 1786: if (cmd != NULL)
! 1787: {
! 1788: if (extra_shell_arg != NULL)
! 1789: argv[argc++] = (char *)extra_shell_arg;
! 1790: argv[argc++] = "-c";
! 1791: argv[argc++] = (char *)cmd;
! 1792: }
! 1793: argv[argc] = NULL;
! 1794:
! 1795: #ifdef tower32
! 1796: /*
! 1797: * reap lost children (seems necessary on NCR Tower,
! 1798: * although I don't have a clue why...) (Slootman)
! 1799: */
! 1800: while (wait(&status) != 0 && errno != ECHILD)
! 1801: ; /* do it again, if necessary */
! 1802: #endif
! 1803:
! 1804: #ifdef USE_GUI
! 1805: /*
! 1806: * First try at using a pseudo-tty to get the stdin/stdout of the executed
! 1807: * command into the current window for the GUI.
! 1808: */
! 1809:
! 1810: if (gui.in_use && show_shell_mess)
! 1811: {
! 1812: /*
! 1813: * Try to open a master pty.
! 1814: * If this works, open the slave pty.
! 1815: * If the slave can't be opened, close the master pty.
! 1816: */
! 1817: if (p_guipty)
! 1818: {
! 1819: pty_master_fd = OpenPTY(&tty_name); /* open pty */
! 1820: if (pty_master_fd >= 0 && ((pty_slave_fd =
! 1821: open(tty_name, O_RDWR | O_EXTRA)) < 0))
! 1822: {
! 1823: close(pty_master_fd);
! 1824: pty_master_fd = -1;
! 1825: }
! 1826: }
! 1827: /*
! 1828: * If opening a pty didn't work, try using pipes.
! 1829: */
! 1830: if (pty_master_fd < 0)
! 1831: {
! 1832: pipe_error = (pipe(fd_toshell) < 0);
! 1833: if (!pipe_error) /* pipe create OK */
! 1834: {
! 1835: pipe_error = (pipe(fd_fromshell) < 0);
! 1836: if (pipe_error) /* pipe create failed */
! 1837: {
! 1838: close(fd_toshell[0]);
! 1839: close(fd_toshell[1]);
! 1840: }
! 1841: }
! 1842: if (pipe_error)
! 1843: {
! 1844: MSG_OUTSTR("\nCannot create pipes\n");
! 1845: flushbuf();
! 1846: }
! 1847: }
! 1848: }
! 1849:
! 1850: if (!pipe_error) /* pty or pipe opened or not used */
! 1851: #endif
! 1852:
! 1853: {
! 1854: if ((pid = fork()) == -1) /* maybe we should use vfork() */
! 1855: {
! 1856: MSG_OUTSTR("\nCannot fork\n");
! 1857: #ifdef USE_GUI
! 1858: if (gui.in_use && show_shell_mess)
! 1859: {
! 1860: if (pty_master_fd >= 0) /* close the pseudo tty */
! 1861: {
! 1862: close(pty_master_fd);
! 1863: close(pty_slave_fd);
! 1864: }
! 1865: else /* close the pipes */
! 1866: {
! 1867: close(fd_toshell[0]);
! 1868: close(fd_toshell[1]);
! 1869: close(fd_fromshell[0]);
! 1870: close(fd_fromshell[1]);
! 1871: }
! 1872: }
! 1873: #endif
! 1874: }
! 1875: else if (pid == 0) /* child */
! 1876: {
! 1877: reset_signals(); /* handle signals normally */
! 1878: if (!show_shell_mess)
! 1879: {
! 1880: int fd;
! 1881:
! 1882: /*
! 1883: * Don't want to show any message from the shell. Can't just
! 1884: * close stdout and stderr though, because some systems will
! 1885: * break if you try to write to them after that, so we must
! 1886: * use dup() to replace them with something else -- webb
! 1887: */
! 1888: fd = open("/dev/null", O_WRONLY | O_EXTRA);
! 1889: fclose(stdout);
! 1890: fclose(stderr);
! 1891:
! 1892: /*
! 1893: * If any of these open()'s and dup()'s fail, we just continue
! 1894: * anyway. It's not fatal, and on most systems it will make
! 1895: * no difference at all. On a few it will cause the execvp()
! 1896: * to exit with a non-zero status even when the completion
! 1897: * could be done, which is nothing too serious. If the open()
! 1898: * or dup() failed we'd just do the same thing ourselves
! 1899: * anyway -- webb
! 1900: */
! 1901: if (fd >= 0)
! 1902: {
! 1903: /* To replace stdout (file descriptor 1) */
! 1904: dup(fd);
! 1905:
! 1906: /* To replace stderr (file descriptor 2) */
! 1907: dup(fd);
! 1908:
! 1909: /* Don't need this now that we've duplicated it */
! 1910: close(fd);
! 1911: }
! 1912: }
! 1913: #ifdef USE_GUI
! 1914: else if (gui.in_use)
! 1915: {
! 1916:
! 1917: #ifdef HAVE_SETSID
! 1918: (void)setsid();
! 1919: #endif
! 1920: #ifdef TIOCSCTTY
! 1921: /* try to become controlling tty (probably doesn't work,
! 1922: * unless run by root) */
! 1923: ioctl(pty_slave_fd, TIOCSCTTY, (char *)NULL);
! 1924: #endif
! 1925: /* Simulate to have a dumb terminal (for now) */
! 1926: #ifdef HAVE_SETENV
! 1927: setenv("TERM", "dumb", 1);
! 1928: sprintf((char *)envbuf, "%ld", Rows);
! 1929: setenv("ROWS", (char *)envbuf, 1);
! 1930: sprintf((char *)envbuf, "%ld", Columns);
! 1931: setenv("COLUMNS", (char *)envbuf, 1);
! 1932: #else
! 1933: /*
! 1934: * Putenv does not copy the string, it has to remain valid.
! 1935: * Use a static array to avoid loosing allocated memory.
! 1936: */
! 1937: putenv("TERM=dumb");
! 1938: sprintf(envbuf_Rows, "ROWS=%ld", Rows);
! 1939: putenv(envbuf_Rows);
! 1940: sprintf(envbuf_Columns, "COLUMNS=%ld", Columns);
! 1941: putenv(envbuf_Columns);
! 1942: #endif
! 1943:
! 1944: if (pty_master_fd >= 0)
! 1945: {
! 1946: close(pty_master_fd); /* close master side of pty */
! 1947:
! 1948: /* set up stdin/stdout/stderr for the child */
! 1949: close(0);
! 1950: dup(pty_slave_fd);
! 1951: close(1);
! 1952: dup(pty_slave_fd);
! 1953: close(2);
! 1954: dup(pty_slave_fd);
! 1955:
! 1956: close(pty_slave_fd); /* has been dupped, close it now */
! 1957: }
! 1958: else
! 1959: {
! 1960: /* set up stdin for the child */
! 1961: close(fd_toshell[1]);
! 1962: close(0);
! 1963: dup(fd_toshell[0]);
! 1964: close(fd_toshell[0]);
! 1965:
! 1966: /* set up stdout for the child */
! 1967: close(fd_fromshell[0]);
! 1968: close(1);
! 1969: dup(fd_fromshell[1]);
! 1970: close(fd_fromshell[1]);
! 1971:
! 1972: /* set up stderr for the child */
! 1973: close(2);
! 1974: dup(1);
! 1975: }
! 1976: }
! 1977: #endif
! 1978: /*
! 1979: * There is no type cast for the argv, because the type may be
! 1980: * different on different machines. This may cause a warning
! 1981: * message with strict compilers, don't worry about it.
! 1982: */
! 1983: execvp(argv[0], argv);
! 1984: exit(EXEC_FAILED); /* exec failed, return failure code */
! 1985: }
! 1986: else /* parent */
! 1987: {
! 1988: /*
! 1989: * While child is running, ignore terminating signals.
! 1990: */
! 1991: catch_signals(SIG_IGN);
! 1992:
! 1993: #ifdef USE_GUI
! 1994:
! 1995: /*
! 1996: * For the GUI we redirect stdin, stdout and stderr to our window.
! 1997: */
! 1998: if (gui.in_use && show_shell_mess)
! 1999: {
! 2000: #define BUFLEN 100 /* length for buffer, pseudo tty limit is 128 */
! 2001: char_u buffer[BUFLEN];
! 2002: int len;
! 2003: int p_more_save;
! 2004: int old_State;
! 2005: int read_count;
! 2006: int c;
! 2007: int toshell_fd;
! 2008: int fromshell_fd;
! 2009:
! 2010: if (pty_master_fd >= 0)
! 2011: {
! 2012: close(pty_slave_fd); /* close slave side of pty */
! 2013: fromshell_fd = pty_master_fd;
! 2014: toshell_fd = dup(pty_master_fd);
! 2015: }
! 2016: else
! 2017: {
! 2018: close(fd_toshell[0]);
! 2019: close(fd_fromshell[1]);
! 2020: toshell_fd = fd_toshell[1];
! 2021: fromshell_fd = fd_fromshell[0];
! 2022: }
! 2023:
! 2024: /*
! 2025: * Write to the child if there are typed characters.
! 2026: * Read from the child if there are characters available.
! 2027: * Repeat the reading a few times if more characters are
! 2028: * available. Need to check for typed keys now and then, but
! 2029: * not too often (delays when no chars are available).
! 2030: * This loop is quit if no characters can be read from the pty
! 2031: * (WaitForChar detected special condition), or there are no
! 2032: * characters available and the child has exited.
! 2033: * Only check if the child has exited when there is no more
! 2034: * output. The child may exit before all the output has
! 2035: * been printed.
! 2036: *
! 2037: * Currently this busy loops!
! 2038: * This can probably dead-lock when the write blocks!
! 2039: */
! 2040: p_more_save = p_more;
! 2041: p_more = FALSE;
! 2042: old_State = State;
! 2043: State = EXTERNCMD; /* don't redraw at window resize */
! 2044:
! 2045: for (;;)
! 2046: {
! 2047: /*
! 2048: * Check if keys have been typed, write them to the child
! 2049: * if there are any. Don't do this if we are expanding
! 2050: * wild cards (would eat typeahead).
! 2051: */
! 2052: if (!(options & SHELL_EXPAND) &&
! 2053: (len = mch_inchar(buffer, BUFLEN - 1, 10)) != 0)
! 2054: {
! 2055: /*
! 2056: * For pipes:
! 2057: * Check for CTRL-C: sent interrupt signal to child.
! 2058: * Check for CTRL-D: EOF, close pipe to child.
! 2059: */
! 2060: if (len == 1 && (pty_master_fd < 0 || cmd != NULL))
! 2061: {
! 2062: #ifdef SIGINT
! 2063: if (buffer[0] == Ctrl('C'))
! 2064: {
! 2065: /* Use both kill() and killpg(), in case one
! 2066: * of the two fails */
! 2067: kill(pid, SIGINT);
! 2068: # ifdef HAVE_KILLPG
! 2069: killpg(0, SIGINT);
! 2070: # endif
! 2071: }
! 2072: #endif
! 2073: if (pty_master_fd < 0 && toshell_fd >= 0 &&
! 2074: buffer[0] == Ctrl('D'))
! 2075: {
! 2076: close(toshell_fd);
! 2077: toshell_fd = -1;
! 2078: }
! 2079: }
! 2080:
! 2081: /* replace K_BS by <BS> and K_DEL by <DEL> */
! 2082: for (i = 0; i < len; ++i)
! 2083: {
! 2084: if (buffer[i] == CSI && len - i > 2)
! 2085: {
! 2086: c = TERMCAP2KEY(buffer[i + 1], buffer[i + 2]);
! 2087: if (c == K_DEL || c == K_BS)
! 2088: {
! 2089: vim_memmove(buffer + i + 1, buffer + i + 3,
! 2090: (size_t)(len - i - 2));
! 2091: if (c == K_DEL)
! 2092: buffer[i] = DEL;
! 2093: else
! 2094: buffer[i] = Ctrl('H');
! 2095: len -= 2;
! 2096: }
! 2097: }
! 2098: else if (buffer[i] == '\r')
! 2099: buffer[i] = '\n';
! 2100: }
! 2101:
! 2102: /*
! 2103: * For pipes: echo the typed characters.
! 2104: * For a pty this does not seem to work.
! 2105: */
! 2106: if (pty_master_fd < 0)
! 2107: {
! 2108: for (i = 0; i < len; ++i)
! 2109: if (buffer[i] == '\n' || buffer[i] == '\b')
! 2110: msg_outchar(buffer[i]);
! 2111: else
! 2112: msg_outtrans_len(buffer + i, 1);
! 2113: windgoto(msg_row, msg_col);
! 2114: flushbuf();
! 2115: }
! 2116:
! 2117: /*
! 2118: * Write the characters to the child, unless EOF has
! 2119: * been typed for pipes. Ignore errors.
! 2120: */
! 2121: if (toshell_fd >= 0)
! 2122: write(toshell_fd, (char *)buffer, (size_t)len);
! 2123: }
! 2124:
! 2125: /*
! 2126: * Check if the child has any characters to be printed.
! 2127: * Read them and write them to our window.
! 2128: * Repeat this a few times as long as there is something
! 2129: * to do, avoid the 10ms wait for mch_inchar().
! 2130: * TODO: This should handle escape sequences.
! 2131: */
! 2132: for (read_count = 0; read_count < 10 &&
! 2133: RealWaitForChar(fromshell_fd, 10); ++read_count)
! 2134: {
! 2135: len = read(fromshell_fd, (char *)buffer,
! 2136: (size_t)BUFLEN);
! 2137: if (len == 0) /* end of file */
! 2138: goto finished;
! 2139: buffer[len] = NUL;
! 2140: msg_outstr(buffer);
! 2141: windgoto(msg_row, msg_col);
! 2142: cursor_on();
! 2143: flushbuf();
! 2144: }
! 2145:
! 2146: /*
! 2147: * Check if the child still exists when we finished
! 2148: * outputting all characters.
! 2149: */
! 2150: if (read_count == 0 &&
! 2151: #ifdef __NeXT__
! 2152: wait4(pid, &status, WNOHANG, (struct rusage *) 0) &&
! 2153: #else
! 2154: waitpid(pid, &status, WNOHANG) &&
! 2155: #endif
! 2156: WIFEXITED(status))
! 2157: break;
! 2158: }
! 2159: finished:
! 2160: p_more = p_more_save;
! 2161: State = old_State;
! 2162: if (toshell_fd >= 0)
! 2163: close(toshell_fd);
! 2164: close(fromshell_fd);
! 2165: }
! 2166: #endif /* USE_GUI */
! 2167:
! 2168: /*
! 2169: * Wait until child has exited.
! 2170: */
! 2171: #ifdef ECHILD
! 2172: /* Don't stop waiting when a signal (e.g. SIGWINCH) is received. */
! 2173: while (wait(&status) == -1 && errno != ECHILD)
! 2174: ;
! 2175: #else
! 2176: wait(&status);
! 2177: #endif
! 2178: /*
! 2179: * Set to raw mode right now, otherwise a CTRL-C after
! 2180: * catch_signals will kill Vim.
! 2181: */
! 2182: settmode(1);
! 2183: did_settmode = TRUE;
! 2184: catch_signals(deathtrap);
! 2185:
! 2186: /*
! 2187: * Check the window size, in case it changed while executing the
! 2188: * external command.
! 2189: */
! 2190: mch_get_winsize();
! 2191:
! 2192: if (WIFEXITED(status))
! 2193: {
! 2194: i = WEXITSTATUS(status);
! 2195: if (i)
! 2196: {
! 2197: if (i == EXEC_FAILED)
! 2198: {
! 2199: MSG_OUTSTR("\nCannot execute shell ");
! 2200: msg_outtrans(p_sh);
! 2201: msg_outchar('\n');
! 2202: }
! 2203: else if (!expand_interactively)
! 2204: {
! 2205: msg_outchar('\n');
! 2206: msg_outnum((long)i);
! 2207: MSG_OUTSTR(" returned\n");
! 2208: }
! 2209: }
! 2210: else
! 2211: retval = OK;
! 2212: }
! 2213: else
! 2214: MSG_OUTSTR("\nCommand terminated\n");
! 2215: }
! 2216: }
! 2217: vim_free(argv);
! 2218:
! 2219: error:
! 2220: if (!did_settmode)
! 2221: settmode(1); /* always set to raw mode */
! 2222: resettitle();
! 2223:
! 2224: return retval;
! 2225:
! 2226: #endif /* USE_SYSTEM */
! 2227: }
! 2228:
! 2229: /*
! 2230: * The input characters are buffered to be able to check for a CTRL-C.
! 2231: * This should be done with signals, but I don't know how to do that in
! 2232: * a portable way for a tty in RAW mode.
! 2233: */
! 2234:
! 2235: /*
! 2236: * Internal typeahead buffer. Includes extra space for long key code
! 2237: * descriptions which would otherwise overflow. The buffer is considered full
! 2238: * when only this extra space (or part of it) remains.
! 2239: */
! 2240: #define INBUFLEN 250
! 2241:
! 2242: static char_u inbuf[INBUFLEN + MAX_KEY_CODE_LEN];
! 2243: static int inbufcount = 0; /* number of chars in inbuf[] */
! 2244:
! 2245: /*
! 2246: * is_input_buf_full(), is_input_buf_empty(), add_to_input_buf(), and
! 2247: * trash_input_buf() are functions for manipulating the input buffer. These
! 2248: * are used by the gui_* calls when a GUI is used to handle keyboard input.
! 2249: *
! 2250: * NOTE: These functions will be identical in msdos.c etc, and should probably
! 2251: * be taken out and put elsewhere, but at the moment inbuf is only local.
! 2252: */
! 2253:
! 2254: int
! 2255: is_input_buf_full()
! 2256: {
! 2257: return (inbufcount >= INBUFLEN);
! 2258: }
! 2259:
! 2260: int
! 2261: is_input_buf_empty()
! 2262: {
! 2263: return (inbufcount == 0);
! 2264: }
! 2265:
! 2266: /* Add the given bytes to the input buffer */
! 2267: void
! 2268: add_to_input_buf(s, len)
! 2269: char_u *s;
! 2270: int len;
! 2271: {
! 2272: if (inbufcount + len > INBUFLEN + MAX_KEY_CODE_LEN)
! 2273: return; /* Shouldn't ever happen! */
! 2274:
! 2275: while (len--)
! 2276: inbuf[inbufcount++] = *s++;
! 2277: }
! 2278:
! 2279: /* Remove everything from the input buffer. Called when ^C is found */
! 2280: void
! 2281: trash_input_buf()
! 2282: {
! 2283: inbufcount = 0;
! 2284: }
! 2285:
! 2286: static int
! 2287: Read(buf, maxlen)
! 2288: char_u *buf;
! 2289: long maxlen;
! 2290: {
! 2291: if (inbufcount == 0) /* if the buffer is empty, fill it */
! 2292: fill_inbuf(TRUE);
! 2293: if (maxlen > inbufcount)
! 2294: maxlen = inbufcount;
! 2295: vim_memmove(buf, inbuf, (size_t)maxlen);
! 2296: inbufcount -= maxlen;
! 2297: if (inbufcount)
! 2298: vim_memmove(inbuf, inbuf + maxlen, (size_t)inbufcount);
! 2299: return (int)maxlen;
! 2300: }
! 2301:
! 2302: void
! 2303: mch_breakcheck()
! 2304: {
! 2305: #ifdef USE_GUI
! 2306: if (gui.in_use)
! 2307: {
! 2308: gui_mch_update();
! 2309: return;
! 2310: }
! 2311: #endif /* USE_GUI */
! 2312:
! 2313: /*
! 2314: * Check for CTRL-C typed by reading all available characters.
! 2315: * In cooked mode we should get SIGINT, no need to check.
! 2316: */
! 2317: if (curr_tmode && RealWaitForChar(0, 0L)) /* if characters available */
! 2318: fill_inbuf(FALSE);
! 2319: }
! 2320:
! 2321: static void
! 2322: fill_inbuf(exit_on_error)
! 2323: int exit_on_error;
! 2324: {
! 2325: int len;
! 2326: int try;
! 2327:
! 2328: #ifdef USE_GUI
! 2329: if (gui.in_use)
! 2330: {
! 2331: gui_mch_update();
! 2332: return;
! 2333: }
! 2334: #endif
! 2335: if (is_input_buf_full())
! 2336: return;
! 2337: /*
! 2338: * Fill_inbuf() is only called when we really need a character.
! 2339: * If we can't get any, but there is some in the buffer, just return.
! 2340: * If we can't get any, and there isn't any in the buffer, we give up and
! 2341: * exit Vim.
! 2342: */
! 2343: for (try = 0; try < 100; ++try)
! 2344: {
! 2345: len = read(0, (char *)inbuf + inbufcount,
! 2346: (size_t)(INBUFLEN - inbufcount));
! 2347: if (len > 0)
! 2348: break;
! 2349: if (!exit_on_error)
! 2350: return;
! 2351: }
! 2352: if (len <= 0)
! 2353: {
! 2354: windgoto((int)Rows - 1, 0);
! 2355: fprintf(stderr, "Vim: Error reading input, exiting...\n");
! 2356: ml_sync_all(FALSE, TRUE); /* preserve all swap files */
! 2357: getout(1);
! 2358: }
! 2359: while (len-- > 0)
! 2360: {
! 2361: /*
! 2362: * if a CTRL-C was typed, remove it from the buffer and set got_int
! 2363: */
! 2364: if (inbuf[inbufcount] == 3)
! 2365: {
! 2366: /* remove everything typed before the CTRL-C */
! 2367: vim_memmove(inbuf, inbuf + inbufcount, (size_t)(len + 1));
! 2368: inbufcount = 0;
! 2369: got_int = TRUE;
! 2370: }
! 2371: ++inbufcount;
! 2372: }
! 2373: }
! 2374:
! 2375: /*
! 2376: * Wait "msec" msec until a character is available from the keyboard or from
! 2377: * inbuf[]. msec == -1 will block forever.
! 2378: * When a GUI is being used, this will never get called -- webb
! 2379: */
! 2380:
! 2381: static int
! 2382: WaitForChar(msec)
! 2383: long msec;
! 2384: {
! 2385: if (inbufcount) /* something in inbuf[] */
! 2386: return 1;
! 2387: return RealWaitForChar(0, msec);
! 2388: }
! 2389:
! 2390: /*
! 2391: * Wait "msec" msec until a character is available from file descriptor "fd".
! 2392: * Time == -1 will block forever.
! 2393: * When a GUI is being used, this will not be used for input -- webb
! 2394: */
! 2395: static int
! 2396: RealWaitForChar(fd, msec)
! 2397: int fd;
! 2398: long msec;
! 2399: {
! 2400: #ifndef HAVE_SELECT
! 2401: struct pollfd fds;
! 2402:
! 2403: fds.fd = fd;
! 2404: fds.events = POLLIN;
! 2405: return (poll(&fds, 1, (int)msec) > 0); /* is this correct when fd != 0?? */
! 2406: #else
! 2407: struct timeval tv;
! 2408: fd_set rfds, efds;
! 2409:
! 2410: # ifdef __EMX__
! 2411: /* don't check for incoming chars if not in raw mode, because select()
! 2412: * always returns TRUE then (in some version of emx.dll) */
! 2413: if (curr_tmode == 0)
! 2414: return 0;
! 2415: # endif
! 2416:
! 2417: if (msec >= 0)
! 2418: {
! 2419: tv.tv_sec = msec / 1000;
! 2420: tv.tv_usec = (msec % 1000) * (1000000/1000);
! 2421: }
! 2422:
! 2423: /*
! 2424: * Select on ready for reading and exceptional condition (end of file).
! 2425: */
! 2426: FD_ZERO(&rfds); /* calls bzero() on a sun */
! 2427: FD_ZERO(&efds);
! 2428: FD_SET(fd, &rfds);
! 2429: FD_SET(fd, &efds);
! 2430: return (select(fd + 1, &rfds, NULL, &efds, (msec >= 0) ? &tv : NULL) > 0);
! 2431: #endif
! 2432: }
! 2433:
! 2434: /*
! 2435: * ExpandWildCards() - this code does wild-card pattern matching using the shell
! 2436: *
! 2437: * return OK for success, FAIL for error (you may lose some memory) and put
! 2438: * an error message in *file.
! 2439: *
! 2440: * num_pat is number of input patterns
! 2441: * pat is array of pointers to input patterns
! 2442: * num_file is pointer to number of matched file names
! 2443: * file is pointer to array of pointers to matched file names
! 2444: * On Unix we do not check for files only yet
! 2445: * list_notfound is ignored
! 2446: */
! 2447:
! 2448: extern char *mktemp __ARGS((char *));
! 2449: #ifndef SEEK_SET
! 2450: # define SEEK_SET 0
! 2451: #endif
! 2452: #ifndef SEEK_END
! 2453: # define SEEK_END 2
! 2454: #endif
! 2455:
! 2456: int
! 2457: ExpandWildCards(num_pat, pat, num_file, file, files_only, list_notfound)
! 2458: int num_pat;
! 2459: char_u **pat;
! 2460: int *num_file;
! 2461: char_u ***file;
! 2462: int files_only;
! 2463: int list_notfound;
! 2464: {
! 2465: int i;
! 2466: size_t len;
! 2467: char_u *p;
! 2468: #ifdef __EMX__
! 2469: # define EXPL_ALLOC_INC 16
! 2470: char_u **expl_files;
! 2471: size_t files_alloced, files_free;
! 2472:
! 2473: *num_file = 0; /* default: no files found */
! 2474: files_alloced = EXPL_ALLOC_INC; /* how much space is allocated */
! 2475: files_free = EXPL_ALLOC_INC; /* how much space is not used */
! 2476: *file = (char_u **) alloc(sizeof(char_u **) * files_alloced);
! 2477: if (!*file)
! 2478: {
! 2479: emsg(e_outofmem);
! 2480: return FAIL;
! 2481: }
! 2482:
! 2483: for (; num_pat > 0; num_pat--, pat++)
! 2484: {
! 2485: expl_files = NULL;
! 2486: if (vim_strchr(*pat, '$') || vim_strchr(*pat, '~'))
! 2487: {
! 2488: /* expand environment var or home dir */
! 2489: char_u *buf = alloc(1024);
! 2490: if (!buf)
! 2491: {
! 2492: emsg(e_outofmem);
! 2493: return FAIL;
! 2494: }
! 2495: expand_env(*pat, buf, 1024);
! 2496: if (mch_has_wildcard(buf)) /* still wildcards in there? */
! 2497: {
! 2498: expl_files = (char_u **)_fnexplode(buf);
! 2499: }
! 2500: if (expl_files == NULL)
! 2501: {
! 2502: /*
! 2503: * If no wildcard still remaining, simply add
! 2504: * the pattern to the results.
! 2505: * If wildcard did not match, add the pattern to
! 2506: * the list of results anyway. This way, doing
! 2507: * :n exist.c notexist*
! 2508: * will at least edits exist.c and then say
! 2509: * notexist* [new file]
! 2510: */
! 2511: expl_files = (char_u **)alloc(sizeof(char_u **) * 2);
! 2512: expl_files[0] = strsave(buf);
! 2513: expl_files[1] = NULL;
! 2514: }
! 2515: vim_free(buf);
! 2516: }
! 2517: else
! 2518: {
! 2519: expl_files = (char_u **)_fnexplode(*pat);
! 2520: if (expl_files == NULL)
! 2521: {
! 2522: /* see above for explanation */
! 2523: expl_files = (char_u **)alloc(sizeof(char_u **) * 2);
! 2524: expl_files[0] = strsave(*pat);
! 2525: expl_files[1] = NULL;
! 2526: }
! 2527: }
! 2528: if (!expl_files)
! 2529: {
! 2530: /* Can't happen */
! 2531: char_u msg[128];
! 2532: sprintf(msg, "%s (unix.c:%d)", e_internal, __LINE__);
! 2533: emsg(msg);
! 2534: *file = (char_u **)"";
! 2535: *num_file = 0;
! 2536: return OK;
! 2537: }
! 2538: /*
! 2539: * Count number of names resulting from expansion,
! 2540: * At the same time add a backslash to the end of names that happen to be
! 2541: * directories, and replace slashes with backslashes.
! 2542: */
! 2543: for (i = 0; (p = expl_files[i]) != NULL; i++, (*num_file)++)
! 2544: {
! 2545: if (--files_free == 0)
! 2546: {
! 2547: /* need more room in table of pointers */
! 2548: files_alloced += EXPL_ALLOC_INC;
! 2549: *file = (char_u **) realloc(*file,
! 2550: sizeof(char_u **) * files_alloced);
! 2551: files_free = EXPL_ALLOC_INC;
! 2552: }
! 2553: slash_adjust(p);
! 2554: if (mch_isdir(p))
! 2555: {
! 2556: len = strlen(p);
! 2557: p = realloc(p, len + 2);
! 2558: if (!p)
! 2559: {
! 2560: emsg(e_outofmem);
! 2561: return FAIL;
! 2562: }
! 2563: (*file)[*num_file] = p;
! 2564: p += len;
! 2565: *p++ = '\\';
! 2566: *p = 0;
! 2567: }
! 2568: else
! 2569: {
! 2570: (*file)[*num_file] = strsave(p);
! 2571: }
! 2572: }
! 2573: _fnexplodefree(expl_files);
! 2574: }
! 2575: return OK;
! 2576:
! 2577: #else /* __EMX__ */
! 2578:
! 2579: int dir;
! 2580: char_u tmpname[TMPNAMELEN];
! 2581: char_u *command;
! 2582: FILE *fd;
! 2583: char_u *buffer;
! 2584: int use_glob = FALSE;
! 2585:
! 2586: *num_file = 0; /* default: no files found */
! 2587: *file = (char_u **)"";
! 2588:
! 2589: /*
! 2590: * If there are no wildcards, just copy the names to allocated memory.
! 2591: * Saves a lot of time, because we don't have to start a new shell.
! 2592: */
! 2593: if (!have_wildcard(num_pat, pat))
! 2594: {
! 2595: *file = (char_u **)alloc(num_pat * sizeof(char_u *));
! 2596: if (*file == NULL)
! 2597: {
! 2598: *file = (char_u **)"";
! 2599: return FAIL;
! 2600: }
! 2601: for (i = 0; i < num_pat; i++)
! 2602: (*file)[i] = strsave(pat[i]);
! 2603: *num_file = num_pat;
! 2604: return OK;
! 2605: }
! 2606:
! 2607: /*
! 2608: * get a name for the temp file
! 2609: */
! 2610: STRCPY(tmpname, TMPNAME2);
! 2611: if (*mktemp((char *)tmpname) == NUL)
! 2612: {
! 2613: emsg(e_notmp);
! 2614: return FAIL;
! 2615: }
! 2616:
! 2617: /*
! 2618: * let the shell expand the patterns and write the result into the temp file
! 2619: * If we use csh, glob will work better than echo.
! 2620: */
! 2621: if ((len = STRLEN(p_sh)) >= 3 && STRCMP(p_sh + len - 3, "csh") == 0)
! 2622: use_glob = TRUE;
! 2623:
! 2624: len = TMPNAMELEN + 11;
! 2625: for (i = 0; i < num_pat; ++i) /* count the length of the patterns */
! 2626: len += STRLEN(pat[i]) + 3;
! 2627: command = alloc(len);
! 2628: if (command == NULL)
! 2629: return FAIL;
! 2630: if (use_glob)
! 2631: STRCPY(command, "glob >"); /* build the shell command */
! 2632: else
! 2633: STRCPY(command, "echo >"); /* build the shell command */
! 2634: STRCAT(command, tmpname);
! 2635: for (i = 0; i < num_pat; ++i)
! 2636: {
! 2637: #ifdef USE_SYSTEM
! 2638: STRCAT(command, " \""); /* need extra quotes because we */
! 2639: STRCAT(command, pat[i]); /* start the shell twice */
! 2640: STRCAT(command, "\"");
! 2641: #else
! 2642: STRCAT(command, " ");
! 2643: STRCAT(command, pat[i]);
! 2644: #endif
! 2645: }
! 2646: if (expand_interactively)
! 2647: show_shell_mess = FALSE;
! 2648: /*
! 2649: * If we use -f then shell variables set in .cshrc won't get expanded.
! 2650: * vi can do it, so we will too, but it is only necessary if there is a "$"
! 2651: * in one of the patterns, otherwise we can still use the fast option.
! 2652: */
! 2653: if (use_glob && !have_dollars(num_pat, pat)) /* Use csh fast option */
! 2654: extra_shell_arg = (char_u *)"-f";
! 2655: i = call_shell(command, SHELL_EXPAND); /* execute it */
! 2656: extra_shell_arg = NULL;
! 2657: show_shell_mess = TRUE;
! 2658: vim_free(command);
! 2659: if (i == FAIL) /* call_shell failed */
! 2660: {
! 2661: vim_remove(tmpname);
! 2662: /*
! 2663: * With interactive completion, the error message is not printed.
! 2664: * However with USE_SYSTEM, I don't know how to turn off error messages
! 2665: * from the shell, so screen may still get messed up -- webb.
! 2666: */
! 2667: #ifndef USE_SYSTEM
! 2668: if (!expand_interactively)
! 2669: #endif
! 2670: {
! 2671: must_redraw = CLEAR; /* probably messed up screen */
! 2672: msg_outchar('\n'); /* clear bottom line quickly */
! 2673: cmdline_row = Rows - 1; /* continue on last line */
! 2674: }
! 2675: return FAIL;
! 2676: }
! 2677:
! 2678: /*
! 2679: * read the names from the file into memory
! 2680: */
! 2681: fd = fopen((char *)tmpname, "r");
! 2682: if (fd == NULL)
! 2683: {
! 2684: emsg2(e_notopen, tmpname);
! 2685: return FAIL;
! 2686: }
! 2687: fseek(fd, 0L, SEEK_END);
! 2688: len = ftell(fd); /* get size of temp file */
! 2689: fseek(fd, 0L, SEEK_SET);
! 2690: buffer = alloc(len + 1);
! 2691: if (buffer == NULL)
! 2692: {
! 2693: vim_remove(tmpname);
! 2694: fclose(fd);
! 2695: return FAIL;
! 2696: }
! 2697: i = fread((char *)buffer, 1, len, fd);
! 2698: fclose(fd);
! 2699: vim_remove(tmpname);
! 2700: if (i != len)
! 2701: {
! 2702: emsg2(e_notread, tmpname);
! 2703: vim_free(buffer);
! 2704: return FAIL;
! 2705: }
! 2706:
! 2707: if (use_glob) /* file names are separated with NUL */
! 2708: {
! 2709: buffer[len] = NUL; /* make sure the buffers ends in NUL */
! 2710: i = 0;
! 2711: for (p = buffer; p < buffer + len; ++p)
! 2712: if (*p == NUL) /* count entry */
! 2713: ++i;
! 2714: if (len)
! 2715: ++i; /* count last entry */
! 2716: }
! 2717: else /* file names are separated with SPACE */
! 2718: {
! 2719: buffer[len] = '\n'; /* make sure the buffers ends in NL */
! 2720: p = buffer;
! 2721: for (i = 0; *p != '\n'; ++i) /* count number of entries */
! 2722: {
! 2723: while (*p != ' ' && *p != '\n') /* skip entry */
! 2724: ++p;
! 2725: p = skipwhite(p); /* skip to next entry */
! 2726: }
! 2727: }
! 2728: if (i == 0)
! 2729: {
! 2730: /*
! 2731: * Can happen when using /bin/sh and typing ":e $NO_SUCH_VAR^I".
! 2732: * /bin/sh will happily expand it to nothing rather than returning an
! 2733: * error; and hey, it's good to check anyway -- webb.
! 2734: */
! 2735: vim_free(buffer);
! 2736: *file = (char_u **)"";
! 2737: return FAIL;
! 2738: }
! 2739: *num_file = i;
! 2740: *file = (char_u **)alloc(sizeof(char_u *) * i);
! 2741: if (*file == NULL)
! 2742: {
! 2743: vim_free(buffer);
! 2744: *file = (char_u **)"";
! 2745: return FAIL;
! 2746: }
! 2747:
! 2748: /*
! 2749: * Isolate the individual file names.
! 2750: */
! 2751: p = buffer;
! 2752: for (i = 0; i < *num_file; ++i)
! 2753: {
! 2754: (*file)[i] = p;
! 2755: if (use_glob)
! 2756: {
! 2757: while (*p && p < buffer + len) /* skip entry */
! 2758: ++p;
! 2759: ++p; /* skip NUL */
! 2760: }
! 2761: else
! 2762: {
! 2763: while (*p != ' ' && *p != '\n') /* skip entry */
! 2764: ++p;
! 2765: if (*p == '\n') /* last entry */
! 2766: *p = NUL;
! 2767: else
! 2768: {
! 2769: *p++ = NUL;
! 2770: p = skipwhite(p); /* skip to next entry */
! 2771: }
! 2772: }
! 2773: }
! 2774:
! 2775: /*
! 2776: * Move the file names to allocated memory.
! 2777: */
! 2778: for (i = 0; i < *num_file; ++i)
! 2779: {
! 2780: /* Require the files to exist. Helps when using /bin/sh */
! 2781: if (expand_interactively)
! 2782: {
! 2783: struct stat st;
! 2784: int j;
! 2785:
! 2786: if (stat((char *)((*file)[i]), &st) < 0)
! 2787: {
! 2788: for (j = i; j + 1 < *num_file; ++j)
! 2789: (*file)[j] = (*file)[j + 1];
! 2790: --*num_file;
! 2791: --i;
! 2792: continue;
! 2793: }
! 2794: }
! 2795:
! 2796: /* if file doesn't exist don't add '/' */
! 2797: dir = (mch_isdir((*file)[i]));
! 2798: p = alloc((unsigned)(STRLEN((*file)[i]) + 1 + dir));
! 2799: if (p)
! 2800: {
! 2801: STRCPY(p, (*file)[i]);
! 2802: if (dir)
! 2803: STRCAT(p, "/");
! 2804: }
! 2805: (*file)[i] = p;
! 2806: }
! 2807: vim_free(buffer);
! 2808:
! 2809: if (*num_file == 0) /* rejected all entries */
! 2810: {
! 2811: vim_free(*file);
! 2812: *file = (char_u **)"";
! 2813: return FAIL;
! 2814: }
! 2815:
! 2816: return OK;
! 2817:
! 2818: #endif /* __EMX__ */
! 2819: }
! 2820:
! 2821: int
! 2822: mch_has_wildcard(p)
! 2823: char_u *p;
! 2824: {
! 2825: for ( ; *p; ++p)
! 2826: {
! 2827: if (*p == '\\' && p[1] != NUL)
! 2828: ++p;
! 2829: else if (vim_strchr((char_u *)"*?[{`~$", *p) != NULL)
! 2830: return TRUE;
! 2831: }
! 2832: return FALSE;
! 2833: }
! 2834:
! 2835: #ifndef __EMX__
! 2836: static int
! 2837: have_wildcard(num, file)
! 2838: int num;
! 2839: char_u **file;
! 2840: {
! 2841: register int i;
! 2842:
! 2843: for (i = 0; i < num; i++)
! 2844: if (mch_has_wildcard(file[i]))
! 2845: return 1;
! 2846: return 0;
! 2847: }
! 2848:
! 2849: static int
! 2850: have_dollars(num, file)
! 2851: int num;
! 2852: char_u **file;
! 2853: {
! 2854: register int i;
! 2855:
! 2856: for (i = 0; i < num; i++)
! 2857: if (vim_strchr(file[i], '$') != NULL)
! 2858: return TRUE;
! 2859: return FALSE;
! 2860: }
! 2861: #endif /* ifndef __EMX__ */
! 2862:
! 2863: #ifndef HAVE_RENAME
! 2864: /*
! 2865: * Scaled-down version of rename, which is missing in Xenix.
! 2866: * This version can only move regular files and will fail if the
! 2867: * destination exists.
! 2868: */
! 2869: int
! 2870: rename(src, dest)
! 2871: const char *src, *dest;
! 2872: {
! 2873: struct stat st;
! 2874:
! 2875: if (stat(dest, &st) >= 0) /* fail if destination exists */
! 2876: return -1;
! 2877: if (link(src, dest) != 0) /* link file to new name */
! 2878: return -1;
! 2879: if (vim_remove(src) == 0) /* delete link to old name */
! 2880: return 0;
! 2881: return -1;
! 2882: }
! 2883: #endif /* !HAVE_RENAME */