mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Remove the old mch_call_shell
implementation
This commit is contained in:
parent
2dcae28328
commit
57cd2d6614
492
src/os_unix.c
492
src/os_unix.c
@ -87,7 +87,6 @@ typedef union wait waitstatus;
|
|||||||
#else
|
#else
|
||||||
typedef int waitstatus;
|
typedef int waitstatus;
|
||||||
#endif
|
#endif
|
||||||
static pid_t wait4pid(pid_t, waitstatus *);
|
|
||||||
|
|
||||||
static int RealWaitForChar(int, long, int *);
|
static int RealWaitForChar(int, long, int *);
|
||||||
|
|
||||||
@ -1069,497 +1068,6 @@ void mch_new_shellsize()
|
|||||||
/* Nothing to do. */
|
/* Nothing to do. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Wait for process "child" to end.
|
|
||||||
* Return "child" if it exited properly, <= 0 on error.
|
|
||||||
*/
|
|
||||||
static pid_t wait4pid(child, status)
|
|
||||||
pid_t child;
|
|
||||||
waitstatus *status;
|
|
||||||
{
|
|
||||||
pid_t wait_pid = 0;
|
|
||||||
|
|
||||||
while (wait_pid != child) {
|
|
||||||
/* When compiled with Python threads are probably used, in which case
|
|
||||||
* wait() sometimes hangs for no obvious reason. Use waitpid()
|
|
||||||
* instead and loop (like the GUI). Also needed for other interfaces,
|
|
||||||
* they might call system(). */
|
|
||||||
# ifdef __NeXT__
|
|
||||||
wait_pid = wait4(child, status, WNOHANG, (struct rusage *)0);
|
|
||||||
# else
|
|
||||||
wait_pid = waitpid(child, status, WNOHANG);
|
|
||||||
# endif
|
|
||||||
if (wait_pid == 0) {
|
|
||||||
/* Wait for 10 msec before trying again. */
|
|
||||||
os_delay(10L, TRUE);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (wait_pid <= 0
|
|
||||||
# ifdef ECHILD
|
|
||||||
&& errno == ECHILD
|
|
||||||
# endif
|
|
||||||
)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return wait_pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mch_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_shell_arg)
|
|
||||||
{
|
|
||||||
int tmode = cur_tmode;
|
|
||||||
|
|
||||||
# define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
|
|
||||||
127, some shells use that already */
|
|
||||||
|
|
||||||
pid_t pid;
|
|
||||||
pid_t wpid = 0;
|
|
||||||
pid_t wait_pid = 0;
|
|
||||||
# ifdef HAVE_UNION_WAIT
|
|
||||||
union wait status;
|
|
||||||
# else
|
|
||||||
int status = -1;
|
|
||||||
# endif
|
|
||||||
int retval = -1;
|
|
||||||
char **argv = NULL;
|
|
||||||
int i;
|
|
||||||
int fd_toshell[2]; /* for pipes */
|
|
||||||
int fd_fromshell[2];
|
|
||||||
int pipe_error = FALSE;
|
|
||||||
char envbuf[50];
|
|
||||||
int did_settmode = FALSE; /* settmode(TMODE_RAW) called */
|
|
||||||
|
|
||||||
out_flush();
|
|
||||||
if (opts & kShellOptCooked)
|
|
||||||
settmode(TMODE_COOK); /* set to normal mode */
|
|
||||||
|
|
||||||
argv = shell_build_argv(cmd, extra_shell_arg);
|
|
||||||
|
|
||||||
if (argv == NULL) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For the GUI, when writing the output into the buffer and when reading
|
|
||||||
* input from the buffer: Try using a pseudo-tty to get the stdin/stdout
|
|
||||||
* of the executed command into the Vim window. Or use a pipe.
|
|
||||||
*/
|
|
||||||
if (opts & (kShellOptRead|kShellOptWrite)) {
|
|
||||||
{
|
|
||||||
pipe_error = (pipe(fd_toshell) < 0);
|
|
||||||
if (!pipe_error) { /* pipe create OK */
|
|
||||||
pipe_error = (pipe(fd_fromshell) < 0);
|
|
||||||
if (pipe_error) { /* pipe create failed */
|
|
||||||
close(fd_toshell[0]);
|
|
||||||
close(fd_toshell[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pipe_error) {
|
|
||||||
MSG_PUTS(_("\nCannot create pipes\n"));
|
|
||||||
out_flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pipe_error) { /* pty or pipe opened or not used */
|
|
||||||
|
|
||||||
if ((pid = fork()) == -1) { /* maybe we should use vfork() */
|
|
||||||
MSG_PUTS(_("\nCannot fork\n"));
|
|
||||||
if (opts & (kShellOptRead | kShellOptWrite)) {
|
|
||||||
{
|
|
||||||
close(fd_toshell[0]);
|
|
||||||
close(fd_toshell[1]);
|
|
||||||
close(fd_fromshell[0]);
|
|
||||||
close(fd_fromshell[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (pid == 0) { /* child */
|
|
||||||
signal_stop(); /* handle signals normally */
|
|
||||||
|
|
||||||
if (opts & (kShellOptHideMess | kShellOptExpand)) {
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Don't want to show any message from the shell. Can't just
|
|
||||||
* close stdout and stderr though, because some systems will
|
|
||||||
* break if you try to write to them after that, so we must
|
|
||||||
* use dup() to replace them with something else -- webb
|
|
||||||
* Connect stdin to /dev/null too, so ":n `cat`" doesn't hang,
|
|
||||||
* waiting for input.
|
|
||||||
*/
|
|
||||||
fd = open("/dev/null", O_RDWR | O_EXTRA, 0);
|
|
||||||
fclose(stdin);
|
|
||||||
fclose(stdout);
|
|
||||||
fclose(stderr);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If any of these open()'s and dup()'s fail, we just continue
|
|
||||||
* anyway. It's not fatal, and on most systems it will make
|
|
||||||
* no difference at all. On a few it will cause the execvp()
|
|
||||||
* to exit with a non-zero status even when the completion
|
|
||||||
* could be done, which is nothing too serious. If the open()
|
|
||||||
* or dup() failed we'd just do the same thing ourselves
|
|
||||||
* anyway -- webb
|
|
||||||
*/
|
|
||||||
if (fd >= 0) {
|
|
||||||
ignored = dup(fd); /* To replace stdin (fd 0) */
|
|
||||||
ignored = dup(fd); /* To replace stdout (fd 1) */
|
|
||||||
ignored = dup(fd); /* To replace stderr (fd 2) */
|
|
||||||
|
|
||||||
/* Don't need this now that we've duplicated it */
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
} else if (opts & (kShellOptRead|kShellOptWrite)) {
|
|
||||||
|
|
||||||
# ifdef HAVE_SETSID
|
|
||||||
/* Create our own process group, so that the child and all its
|
|
||||||
* children can be kill()ed. Don't do this when using pipes,
|
|
||||||
* because stdin is not a tty, we would lose /dev/tty. */
|
|
||||||
if (p_stmp) {
|
|
||||||
(void)setsid();
|
|
||||||
# if defined(SIGHUP)
|
|
||||||
/* When doing "!xterm&" and 'shell' is bash: the shell
|
|
||||||
* will exit and send SIGHUP to all processes in its
|
|
||||||
* group, killing the just started process. Ignore SIGHUP
|
|
||||||
* to avoid that. (suggested by Simon Schubert)
|
|
||||||
*/
|
|
||||||
signal(SIGHUP, SIG_IGN);
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
/* Simulate to have a dumb terminal (for now) */
|
|
||||||
os_setenv("TERM", "dumb", 1);
|
|
||||||
sprintf((char *)envbuf, "%ld", Rows);
|
|
||||||
os_setenv("ROWS", (char *)envbuf, 1);
|
|
||||||
sprintf((char *)envbuf, "%ld", Rows);
|
|
||||||
os_setenv("LINES", (char *)envbuf, 1);
|
|
||||||
sprintf((char *)envbuf, "%ld", Columns);
|
|
||||||
os_setenv("COLUMNS", (char *)envbuf, 1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* stderr is only redirected when using the GUI, so that a
|
|
||||||
* program like gpg can still access the terminal to get a
|
|
||||||
* passphrase using stderr.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
/* set up stdin for the child */
|
|
||||||
close(fd_toshell[1]);
|
|
||||||
close(0);
|
|
||||||
ignored = dup(fd_toshell[0]);
|
|
||||||
close(fd_toshell[0]);
|
|
||||||
|
|
||||||
/* set up stdout for the child */
|
|
||||||
close(fd_fromshell[0]);
|
|
||||||
close(1);
|
|
||||||
ignored = dup(fd_fromshell[1]);
|
|
||||||
close(fd_fromshell[1]);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* There is no type cast for the argv, because the type may be
|
|
||||||
* different on different machines. This may cause a warning
|
|
||||||
* message with strict compilers, don't worry about it.
|
|
||||||
* Call _exit() instead of exit() to avoid closing the connection
|
|
||||||
* to the X server (esp. with GTK, which uses atexit()).
|
|
||||||
*/
|
|
||||||
execvp(argv[0], argv);
|
|
||||||
_exit(EXEC_FAILED); /* exec failed, return failure code */
|
|
||||||
} else { /* parent */
|
|
||||||
/*
|
|
||||||
* While child is running, ignore terminating signals.
|
|
||||||
* Do catch CTRL-C, so that "got_int" is set.
|
|
||||||
*/
|
|
||||||
signal_reject_deadly();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For the GUI we redirect stdin, stdout and stderr to our window.
|
|
||||||
* This is also used to pipe stdin/stdout to/from the external
|
|
||||||
* command.
|
|
||||||
*/
|
|
||||||
if (opts & (kShellOptRead|kShellOptWrite)) {
|
|
||||||
# define BUFLEN 100 /* length for buffer, pseudo tty limit is 128 */
|
|
||||||
char_u buffer[BUFLEN + 1];
|
|
||||||
int buffer_off = 0; /* valid bytes in buffer[] */
|
|
||||||
char_u ta_buf[BUFLEN + 1]; /* TypeAHead */
|
|
||||||
int ta_len = 0; /* valid bytes in ta_buf[] */
|
|
||||||
int len;
|
|
||||||
int p_more_save;
|
|
||||||
int old_State;
|
|
||||||
int toshell_fd;
|
|
||||||
int fromshell_fd;
|
|
||||||
garray_T ga;
|
|
||||||
int noread_cnt;
|
|
||||||
# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
|
|
||||||
struct timeval start_tv;
|
|
||||||
# endif
|
|
||||||
|
|
||||||
{
|
|
||||||
close(fd_toshell[0]);
|
|
||||||
close(fd_fromshell[1]);
|
|
||||||
toshell_fd = fd_toshell[1];
|
|
||||||
fromshell_fd = fd_fromshell[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Write to the child if there are typed characters.
|
|
||||||
* Read from the child if there are characters available.
|
|
||||||
* Repeat the reading a few times if more characters are
|
|
||||||
* available. Need to check for typed keys now and then, but
|
|
||||||
* not too often (delays when no chars are available).
|
|
||||||
* This loop is quit if no characters can be read from the pty
|
|
||||||
* (WaitForChar detected special condition), or there are no
|
|
||||||
* characters available and the child has exited.
|
|
||||||
* Only check if the child has exited when there is no more
|
|
||||||
* output. The child may exit before all the output has
|
|
||||||
* been printed.
|
|
||||||
*
|
|
||||||
* Currently this busy loops!
|
|
||||||
* This can probably dead-lock when the write blocks!
|
|
||||||
*/
|
|
||||||
p_more_save = p_more;
|
|
||||||
p_more = FALSE;
|
|
||||||
old_State = State;
|
|
||||||
State = EXTERNCMD; /* don't redraw at window resize */
|
|
||||||
|
|
||||||
if ((opts & kShellOptWrite) && toshell_fd >= 0) {
|
|
||||||
/* Fork a process that will write the lines to the
|
|
||||||
* external program. */
|
|
||||||
if ((wpid = fork()) == -1) {
|
|
||||||
MSG_PUTS(_("\nCannot fork\n"));
|
|
||||||
} else if (wpid == 0) { /* child */
|
|
||||||
linenr_T lnum = curbuf->b_op_start.lnum;
|
|
||||||
int written = 0;
|
|
||||||
char_u *lp = ml_get(lnum);
|
|
||||||
size_t l;
|
|
||||||
|
|
||||||
close(fromshell_fd);
|
|
||||||
for (;; ) {
|
|
||||||
l = STRLEN(lp + written);
|
|
||||||
if (l == 0)
|
|
||||||
len = 0;
|
|
||||||
else if (lp[written] == NL)
|
|
||||||
/* NL -> NUL translation */
|
|
||||||
len = write(toshell_fd, "", (size_t)1);
|
|
||||||
else {
|
|
||||||
char_u *s = vim_strchr(lp + written, NL);
|
|
||||||
|
|
||||||
len = write(toshell_fd, (char *)lp + written,
|
|
||||||
s == NULL ? l
|
|
||||||
: (size_t)(s - (lp + written)));
|
|
||||||
}
|
|
||||||
if (len == (int)l) {
|
|
||||||
/* Finished a line, add a NL, unless this line
|
|
||||||
* should not have one. */
|
|
||||||
if (lnum != curbuf->b_op_end.lnum
|
|
||||||
|| !curbuf->b_p_bin
|
|
||||||
|| (lnum != curbuf->b_no_eol_lnum
|
|
||||||
&& (lnum !=
|
|
||||||
curbuf->b_ml.ml_line_count
|
|
||||||
|| curbuf->b_p_eol)))
|
|
||||||
ignored = write(toshell_fd, "\n",
|
|
||||||
(size_t)1);
|
|
||||||
++lnum;
|
|
||||||
if (lnum > curbuf->b_op_end.lnum) {
|
|
||||||
/* finished all the lines, close pipe */
|
|
||||||
close(toshell_fd);
|
|
||||||
toshell_fd = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
lp = ml_get(lnum);
|
|
||||||
written = 0;
|
|
||||||
} else if (len > 0)
|
|
||||||
written += len;
|
|
||||||
}
|
|
||||||
_exit(0);
|
|
||||||
} else { /* parent */
|
|
||||||
close(toshell_fd);
|
|
||||||
toshell_fd = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts & kShellOptRead)
|
|
||||||
ga_init(&ga, 1, BUFLEN);
|
|
||||||
|
|
||||||
noread_cnt = 0;
|
|
||||||
# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
|
|
||||||
gettimeofday(&start_tv, NULL);
|
|
||||||
# endif
|
|
||||||
for (;; ) {
|
|
||||||
len = 0;
|
|
||||||
if (got_int) {
|
|
||||||
/* CTRL-C sends a signal to the child, we ignore it
|
|
||||||
* ourselves */
|
|
||||||
# ifdef HAVE_SETSID
|
|
||||||
kill(-pid, SIGINT);
|
|
||||||
# else
|
|
||||||
kill(0, SIGINT);
|
|
||||||
# endif
|
|
||||||
if (wpid > 0)
|
|
||||||
kill(wpid, SIGINT);
|
|
||||||
got_int = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if the child has any characters to be printed.
|
|
||||||
* Read them and write them to our window. Repeat this as
|
|
||||||
* long as there is something to do, avoid the 10ms wait
|
|
||||||
* for os_inchar(), or sending typeahead characters to
|
|
||||||
* the external process.
|
|
||||||
* TODO: This should handle escape sequences, compatible
|
|
||||||
* to some terminal (vt52?).
|
|
||||||
*/
|
|
||||||
++noread_cnt;
|
|
||||||
while (RealWaitForChar(fromshell_fd, 10L, NULL)) {
|
|
||||||
len = read_eintr(fromshell_fd, buffer
|
|
||||||
+ buffer_off, (size_t)(BUFLEN - buffer_off)
|
|
||||||
);
|
|
||||||
if (len <= 0) /* end of file or error */
|
|
||||||
goto finished;
|
|
||||||
|
|
||||||
noread_cnt = 0;
|
|
||||||
if (opts & kShellOptRead) {
|
|
||||||
/* Do NUL -> NL translation, append NL separated
|
|
||||||
* lines to the current buffer. */
|
|
||||||
for (i = 0; i < len; ++i) {
|
|
||||||
if (buffer[i] == NL)
|
|
||||||
append_ga_line(&ga);
|
|
||||||
else if (buffer[i] == NUL)
|
|
||||||
ga_append(&ga, NL);
|
|
||||||
else
|
|
||||||
ga_append(&ga, buffer[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
windgoto(msg_row, msg_col);
|
|
||||||
cursor_on();
|
|
||||||
out_flush();
|
|
||||||
if (got_int)
|
|
||||||
break;
|
|
||||||
|
|
||||||
# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
|
|
||||||
{
|
|
||||||
struct timeval now_tv;
|
|
||||||
long msec;
|
|
||||||
|
|
||||||
/* Avoid that we keep looping here without
|
|
||||||
* checking for a CTRL-C for a long time. Don't
|
|
||||||
* break out too often to avoid losing typeahead. */
|
|
||||||
gettimeofday(&now_tv, NULL);
|
|
||||||
msec = (now_tv.tv_sec - start_tv.tv_sec) * 1000L
|
|
||||||
+ (now_tv.tv_usec - start_tv.tv_usec) / 1000L;
|
|
||||||
if (msec > 2000) {
|
|
||||||
noread_cnt = 5;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we already detected the child has finished break the
|
|
||||||
* loop now. */
|
|
||||||
if (wait_pid == pid)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if the child still exists, before checking for
|
|
||||||
* typed characters (otherwise we would lose typeahead).
|
|
||||||
*/
|
|
||||||
# ifdef __NeXT__
|
|
||||||
wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *)0);
|
|
||||||
# else
|
|
||||||
wait_pid = waitpid(pid, &status, WNOHANG);
|
|
||||||
# endif
|
|
||||||
if ((wait_pid == (pid_t)-1 && errno == ECHILD)
|
|
||||||
|| (wait_pid == pid && WIFEXITED(status))) {
|
|
||||||
/* Don't break the loop yet, try reading more
|
|
||||||
* characters from "fromshell_fd" first. When using
|
|
||||||
* pipes there might still be something to read and
|
|
||||||
* then we'll break the loop at the "break" above. */
|
|
||||||
wait_pid = pid;
|
|
||||||
} else
|
|
||||||
wait_pid = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
finished:
|
|
||||||
p_more = p_more_save;
|
|
||||||
if (opts & kShellOptRead) {
|
|
||||||
if (ga.ga_len > 0) {
|
|
||||||
append_ga_line(&ga);
|
|
||||||
/* remember that the NL was missing */
|
|
||||||
curbuf->b_no_eol_lnum = curwin->w_cursor.lnum;
|
|
||||||
} else
|
|
||||||
curbuf->b_no_eol_lnum = 0;
|
|
||||||
ga_clear(&ga);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Give all typeahead that wasn't used back to ui_inchar().
|
|
||||||
*/
|
|
||||||
if (ta_len)
|
|
||||||
ui_inchar_undo(ta_buf, ta_len);
|
|
||||||
State = old_State;
|
|
||||||
if (toshell_fd >= 0)
|
|
||||||
close(toshell_fd);
|
|
||||||
close(fromshell_fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Wait until our child has exited.
|
|
||||||
* Ignore wait() returning pids of other children and returning
|
|
||||||
* because of some signal like SIGWINCH.
|
|
||||||
* Don't wait if wait_pid was already set above, indicating the
|
|
||||||
* child already exited.
|
|
||||||
*/
|
|
||||||
if (wait_pid != pid)
|
|
||||||
wait_pid = wait4pid(pid, &status);
|
|
||||||
|
|
||||||
|
|
||||||
/* Make sure the child that writes to the external program is
|
|
||||||
* dead. */
|
|
||||||
if (wpid > 0) {
|
|
||||||
kill(wpid, SIGKILL);
|
|
||||||
wait4pid(wpid, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set to raw mode right now, otherwise a CTRL-C after
|
|
||||||
* catch_signals() will kill Vim.
|
|
||||||
*/
|
|
||||||
if (tmode == TMODE_RAW)
|
|
||||||
settmode(TMODE_RAW);
|
|
||||||
did_settmode = TRUE;
|
|
||||||
signal_accept_deadly();
|
|
||||||
|
|
||||||
if (WIFEXITED(status)) {
|
|
||||||
/* LINTED avoid "bitwise operation on signed value" */
|
|
||||||
retval = WEXITSTATUS(status);
|
|
||||||
if (retval != 0 && !emsg_silent) {
|
|
||||||
if (retval == EXEC_FAILED) {
|
|
||||||
MSG_PUTS(_("\nCannot execute shell "));
|
|
||||||
msg_outtrans(p_sh);
|
|
||||||
msg_putchar('\n');
|
|
||||||
} else if (!(opts & kShellOptSilent)) {
|
|
||||||
MSG_PUTS(_("\nshell returned "));
|
|
||||||
msg_outnum((long)retval);
|
|
||||||
msg_putchar('\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
MSG_PUTS(_("\nCommand terminated\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
shell_free_argv(argv);
|
|
||||||
|
|
||||||
error:
|
|
||||||
if (!did_settmode)
|
|
||||||
if (tmode == TMODE_RAW)
|
|
||||||
settmode(TMODE_RAW); /* set to raw mode */
|
|
||||||
resettitle();
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wait "msec" msec until a character is available from file descriptor "fd".
|
* Wait "msec" msec until a character is available from file descriptor "fd".
|
||||||
* "msec" == 0 will check for characters once.
|
* "msec" == 0 will check for characters once.
|
||||||
|
@ -40,7 +40,6 @@ int mch_screenmode(char_u *arg);
|
|||||||
int mch_get_shellsize(void);
|
int mch_get_shellsize(void);
|
||||||
void mch_set_shellsize(void);
|
void mch_set_shellsize(void);
|
||||||
void mch_new_shellsize(void);
|
void mch_new_shellsize(void);
|
||||||
int mch_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_shell_arg);
|
|
||||||
int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file,
|
int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file,
|
||||||
char_u ***file,
|
char_u ***file,
|
||||||
int flags);
|
int flags);
|
||||||
|
Loading…
Reference in New Issue
Block a user