shell.c (39835B)
1 #include <assert.h> 2 #include <stdbool.h> 3 #include <stdint.h> 4 #include <stdio.h> 5 #include <string.h> 6 #include <uv.h> 7 8 #include "auto/config.h" 9 #include "klib/kvec.h" 10 #include "nvim/ascii_defs.h" 11 #include "nvim/buffer.h" 12 #include "nvim/charset.h" 13 #include "nvim/errors.h" 14 #include "nvim/eval/typval_defs.h" 15 #include "nvim/eval/vars.h" 16 #include "nvim/event/defs.h" 17 #include "nvim/event/libuv_proc.h" 18 #include "nvim/event/loop.h" 19 #include "nvim/event/multiqueue.h" 20 #include "nvim/event/proc.h" 21 #include "nvim/event/rstream.h" 22 #include "nvim/event/stream.h" 23 #include "nvim/event/wstream.h" 24 #include "nvim/ex_cmds.h" 25 #include "nvim/fileio.h" 26 #include "nvim/gettext_defs.h" 27 #include "nvim/globals.h" 28 #include "nvim/macros_defs.h" 29 #include "nvim/main.h" 30 #include "nvim/mbyte.h" 31 #include "nvim/memline.h" 32 #include "nvim/memory.h" 33 #include "nvim/message.h" 34 #include "nvim/option_vars.h" 35 #include "nvim/os/fs.h" 36 #include "nvim/os/os.h" 37 #include "nvim/os/os_defs.h" 38 #include "nvim/os/shell.h" 39 #include "nvim/os/signal.h" 40 #include "nvim/os/time.h" 41 #include "nvim/path.h" 42 #include "nvim/pos_defs.h" 43 #include "nvim/profile.h" 44 #include "nvim/state_defs.h" 45 #include "nvim/strings.h" 46 #include "nvim/tag.h" 47 #include "nvim/types_defs.h" 48 #include "nvim/ui.h" 49 #include "nvim/vim_defs.h" 50 51 #define NS_1_SECOND 1000000000U // 1 second, in nanoseconds 52 #define OUT_DATA_THRESHOLD 1024 * 10U // 10KB, "a few screenfuls" of data. 53 54 #define SHELL_SPECIAL "\t \"&'$;<>()\\|" 55 56 #include "os/shell.c.generated.h" 57 58 static void save_patterns(int num_pat, char **pat, int *num_file, char ***file) 59 { 60 *file = xmalloc((size_t)num_pat * sizeof(char *)); 61 for (int i = 0; i < num_pat; i++) { 62 char *s = xstrdup(pat[i]); 63 // Be compatible with expand_filename(): halve the number of 64 // backslashes. 65 backslash_halve(s); 66 (*file)[i] = s; 67 } 68 *num_file = num_pat; 69 } 70 71 static bool have_wildcard(int num, char **file) 72 { 73 for (int i = 0; i < num; i++) { 74 if (path_has_wildcard(file[i])) { 75 return true; 76 } 77 } 78 return false; 79 } 80 81 static bool have_dollars(int num, char **file) 82 { 83 for (int i = 0; i < num; i++) { 84 if (vim_strchr(file[i], '$') != NULL) { 85 return true; 86 } 87 } 88 return false; 89 } 90 91 /// Performs wildcard pattern matching using the shell. 92 /// 93 /// @param num_pat is the number of input patterns. 94 /// @param pat is an array of pointers to input patterns. 95 /// @param[out] num_file is pointer to number of matched file names. 96 /// Set to the number of pointers in *file. 97 /// @param[out] file is pointer to array of pointers to matched file names. 98 /// Memory pointed to by the initial value of *file will 99 /// not be freed. 100 /// Set to NULL if FAIL is returned. Otherwise points to 101 /// allocated memory. 102 /// @param flags is a combination of EW_* flags used in 103 /// expand_wildcards(). 104 /// If matching fails but EW_NOTFOUND is set in flags or 105 /// there are no wildcards, the patterns from pat are 106 /// copied into *file. 107 /// 108 /// @returns OK for success or FAIL for error. 109 int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, int flags) 110 FUNC_ATTR_NONNULL_ARG(3) 111 FUNC_ATTR_NONNULL_ARG(4) 112 { 113 int i; 114 size_t len; 115 char *p; 116 char *extra_shell_arg = NULL; 117 int shellopts = kShellOptExpand | kShellOptSilent; 118 int j; 119 char *tempname; 120 #define STYLE_ECHO 0 // use "echo", the default 121 #define STYLE_GLOB 1 // use "glob", for csh 122 #define STYLE_VIMGLOB 2 // use "vimglob", for Posix sh 123 #define STYLE_PRINT 3 // use "print -N", for zsh 124 #define STYLE_BT 4 // `cmd` expansion, execute the pattern directly 125 #define STYLE_GLOBSTAR 5 // use extended shell glob for bash (this uses extended 126 // globbing functionality with globstar, needs bash > 4) 127 int shell_style = STYLE_ECHO; 128 int check_spaces; 129 static bool did_find_nul = false; 130 bool ampersand = false; 131 // vimglob() function to define for Posix shell 132 static char *sh_vimglob_func = 133 "vimglob() { while [ $# -ge 1 ]; do echo \"$1\"; shift; done }; vimglob >"; 134 // vimglob() function with globstar setting enabled, only for bash >= 4.X 135 static char *sh_globstar_opt = 136 "[[ ${BASH_VERSINFO[0]} -ge 4 ]] && shopt -s globstar; "; 137 138 bool is_fish_shell = 139 #if defined(UNIX) 140 strncmp(invocation_path_tail(p_sh, NULL), "fish", 4) == 0; 141 #else 142 false; 143 #endif 144 145 *num_file = 0; // default: no files found 146 *file = NULL; 147 148 // If there are no wildcards, just copy the names to allocated memory. 149 // Saves a lot of time, because we don't have to start a new shell. 150 if (!have_wildcard(num_pat, pat)) { 151 save_patterns(num_pat, pat, num_file, file); 152 return OK; 153 } 154 155 // Don't allow any shell command in the sandbox. 156 if (sandbox != 0 && check_secure()) { 157 return FAIL; 158 } 159 160 // Don't allow the use of backticks in secure. 161 if (secure) { 162 for (i = 0; i < num_pat; i++) { 163 if (vim_strchr(pat[i], '`') != NULL 164 && (check_secure())) { 165 return FAIL; 166 } 167 } 168 } 169 170 // get a name for the temp file 171 if ((tempname = vim_tempname()) == NULL) { 172 emsg(_(e_notmp)); 173 return FAIL; 174 } 175 176 // Let the shell expand the patterns and write the result into the temp 177 // file. 178 // STYLE_BT: NL separated 179 // If expanding `cmd` execute it directly. 180 // STYLE_GLOB: NUL separated 181 // If we use *csh, "glob" will work better than "echo". 182 // STYLE_PRINT: NL or NUL separated 183 // If we use *zsh, "print -N" will work better than "glob". 184 // STYLE_VIMGLOB: NL separated 185 // If we use *sh*, we define "vimglob()". 186 // STYLE_GLOBSTAR: NL separated 187 // If we use *bash*, we define "vimglob() and enable globstar option". 188 // STYLE_ECHO: space separated. 189 // A shell we don't know, stay safe and use "echo". 190 if (num_pat == 1 && *pat[0] == '`' 191 && (len = strlen(pat[0])) > 2 192 && *(pat[0] + len - 1) == '`') { 193 shell_style = STYLE_BT; 194 } else if ((len = strlen(p_sh)) >= 3) { 195 if (strcmp(p_sh + len - 3, "csh") == 0) { 196 shell_style = STYLE_GLOB; 197 } else if (strcmp(p_sh + len - 3, "zsh") == 0) { 198 shell_style = STYLE_PRINT; 199 } 200 } 201 if (shell_style == STYLE_ECHO) { 202 if (strstr(path_tail(p_sh), "bash") != NULL) { 203 shell_style = STYLE_GLOBSTAR; 204 } else if (strstr(path_tail(p_sh), "sh") != NULL) { 205 shell_style = STYLE_VIMGLOB; 206 } 207 } 208 209 // Compute the length of the command. We need 2 extra bytes: for the 210 // optional '&' and for the NUL. 211 // Worst case: "unset nonomatch; print -N >" plus two is 29 212 len = strlen(tempname) + 29; 213 if (shell_style == STYLE_VIMGLOB) { 214 len += strlen(sh_vimglob_func); 215 } else if (shell_style == STYLE_GLOBSTAR) { 216 len += strlen(sh_vimglob_func) + strlen(sh_globstar_opt); 217 } 218 219 for (i = 0; i < num_pat; i++) { 220 // Count the length of the patterns in the same way as they are put in 221 // "command" below. 222 len++; // add space 223 for (j = 0; pat[i][j] != NUL; j++) { 224 if (vim_strchr(SHELL_SPECIAL, (uint8_t)pat[i][j]) != NULL) { 225 len++; // may add a backslash 226 } 227 len++; 228 } 229 } 230 231 if (is_fish_shell) { 232 len += sizeof("egin;" " end") - 1; 233 } 234 235 char *command = xmalloc(len); 236 237 // Build the shell command: 238 // - Set $nonomatch depending on EW_NOTFOUND (hopefully the shell 239 // recognizes this). 240 // - Add the shell command to print the expanded names. 241 // - Add the temp file name. 242 // - Add the file name patterns. 243 if (shell_style == STYLE_BT) { 244 // change `command; command& ` to (command; command ) 245 if (is_fish_shell) { 246 STRCPY(command, "begin; "); 247 } else { 248 STRCPY(command, "("); 249 } 250 strcat(command, pat[0] + 1); // exclude first backtick 251 p = command + strlen(command) - 1; 252 if (is_fish_shell) { 253 *p-- = ';'; 254 strcat(command, " end"); 255 } else { 256 *p-- = ')'; // remove last backtick 257 } 258 while (p > command && ascii_iswhite(*p)) { 259 p--; 260 } 261 if (*p == '&') { // remove trailing '&' 262 ampersand = true; 263 *p = ' '; 264 } 265 strcat(command, ">"); 266 } else { 267 STRCPY(command, ""); 268 if (shell_style == STYLE_GLOB) { 269 // Assume the nonomatch option is valid only for csh like shells, 270 // otherwise, this may set the positional parameters for the shell, 271 // e.g. "$*". 272 if (flags & EW_NOTFOUND) { 273 strcat(command, "set nonomatch; "); 274 } else { 275 strcat(command, "unset nonomatch; "); 276 } 277 } 278 if (shell_style == STYLE_GLOB) { 279 strcat(command, "glob >"); 280 } else if (shell_style == STYLE_PRINT) { 281 strcat(command, "print -N >"); 282 } else if (shell_style == STYLE_VIMGLOB) { 283 strcat(command, sh_vimglob_func); 284 } else if (shell_style == STYLE_GLOBSTAR) { 285 strcat(command, sh_globstar_opt); 286 strcat(command, sh_vimglob_func); 287 } else { 288 strcat(command, "echo >"); 289 } 290 } 291 292 strcat(command, tempname); 293 294 if (shell_style != STYLE_BT) { 295 for (i = 0; i < num_pat; i++) { 296 // Put a backslash before special 297 // characters, except inside ``. 298 bool intick = false; 299 300 p = command + strlen(command); 301 *p++ = ' '; 302 for (j = 0; pat[i][j] != NUL; j++) { 303 if (pat[i][j] == '`') { 304 intick = !intick; 305 } else if (pat[i][j] == '\\' && pat[i][j + 1] != NUL) { 306 // Remove a backslash, take char literally. But keep 307 // backslash inside backticks, before a special character 308 // and before a backtick. 309 if (intick 310 || vim_strchr(SHELL_SPECIAL, (uint8_t)pat[i][j + 1]) != NULL 311 || pat[i][j + 1] == '`') { 312 *p++ = '\\'; 313 } 314 j++; 315 } else if (!intick 316 && ((flags & EW_KEEPDOLLAR) == 0 || pat[i][j] != '$') 317 && vim_strchr(SHELL_SPECIAL, (uint8_t)pat[i][j]) != NULL) { 318 // Put a backslash before a special character, but not 319 // when inside ``. And not for $var when EW_KEEPDOLLAR is 320 // set. 321 *p++ = '\\'; 322 } 323 324 // Copy one character. 325 *p++ = pat[i][j]; 326 } 327 *p = NUL; 328 } 329 } 330 331 if (flags & EW_SILENT) { 332 shellopts |= kShellOptHideMess; 333 } 334 335 if (ampersand) { 336 strcat(command, "&"); // put the '&' after the redirection 337 } 338 339 // Using zsh -G: If a pattern has no matches, it is just deleted from 340 // the argument list, otherwise zsh gives an error message and doesn't 341 // expand any other pattern. 342 if (shell_style == STYLE_PRINT) { 343 extra_shell_arg = "-G"; // Use zsh NULL_GLOB option 344 345 // If we use -f then shell variables set in .cshrc won't get expanded. 346 // vi can do it, so we will too, but it is only necessary if there is a "$" 347 // in one of the patterns, otherwise we can still use the fast option. 348 } else if (shell_style == STYLE_GLOB && !have_dollars(num_pat, pat)) { 349 extra_shell_arg = "-f"; // Use csh fast option 350 } 351 352 // execute the shell command 353 i = call_shell(command, shellopts, extra_shell_arg); 354 355 // When running in the background, give it some time to create the temp 356 // file, but don't wait for it to finish. 357 if (ampersand) { 358 os_delay(10, true); 359 } 360 361 xfree(command); 362 363 if (i) { // os_call_shell() failed 364 os_remove(tempname); 365 xfree(tempname); 366 // With interactive completion, the error message is not printed. 367 if (!(flags & EW_SILENT)) { 368 msg_putchar('\n'); // clear bottom line quickly 369 cmdline_row = Rows - 1; // continue on last line 370 msg(_(e_wildexpand), 0); 371 msg_start(); // don't overwrite this message 372 } 373 374 // If a `cmd` expansion failed, don't list `cmd` as a match, even when 375 // EW_NOTFOUND is given 376 if (shell_style == STYLE_BT) { 377 return FAIL; 378 } 379 goto notfound; 380 } 381 382 // read the names from the file into memory 383 FILE *fd = fopen(tempname, READBIN); 384 if (fd == NULL) { 385 // Something went wrong, perhaps a file name with a special char. 386 if (!(flags & EW_SILENT)) { 387 msg(_(e_wildexpand), 0); 388 msg_start(); // don't overwrite this message 389 } 390 xfree(tempname); 391 goto notfound; 392 } 393 int fseek_res = fseek(fd, 0, SEEK_END); 394 if (fseek_res < 0) { 395 xfree(tempname); 396 fclose(fd); 397 return FAIL; 398 } 399 int64_t templen = ftell(fd); // get size of temp file 400 if (templen < 0) { 401 xfree(tempname); 402 fclose(fd); 403 return FAIL; 404 } 405 #if 8 > SIZEOF_SIZE_T 406 assert(templen <= SIZE_MAX); // NOLINT(runtime/int) 407 #endif 408 len = (size_t)templen; 409 fseek(fd, 0, SEEK_SET); 410 char *buffer = xmalloc(len + 1); 411 // fread() doesn't terminate buffer with NUL; 412 // appropriate termination (not always NUL) is done below. 413 size_t readlen = fread(buffer, 1, len, fd); 414 fclose(fd); 415 os_remove(tempname); 416 if (readlen != len) { 417 // unexpected read error 418 semsg(_(e_cant_read_file_str), tempname); 419 xfree(tempname); 420 xfree(buffer); 421 return FAIL; 422 } 423 xfree(tempname); 424 425 // file names are separated with Space 426 if (shell_style == STYLE_ECHO) { 427 buffer[len] = '\n'; // make sure the buffer ends in NL 428 p = buffer; 429 for (i = 0; *p != '\n'; i++) { // count number of entries 430 while (*p != ' ' && *p != '\n') { 431 p++; 432 } 433 p = skipwhite(p); // skip to next entry 434 } 435 // file names are separated with NL 436 } else if (shell_style == STYLE_BT 437 || shell_style == STYLE_VIMGLOB 438 || shell_style == STYLE_GLOBSTAR) { 439 buffer[len] = NUL; // make sure the buffer ends in NUL 440 p = buffer; 441 for (i = 0; *p != NUL; i++) { // count number of entries 442 while (*p != '\n' && *p != NUL) { 443 p++; 444 } 445 if (*p != NUL) { 446 p++; 447 } 448 p = skipwhite(p); // skip leading white space 449 } 450 // file names are separated with NUL 451 } else { 452 // Some versions of zsh use spaces instead of NULs to separate 453 // results. Only do this when there is no NUL before the end of the 454 // buffer, otherwise we would never be able to use file names with 455 // embedded spaces when zsh does use NULs. 456 // When we found a NUL once, we know zsh is OK, set did_find_nul and 457 // don't check for spaces again. 458 check_spaces = false; 459 if (shell_style == STYLE_PRINT && !did_find_nul) { 460 // If there is a NUL, set did_find_nul, else set check_spaces 461 buffer[len] = NUL; 462 if (len && (int)strlen(buffer) < (int)len) { 463 did_find_nul = true; 464 } else { 465 check_spaces = true; 466 } 467 } 468 469 // Make sure the buffer ends with a NUL. For STYLE_PRINT there 470 // already is one, for STYLE_GLOB it needs to be added. 471 if (len && buffer[len - 1] == NUL) { 472 len--; 473 } else { 474 buffer[len] = NUL; 475 } 476 for (p = buffer; p < buffer + len; p++) { 477 if (*p == NUL || (*p == ' ' && check_spaces)) { // count entry 478 i++; 479 *p = NUL; 480 } 481 } 482 if (len) { 483 i++; // count last entry 484 } 485 } 486 assert(buffer[len] == NUL || buffer[len] == '\n'); 487 488 if (i == 0) { 489 // Can happen when using /bin/sh and typing ":e $NO_SUCH_VAR^I". 490 // /bin/sh will happily expand it to nothing rather than returning an 491 // error; and hey, it's good to check anyway -- webb. 492 xfree(buffer); 493 goto notfound; 494 } 495 *num_file = i; 496 *file = xmalloc(sizeof(char *) * (size_t)i); 497 498 // Isolate the individual file names. 499 p = buffer; 500 for (i = 0; i < *num_file; i++) { 501 (*file)[i] = p; 502 // Space or NL separates 503 if (shell_style == STYLE_ECHO || shell_style == STYLE_BT 504 || shell_style == STYLE_VIMGLOB || shell_style == STYLE_GLOBSTAR) { 505 while (!(shell_style == STYLE_ECHO && *p == ' ') 506 && *p != '\n' && *p != NUL) { 507 p++; 508 } 509 if (p == buffer + len) { // last entry 510 *p = NUL; 511 } else { 512 *p++ = NUL; 513 p = skipwhite(p); // skip to next entry 514 } 515 } else { // NUL separates 516 while (*p && p < buffer + len) { // skip entry 517 p++; 518 } 519 p++; // skip NUL 520 } 521 } 522 523 // Move the file names to allocated memory. 524 for (j = 0, i = 0; i < *num_file; i++) { 525 // Require the files to exist. Helps when using /bin/sh 526 if (!(flags & EW_NOTFOUND) && !os_path_exists((*file)[i])) { 527 continue; 528 } 529 530 // check if this entry should be included 531 bool dir = (os_isdir((*file)[i])); 532 if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE))) { 533 continue; 534 } 535 536 // Skip files that are not executable if we check for that. 537 if (!dir && (flags & EW_EXEC) 538 && !os_can_exe((*file)[i], NULL, !(flags & EW_SHELLCMD))) { 539 continue; 540 } 541 542 p = xmalloc(strlen((*file)[i]) + 1 + dir); 543 STRCPY(p, (*file)[i]); 544 if (dir) { 545 add_pathsep(p); // add '/' to a directory name 546 } 547 (*file)[j++] = p; 548 } 549 xfree(buffer); 550 *num_file = j; 551 552 if (*num_file == 0) { // rejected all entries 553 XFREE_CLEAR(*file); 554 goto notfound; 555 } 556 557 return OK; 558 559 notfound: 560 if (flags & EW_NOTFOUND) { 561 save_patterns(num_pat, pat, num_file, file); 562 return OK; 563 } 564 return FAIL; 565 } 566 567 /// Builds the argument vector for running the user-configured 'shell' (p_sh) 568 /// with an optional command prefixed by 'shellcmdflag' (p_shcf). E.g.: 569 /// 570 /// ["shell", "-extra_args", "-shellcmdflag", "command with spaces"] 571 /// 572 /// @param cmd Command string, or NULL to run an interactive shell. 573 /// @param extra_args Extra arguments to the shell, or NULL. 574 /// @return Newly allocated argument vector. Must be freed with shell_free_argv. 575 char **shell_build_argv(const char *cmd, const char *extra_args) 576 FUNC_ATTR_NONNULL_RET 577 { 578 size_t argc = tokenize(p_sh, NULL) + (cmd ? tokenize(p_shcf, NULL) : 0); 579 char **rv = xmalloc((argc + 4) * sizeof(*rv)); 580 581 // Split 'shell' 582 size_t i = tokenize(p_sh, rv); 583 584 if (extra_args) { 585 rv[i++] = xstrdup(extra_args); // Push a copy of `extra_args` 586 } 587 588 if (cmd) { 589 i += tokenize(p_shcf, rv + i); // Split 'shellcmdflag' 590 rv[i++] = shell_xescape_xquote(cmd); // Copy (and escape) `cmd`. 591 } 592 593 rv[i] = NULL; 594 595 assert(rv[0]); 596 597 return rv; 598 } 599 600 /// Releases the memory allocated by `shell_build_argv`. 601 /// 602 /// @param argv The argument vector. 603 void shell_free_argv(char **argv) 604 { 605 char **p = argv; 606 if (p == NULL) { 607 // Nothing was allocated, return 608 return; 609 } 610 while (*p != NULL) { 611 // Free each argument 612 xfree(*p); 613 p++; 614 } 615 xfree(argv); 616 } 617 618 /// Joins shell arguments from `argv` into a new string. 619 /// If the result is too long it is truncated with ellipsis ("..."). 620 /// 621 /// @returns[allocated] `argv` joined to a string. 622 char *shell_argv_to_str(char **const argv) 623 FUNC_ATTR_NONNULL_ALL 624 { 625 size_t n = 0; 626 char **p = argv; 627 char *rv = xcalloc(256, sizeof(*rv)); 628 const size_t maxsize = (256 * sizeof(*rv)); 629 if (*p == NULL) { 630 return rv; 631 } 632 while (*p != NULL) { 633 xstrlcat(rv, "'", maxsize); 634 xstrlcat(rv, *p, maxsize); 635 n = xstrlcat(rv, "' ", maxsize); 636 if (n >= maxsize) { 637 break; 638 } 639 p++; 640 } 641 if (n < maxsize) { 642 rv[n - 1] = NUL; 643 } else { 644 // Command too long, show ellipsis: "/bin/bash 'foo' 'bar'..." 645 rv[maxsize - 4] = '.'; 646 rv[maxsize - 3] = '.'; 647 rv[maxsize - 2] = '.'; 648 rv[maxsize - 1] = NUL; 649 } 650 return rv; 651 } 652 653 /// Calls the user-configured 'shell' (p_sh) for running a command or wildcard 654 /// expansion. 655 /// 656 /// @param cmd The command to execute, or NULL to run an interactive shell. 657 /// @param opts Options that control how the shell will work. 658 /// @param extra_args Extra arguments to the shell, or NULL. 659 /// 660 /// @return shell command exit code 661 int os_call_shell(char *cmd, int opts, char *extra_args) 662 { 663 StringBuilder input = KV_INITIAL_VALUE; 664 char *output = NULL; 665 char **output_ptr = NULL; 666 int current_state = State; 667 bool forward_output = true; 668 669 // While the child is running, ignore terminating signals 670 signal_reject_deadly(); 671 672 if (opts & (kShellOptHideMess | kShellOptExpand)) { 673 forward_output = false; 674 } else { 675 State = MODE_EXTERNCMD; 676 677 if (opts & kShellOptWrite) { 678 read_input(&input); 679 } 680 681 if (opts & kShellOptRead) { 682 output_ptr = &output; 683 forward_output = false; 684 } else if (opts & kShellOptDoOut) { 685 // Caller has already redirected output 686 forward_output = false; 687 } 688 } 689 690 size_t nread; 691 int exitcode = do_os_system(shell_build_argv(cmd, extra_args), 692 input.items, input.size, output_ptr, &nread, 693 emsg_silent, forward_output); 694 kv_destroy(input); 695 696 if (output) { 697 write_output(output, nread, true); 698 xfree(output); 699 } 700 701 if (!emsg_silent && exitcode != 0 && !(opts & kShellOptSilent)) { 702 msg_ext_set_kind("shell_ret"); 703 msg_puts(_("\nshell returned ")); 704 msg_outnum(exitcode); 705 msg_putchar('\n'); 706 } 707 708 State = current_state; 709 signal_accept_deadly(); 710 711 return exitcode; 712 } 713 714 /// os_call_shell() wrapper. Handles 'verbose', :profile, and v:shell_error. 715 /// Invalidates cached tags. 716 /// 717 /// @param opts a combination of ShellOpts flags 718 /// 719 /// @return shell command exit code 720 int call_shell(char *cmd, int opts, char *extra_shell_arg) 721 { 722 int retval; 723 proftime_T wait_time; 724 725 if (p_verbose > 3) { 726 verbose_enter(); 727 smsg(0, _("Executing command: \"%s\""), cmd == NULL ? p_sh : cmd); 728 msg_putchar('\n'); 729 verbose_leave(); 730 } 731 732 if (do_profiling == PROF_YES) { 733 prof_child_enter(&wait_time); 734 } 735 736 if (*p_sh == NUL) { 737 emsg(_(e_shellempty)); 738 retval = -1; 739 } else { 740 // The external command may update a tags file, clear cached tags. 741 tag_freematch(); 742 743 retval = os_call_shell(cmd, opts, extra_shell_arg); 744 } 745 746 set_vim_var_nr(VV_SHELL_ERROR, (varnumber_T)retval); 747 if (do_profiling == PROF_YES) { 748 prof_child_exit(&wait_time); 749 } 750 751 return retval; 752 } 753 754 /// Get the stdout of an external command. 755 /// If "ret_len" is NULL replace NUL characters with NL. When "ret_len" is not 756 /// NULL store the length there. 757 /// 758 /// @param cmd command to execute 759 /// @param infile optional input file name 760 /// @param flags can be kShellOptSilent or 0 761 /// @param ret_len length of the stdout 762 /// 763 /// @return an allocated string, or NULL for error. 764 char *get_cmd_output(char *cmd, char *infile, int flags, size_t *ret_len) 765 { 766 char *buffer = NULL; 767 768 if (check_secure()) { 769 return NULL; 770 } 771 772 // get a name for the temp file 773 char *tempname = vim_tempname(); 774 if (tempname == NULL) { 775 emsg(_(e_notmp)); 776 return NULL; 777 } 778 779 // Add the redirection stuff 780 char *command = make_filter_cmd(cmd, infile, tempname, false); 781 782 // Call the shell to execute the command (errors are ignored). 783 // Don't check timestamps here. 784 no_check_timestamps++; 785 call_shell(command, kShellOptDoOut | kShellOptExpand | flags, NULL); 786 no_check_timestamps--; 787 788 xfree(command); 789 790 // read the names from the file into memory 791 FILE *fd = os_fopen(tempname, READBIN); 792 793 // Not being able to seek means we can't read the file. 794 long len_l; 795 if (fd == NULL 796 || fseek(fd, 0L, SEEK_END) == -1 797 || (len_l = ftell(fd)) == -1 // get size of temp file 798 || fseek(fd, 0L, SEEK_SET) == -1) { // back to the start 799 semsg(_(e_cannot_read_from_str_2), tempname); 800 if (fd != NULL) { 801 fclose(fd); 802 } 803 goto done; 804 } 805 806 size_t len = (size_t)len_l; 807 buffer = xmalloc(len + 1); 808 size_t i = fread(buffer, 1, len, fd); 809 fclose(fd); 810 os_remove(tempname); 811 if (i != len) { 812 semsg(_(e_cant_read_file_str), tempname); 813 XFREE_CLEAR(buffer); 814 } else if (ret_len == NULL) { 815 // Change NUL into SOH, otherwise the string is truncated. 816 for (i = 0; i < len; i++) { 817 if (buffer[i] == NUL) { 818 buffer[i] = 1; 819 } 820 } 821 822 buffer[len] = NUL; // make sure the buffer is terminated 823 } else { 824 *ret_len = len; 825 } 826 827 done: 828 xfree(tempname); 829 return buffer; 830 } 831 /// os_system - synchronously execute a command in the shell 832 /// 833 /// example: 834 /// char *output = NULL; 835 /// size_t nread = 0; 836 /// char *argv[] = {"ls", "-la", NULL}; 837 /// int exitcode = os_system(argv, NULL, 0, &output, &nread); 838 /// 839 /// @param argv The commandline arguments to be passed to the shell. `argv` 840 /// will be consumed. 841 /// @param input The input to the shell (NULL for no input), passed to the 842 /// stdin of the resulting process. 843 /// @param len The length of the input buffer (not used if `input` == NULL) 844 /// @param[out] output Pointer to a location where the output will be 845 /// allocated and stored. Will point to NULL if the shell 846 /// command did not output anything. If NULL is passed, 847 /// the shell output will be ignored. 848 /// @param[out] nread the number of bytes in the returned buffer (if the 849 /// returned buffer is not NULL) 850 /// @return the return code of the process, -1 if the process couldn't be 851 /// started properly 852 int os_system(char **argv, const char *input, size_t len, char **output, 853 size_t *nread) FUNC_ATTR_NONNULL_ARG(1) 854 { 855 return do_os_system(argv, input, len, output, nread, true, false); 856 } 857 858 static int do_os_system(char **argv, const char *input, size_t len, char **output, size_t *nread, 859 bool silent, bool forward_output) 860 { 861 int exitcode = -1; 862 863 #ifdef MSWIN 864 // do not execute anything from the current directory by setting the 865 // environment variable $NoDefaultCurrentDirectoryInExePath 866 char *oldval = os_getenv("NoDefaultCurrentDirectoryInExePath"); 867 os_setenv("NoDefaultCurrentDirectoryInExePath", "1", true); 868 #endif 869 870 out_data_decide_throttle(0); // Initialize throttle decider. 871 out_data_ring(NULL, 0); // Initialize output ring-buffer. 872 bool has_input = (input != NULL && len > 0); 873 874 // the output buffer 875 StringBuilder buf = KV_INITIAL_VALUE; 876 stream_read_cb data_cb = system_data_cb; 877 if (nread) { 878 *nread = 0; 879 } 880 881 if (forward_output) { 882 data_cb = out_data_cb; 883 } else if (!output) { 884 data_cb = NULL; 885 } 886 887 // Copy the program name in case we need to report an error. 888 char prog[MAXPATHL]; 889 xstrlcpy(prog, argv[0], MAXPATHL); 890 891 LibuvProc uvproc = libuv_proc_init(&main_loop, &buf); 892 Proc *proc = &uvproc.proc; 893 MultiQueue *events = multiqueue_new_child(main_loop.events); 894 proc->events = events; 895 proc->argv = argv; 896 int status = proc_spawn(proc, has_input, true, true); 897 if (status) { 898 loop_poll_events(&main_loop, 0); 899 // Failed, probably 'shell' is not executable. 900 if (!silent) { 901 msg_puts(_("\nshell failed to start: ")); 902 msg_outtrans(os_strerror(status), 0, false); 903 msg_puts(": "); 904 msg_outtrans(prog, 0, false); 905 msg_putchar('\n'); 906 } 907 goto end; 908 } 909 910 // Note: unlike process events, stream events are not queued, as we want to 911 // deal with stream events as fast a possible. It prevents closing the 912 // streams while there's still data in the OS buffer (due to the process 913 // exiting before all data is read). 914 if (has_input) { 915 wstream_init(&proc->in, 0); 916 } 917 rstream_init(&proc->out); 918 rstream_start(&proc->out, data_cb, &buf); 919 rstream_init(&proc->err); 920 rstream_start(&proc->err, data_cb, &buf); 921 922 // write the input, if any 923 if (has_input) { 924 WBuffer *input_buffer = wstream_new_buffer((char *)input, len, 1, NULL); 925 926 if (wstream_write(&proc->in, input_buffer) != 0) { 927 // couldn't write, stop the process and tell the user about it 928 proc_stop(proc); 929 goto end; 930 } 931 // close the input stream after everything is written 932 wstream_set_write_cb(&proc->in, shell_write_cb, NULL); 933 } 934 935 // Invoke busy_start here so LOOP_PROCESS_EVENTS_UNTIL will not change the 936 // busy state. 937 ui_busy_start(); 938 ui_flush(); 939 if (forward_output) { 940 msg_sb_eol(); 941 msg_start(); 942 msg_no_more = true; 943 lines_left = -1; 944 } 945 exitcode = proc_wait(proc, -1, NULL); 946 if (!got_int && out_data_decide_throttle(0)) { 947 // Last chunk of output was skipped; display it now. 948 out_data_ring(NULL, SIZE_MAX); 949 } 950 if (forward_output) { 951 // caller should decide if wait_return() is invoked 952 no_wait_return++; 953 msg_end(); 954 no_wait_return--; 955 msg_no_more = false; 956 } 957 958 ui_busy_stop(); 959 960 // prepare the out parameters if requested 961 if (output) { 962 assert(nread); 963 if (buf.size == 0) { 964 // no data received from the process, return NULL 965 *output = NULL; 966 *nread = 0; 967 kv_destroy(buf); 968 } else { 969 *nread = buf.size; 970 // NUL-terminate to make the output directly usable as a C string 971 kv_push(buf, NUL); 972 *output = buf.items; 973 } 974 } 975 976 assert(multiqueue_empty(events)); 977 end: 978 multiqueue_free(events); 979 980 #ifdef MSWIN 981 // Restore original value of NoDefaultCurrentDirectoryInExePath 982 restore_env_var("NoDefaultCurrentDirectoryInExePath", oldval, true); 983 #endif 984 985 return exitcode; 986 } 987 988 static size_t system_data_cb(RStream *stream, const char *buf, size_t count, void *data, bool eof) 989 { 990 StringBuilder *dbuf = data; 991 kv_concat_len(*dbuf, buf, count); 992 return count; 993 } 994 995 /// Tracks output received for the current executing shell command, and displays 996 /// a pulsing "..." when output should be skipped. Tracking depends on the 997 /// synchronous/blocking nature of ":!". 998 /// 999 /// Purpose: 1000 /// 1. CTRL-C is more responsive. #1234 #5396 1001 /// 2. Improves performance of :! (UI, esp. TUI, is the bottleneck). 1002 /// 3. Avoids OOM during long-running, spammy :!. 1003 /// 1004 /// Vim does not need this hack because: 1005 /// 1. :! in terminal-Vim runs in cooked mode, so CTRL-C is caught by the 1006 /// terminal and raises SIGINT out-of-band. 1007 /// 2. :! in terminal-Vim uses a tty (Nvim uses pipes), so commands 1008 /// (e.g. `git grep`) may page themselves. 1009 /// 1010 /// @param size Length of data, used with internal state to decide whether 1011 /// output should be skipped. size=0 resets the internal state and 1012 /// returns the previous decision. 1013 /// 1014 /// @returns true if output should be skipped and pulse was displayed. 1015 /// Returns the previous decision if size=0. 1016 static bool out_data_decide_throttle(size_t size) 1017 { 1018 static uint64_t started = 0; // Start time of the current throttle. 1019 static size_t received = 0; // Bytes observed since last throttle. 1020 static size_t visit = 0; // "Pulse" count of the current throttle. 1021 static char pulse_msg[] = { ' ', ' ', ' ', NUL }; 1022 1023 if (!size) { 1024 bool previous_decision = (visit > 0); 1025 started = received = visit = 0; 1026 return previous_decision; 1027 } 1028 1029 received += size; 1030 if (received < OUT_DATA_THRESHOLD 1031 // Display at least the first chunk of output even if it is big. 1032 || (!started && received < size + 1000)) { 1033 return false; 1034 } else if (!visit) { 1035 started = os_hrtime(); 1036 } else { 1037 uint64_t since = os_hrtime() - started; 1038 if (since < (visit * (NS_1_SECOND / 10))) { 1039 return true; 1040 } 1041 if (since > (3 * NS_1_SECOND)) { 1042 received = visit = 0; 1043 return false; 1044 } 1045 } 1046 1047 visit++; 1048 // Pulse "..." at the bottom of the screen. 1049 size_t tick = visit % 4; 1050 pulse_msg[0] = (tick > 0) ? '.' : ' '; 1051 pulse_msg[1] = (tick > 1) ? '.' : ' '; 1052 pulse_msg[2] = (tick > 2) ? '.' : ' '; 1053 if (visit == 1) { 1054 msg_puts("...\n"); 1055 } 1056 msg_putchar('\r'); // put cursor at start of line 1057 msg_puts(pulse_msg); 1058 msg_putchar('\r'); 1059 ui_flush(); 1060 return true; 1061 } 1062 1063 /// Saves output in a quasi-ringbuffer. Used to ensure the last ~page of 1064 /// output for a shell-command is always displayed. 1065 /// 1066 /// Init mode: Resets the internal state. 1067 /// output = NULL 1068 /// size = 0 1069 /// Print mode: Displays the current saved data. 1070 /// output = NULL 1071 /// size = SIZE_MAX 1072 /// 1073 /// @param output Data to save, or NULL to invoke a special mode. 1074 /// @param size Length of `output`. 1075 static void out_data_ring(const char *output, size_t size) 1076 { 1077 #define MAX_CHUNK_SIZE (OUT_DATA_THRESHOLD / 2) 1078 static char last_skipped[MAX_CHUNK_SIZE]; // Saved output. 1079 static size_t last_skipped_len = 0; 1080 1081 assert(output != NULL || (size == 0 || size == SIZE_MAX)); 1082 1083 if (output == NULL && size == 0) { // Init mode 1084 last_skipped_len = 0; 1085 return; 1086 } 1087 1088 if (output == NULL && size == SIZE_MAX) { // Print mode 1089 out_data_append_to_screen(last_skipped, &last_skipped_len, STDOUT_FILENO, true); 1090 return; 1091 } 1092 1093 // This is basically a ring-buffer... 1094 if (size >= MAX_CHUNK_SIZE) { // Save mode 1095 size_t start = size - MAX_CHUNK_SIZE; 1096 memcpy(last_skipped, output + start, MAX_CHUNK_SIZE); 1097 last_skipped_len = MAX_CHUNK_SIZE; 1098 } else if (size > 0) { 1099 // Length of the old data that can be kept. 1100 size_t keep_len = MIN(last_skipped_len, MAX_CHUNK_SIZE - size); 1101 size_t keep_start = last_skipped_len - keep_len; 1102 // Shift the kept part of the old data to the start. 1103 if (keep_start) { 1104 memmove(last_skipped, last_skipped + keep_start, keep_len); 1105 } 1106 // Copy the entire new data to the remaining space. 1107 memcpy(last_skipped + keep_len, output, size); 1108 last_skipped_len = keep_len + size; 1109 } 1110 } 1111 1112 /// Continue to append data to last screen line. 1113 /// 1114 /// @param output Data to append to screen lines. 1115 /// @param count Size of data. 1116 /// @param eof If true, there will be no more data output. 1117 static void out_data_append_to_screen(const char *output, size_t *count, int fd, bool eof) 1118 FUNC_ATTR_NONNULL_ALL 1119 { 1120 const char *p = output; 1121 const char *end = output + *count; 1122 msg_ext_set_kind(fd == STDERR_FILENO ? "shell_err" : "shell_out"); 1123 while (p < end) { 1124 if (*p == '\n' || *p == '\r' || *p == TAB || *p == BELL) { 1125 msg_putchar_hl((uint8_t)(*p), fd == STDERR_FILENO ? HLF_SE : HLF_SO); 1126 p++; 1127 } else { 1128 // Note: this is not 100% precise: 1129 // 1. we don't check if received continuation bytes are already invalid 1130 // and we thus do some buffering that could be avoided 1131 // 2. we don't compose chars over buffer boundaries, even if we see an 1132 // incomplete UTF-8 sequence that could be composing with the last 1133 // complete sequence. 1134 // This will be corrected when we switch to vterm based implementation 1135 int i = *p ? utfc_ptr2len_len(p, (int)(end - p)) : 1; 1136 if (!eof && i == 1 && utf8len_tab_zero[*(uint8_t *)p] > (end - p)) { 1137 *count = (size_t)(p - output); 1138 goto end; 1139 } 1140 1141 msg_outtrans_len(p, i, fd == STDERR_FILENO ? HLF_SE : HLF_SO, false); 1142 p += i; 1143 } 1144 } 1145 1146 end: 1147 ui_flush(); 1148 } 1149 1150 static size_t out_data_cb(RStream *stream, const char *ptr, size_t count, void *data, bool eof) 1151 { 1152 if (count > 0 && out_data_decide_throttle(count)) { // Skip output above a threshold. 1153 // Save the skipped output. If it is the final chunk, we display it later. 1154 out_data_ring(ptr, count); 1155 } else if (count > 0) { 1156 out_data_append_to_screen(ptr, &count, stream->s.fd, eof); 1157 } 1158 1159 return count; 1160 } 1161 1162 /// Parses a command string into a sequence of words, taking quotes into 1163 /// consideration. 1164 /// 1165 /// @param str The command string to be parsed 1166 /// @param argv The vector that will be filled with copies of the parsed 1167 /// words. It can be NULL if the caller only needs to count words. 1168 /// @return The number of words parsed. 1169 static size_t tokenize(const char *const str, char **const argv) 1170 FUNC_ATTR_NONNULL_ARG(1) 1171 { 1172 size_t argc = 0; 1173 const char *p = str; 1174 1175 while (*p != NUL) { 1176 const size_t len = word_length(p); 1177 1178 if (argv != NULL) { 1179 // Fill the slot 1180 argv[argc] = vim_strnsave_unquoted(p, len); 1181 } 1182 1183 argc++; 1184 p = skipwhite((p + len)); 1185 } 1186 1187 return argc; 1188 } 1189 1190 /// Calculates the length of a shell word. 1191 /// 1192 /// @param str A pointer to the first character of the word 1193 /// @return The offset from `str` at which the word ends. 1194 static size_t word_length(const char *str) 1195 { 1196 const char *p = str; 1197 bool inquote = false; 1198 size_t length = 0; 1199 1200 // Move `p` to the end of shell word by advancing the pointer while it's 1201 // inside a quote or it's a non-whitespace character 1202 while (*p && (inquote || (*p != ' ' && *p != TAB))) { 1203 if (*p == '"') { 1204 // Found a quote character, switch the `inquote` flag 1205 inquote = !inquote; 1206 } else if (*p == '\\' && inquote) { 1207 p++; 1208 length++; 1209 } 1210 1211 p++; 1212 length++; 1213 } 1214 1215 return length; 1216 } 1217 1218 /// To remain compatible with the old implementation (which forked a process 1219 /// for writing) the entire text is copied to a temporary buffer before the 1220 /// event loop starts. If we don't (by writing in chunks returned by `ml_get`) 1221 /// the buffer being modified might get modified by reading from the process 1222 /// before we finish writing. 1223 static void read_input(StringBuilder *buf) 1224 { 1225 read_buffer_into(curbuf, curbuf->b_op_start.lnum, curbuf->b_op_end.lnum, buf); 1226 } 1227 1228 static size_t write_output(char *output, size_t remaining, bool eof) 1229 { 1230 if (!output) { 1231 return 0; 1232 } 1233 1234 char *start = output; 1235 size_t off = 0; 1236 while (off < remaining) { 1237 // CRLF 1238 if (output[off] == CAR && output[off + 1] == NL) { 1239 output[off] = NUL; 1240 ml_append(curwin->w_cursor.lnum++, output, (int)off + 1, false); 1241 size_t skip = off + 2; 1242 output += skip; 1243 remaining -= skip; 1244 off = 0; 1245 continue; 1246 } else if (output[off] == CAR || output[off] == NL) { 1247 // Insert the line 1248 output[off] = NUL; 1249 ml_append(curwin->w_cursor.lnum++, output, (int)off + 1, false); 1250 size_t skip = off + 1; 1251 output += skip; 1252 remaining -= skip; 1253 off = 0; 1254 continue; 1255 } 1256 1257 if (output[off] == NUL) { 1258 // Translate NUL to NL 1259 output[off] = NL; 1260 } 1261 off++; 1262 } 1263 1264 if (eof) { 1265 if (remaining) { 1266 // append unfinished line 1267 ml_append(curwin->w_cursor.lnum++, output, 0, false); 1268 // remember that the line ending was missing 1269 curbuf->b_no_eol_lnum = curwin->w_cursor.lnum; 1270 output += remaining; 1271 } else { 1272 curbuf->b_no_eol_lnum = 0; 1273 } 1274 } 1275 1276 ui_flush(); 1277 1278 return (size_t)(output - start); 1279 } 1280 1281 static void shell_write_cb(Stream *stream, void *data, int status) 1282 { 1283 if (status) { 1284 // Can happen if system() tries to send input to a shell command that was 1285 // backgrounded (:call system("cat - &", "foo")). #3529 #5241 1286 msg_schedule_semsg(_("E5677: Error writing input to shell-command: %s"), 1287 uv_err_name(status)); 1288 } 1289 stream_may_close(stream); 1290 } 1291 1292 /// Applies 'shellxescape' (p_sxe) and 'shellxquote' (p_sxq) to a command. 1293 /// 1294 /// @param cmd Command string 1295 /// @return Escaped/quoted command string (allocated). 1296 static char *shell_xescape_xquote(const char *cmd) 1297 FUNC_ATTR_NONNULL_ALL FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT 1298 { 1299 if (*p_sxq == NUL) { 1300 return xstrdup(cmd); 1301 } 1302 1303 const char *ecmd = cmd; 1304 if (*p_sxe != NUL && strcmp(p_sxq, "(") == 0) { 1305 ecmd = vim_strsave_escaped_ext(cmd, p_sxe, '^', false); 1306 } 1307 size_t ncmd_size = strlen(ecmd) + strlen(p_sxq) * 2 + 1; 1308 char *ncmd = xmalloc(ncmd_size); 1309 1310 // When 'shellxquote' is ( append ). 1311 // When 'shellxquote' is "( append )". 1312 if (strcmp(p_sxq, "(") == 0) { 1313 vim_snprintf(ncmd, ncmd_size, "(%s)", ecmd); 1314 } else if (strcmp(p_sxq, "\"(") == 0) { 1315 vim_snprintf(ncmd, ncmd_size, "\"(%s)\"", ecmd); 1316 } else { 1317 vim_snprintf(ncmd, ncmd_size, "%s%s%s", p_sxq, ecmd, p_sxq); 1318 } 1319 1320 if (ecmd != cmd) { 1321 xfree((void *)ecmd); 1322 } 1323 1324 return ncmd; 1325 }