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