eval: reimplement f_system() on top of os_system()

This evades the tempfile problem (unless of course one manually adds
redirects to the shell commandline, which some plugins seem to do, e.g.:
vim-easytags).
This commit is contained in:
Nicolas Hillegeer
2014-07-21 22:51:04 +02:00
committed by Thiago de Arruda
parent 3d3b233df8
commit 6f30b25f45

View File

@@ -14077,76 +14077,58 @@ static void f_synstack(typval_T *argvars, typval_T *rettv)
} }
} }
/* /// f_system - the VimL system() function
* "system()" function
*/
static void f_system(typval_T *argvars, typval_T *rettv) static void f_system(typval_T *argvars, typval_T *rettv)
{ {
char_u *res = NULL; rettv->v_type = VAR_STRING;
char_u *p; rettv->vval.v_string = NULL;
char_u *infile = NULL;
if (check_restricted() || check_secure()) {
return;
}
// get input to the shell command (if any), and its length
char_u buf[NUMBUFLEN]; char_u buf[NUMBUFLEN];
int err = FALSE; const char *input = (argvars[1].v_type != VAR_UNKNOWN)
FILE *fd; ? (char *) get_tv_string_buf_chk(&argvars[1], buf): NULL;
size_t input_len = input ? strlen(input) : 0;
if (check_restricted() || check_secure()) // get shell command to execute
goto done; const char *cmd = (char *) get_tv_string(&argvars[0]);
if (argvars[1].v_type != VAR_UNKNOWN) { // execute the command
/* size_t nread = 0;
* Write the string to a temp file, to be used for input of the shell char *res = NULL;
* command. int status = os_system(cmd, input, input_len, &res, &nread);
*/
if ((infile = vim_tempname()) == NULL) {
EMSG(_(e_notmp));
goto done;
}
fd = mch_fopen((char *)infile, WRITEBIN); set_vim_var_nr(VV_SHELL_ERROR, (long) status);
if (fd == NULL) {
EMSG2(_(e_notopen), infile);
goto done;
}
p = get_tv_string_buf_chk(&argvars[1], buf);
if (p == NULL) {
fclose(fd);
goto done; /* type error; errmsg already given */
}
if (fwrite(p, STRLEN(p), 1, fd) != 1)
err = TRUE;
if (fclose(fd) != 0)
err = TRUE;
if (err) {
EMSG(_("E677: Error writing temp file"));
goto done;
}
}
res = get_cmd_output(get_tv_string(&argvars[0]), infile, #if defined(USE_CR)
kShellOptSilent | kShellOptCooked); // translate <CR> into <NL>
#ifdef USE_CRNL
/* translate <CR><NL> into <NL> */
if (res != NULL) { if (res != NULL) {
char_u *s, *d; for (char *s = res; *s; ++s) {
if (*s == CAR) {
d = res; *s = NL;
for (s = res; *s; ++s) { }
if (s[0] == CAR && s[1] == NL) }
}
#elif defined(USE_CRNL)
// translate <CR><NL> into <NL>
if (res != NULL) {
char *d = res;
for (char *s = res; *s; ++s) {
if (s[0] == CAR && s[1] == NL) {
++s; ++s;
}
*d++ = *s; *d++ = *s;
} }
*d = NUL; *d = NUL;
} }
#endif #endif
done: rettv->vval.v_string = (char_u *) res;
if (infile != NULL) {
os_remove((char *)infile);
free(infile);
}
rettv->v_type = VAR_STRING;
rettv->vval.v_string = res;
} }
/* /*