[BACK]Return to unix.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / vim

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 */