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