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