comparison src/os_win32.c @ 2935:bf283e37792b v7.3.240

updated for version 7.3.240 Problem: External commands can't use pipes on MS-Windows. Solution: Implement pipes and use them when 'shelltemp' isn't set. (Vincent Berthoux)
author Bram Moolenaar <bram@vim.org>
date Thu, 07 Jul 2011 16:20:52 +0200
parents ce1dce2af2a3
children e5b17a5f6516
comparison
equal deleted inserted replaced
2934:ba9df996e47c 2935:bf283e37792b
415 static HANDLE advapi_lib = NULL; /* Handle for ADVAPI library */ 415 static HANDLE advapi_lib = NULL; /* Handle for ADVAPI library */
416 static PSNSECINFO pSetNamedSecurityInfo; 416 static PSNSECINFO pSetNamedSecurityInfo;
417 static PGNSECINFO pGetNamedSecurityInfo; 417 static PGNSECINFO pGetNamedSecurityInfo;
418 #endif 418 #endif
419 419
420 typedef BOOL (WINAPI *PSETHANDLEINFORMATION)(HANDLE, DWORD, DWORD);
421
422 static BOOL allowPiping = FALSE;
423 static PSETHANDLEINFORMATION pSetHandleInformation;
424
420 /* 425 /*
421 * Set g_PlatformId to VER_PLATFORM_WIN32_NT (NT) or 426 * Set g_PlatformId to VER_PLATFORM_WIN32_NT (NT) or
422 * VER_PLATFORM_WIN32_WINDOWS (Win95). 427 * VER_PLATFORM_WIN32_WINDOWS (Win95).
423 */ 428 */
424 void 429 void
465 advapi_lib = NULL; 470 advapi_lib = NULL;
466 } 471 }
467 } 472 }
468 } 473 }
469 #endif 474 #endif
475 /*
476 * If we are on windows NT, try to load the pipe functions, only
477 * available from Win2K.
478 */
479 if (g_PlatformId == VER_PLATFORM_WIN32_NT)
480 {
481 HANDLE kernel32 = GetModuleHandle("kernel32");
482 pSetHandleInformation = (PSETHANDLEINFORMATION)GetProcAddress(
483 kernel32, "SetHandleInformation");
484
485 allowPiping = pSetHandleInformation != NULL;
486 }
470 done = TRUE; 487 done = TRUE;
471 } 488 }
472 } 489 }
473 490
474 /* 491 /*
1633 return FALSE; 1650 return FALSE;
1634 return TRUE; 1651 return TRUE;
1635 } 1652 }
1636 1653
1637 #if ((defined(__MINGW32__) || defined (__CYGWIN32__)) && \ 1654 #if ((defined(__MINGW32__) || defined (__CYGWIN32__)) && \
1638 __MSVCRT_VERSION__ >= 0x800) || (defined(_MSC_VER) && _MSC_VER >= 1400) 1655 __MSVCRT_VERSION__ >= 0x800) || (defined(_MSC_VER) && _MSC_VER >= 1400)
1639 /* 1656 /*
1640 * Bad parameter handler. 1657 * Bad parameter handler.
1641 * 1658 *
1642 * Certain MS CRT functions will intentionally crash when passed invalid 1659 * Certain MS CRT functions will intentionally crash when passed invalid
1643 * parameters to highlight possible security holes. Setting this function as 1660 * parameters to highlight possible security holes. Setting this function as
3208 * 2. Run the subprocess (it gets the allocated console by default) 3225 * 2. Run the subprocess (it gets the allocated console by default)
3209 * 3. Wait for the subprocess to terminate and get its exit code 3226 * 3. Wait for the subprocess to terminate and get its exit code
3210 * 4. Prompt the user to press a key to close the console window 3227 * 4. Prompt the user to press a key to close the console window
3211 */ 3228 */
3212 static int 3229 static int
3213 mch_system(char *cmd, int options) 3230 mch_system_classic(char *cmd, int options)
3214 { 3231 {
3215 STARTUPINFO si; 3232 STARTUPINFO si;
3216 PROCESS_INFORMATION pi; 3233 PROCESS_INFORMATION pi;
3217 DWORD ret = 0; 3234 DWORD ret = 0;
3218 HWND hwnd = GetFocus(); 3235 HWND hwnd = GetFocus();
3313 /* Try to get input focus back. Doesn't always work though. */ 3330 /* Try to get input focus back. Doesn't always work though. */
3314 PostMessage(hwnd, WM_SETFOCUS, 0, 0); 3331 PostMessage(hwnd, WM_SETFOCUS, 0, 0);
3315 3332
3316 return ret; 3333 return ret;
3317 } 3334 }
3335
3336 /*
3337 * Thread launched by the gui to send the current buffer data to the
3338 * process. This way avoid to hang up vim totally if the children
3339 * process take a long time to process the lines.
3340 */
3341 static DWORD WINAPI
3342 sub_process_writer(LPVOID param)
3343 {
3344 HANDLE g_hChildStd_IN_Wr = param;
3345 linenr_T lnum = curbuf->b_op_start.lnum;
3346 DWORD len = 0;
3347 DWORD l;
3348 char_u *lp = ml_get(lnum);
3349 char_u *s;
3350 int written = 0;
3351
3352 for (;;)
3353 {
3354 l = (DWORD)STRLEN(lp + written);
3355 if (l == 0)
3356 len = 0;
3357 else if (lp[written] == NL)
3358 {
3359 /* NL -> NUL translation */
3360 WriteFile(g_hChildStd_IN_Wr, "", 1, &len, NULL);
3361 }
3362 else
3363 {
3364 s = vim_strchr(lp + written, NL);
3365 WriteFile(g_hChildStd_IN_Wr, (char *)lp + written,
3366 s == NULL ? l : (DWORD)(s - (lp + written)),
3367 &len, NULL);
3368 }
3369 if (len == (int)l)
3370 {
3371 /* Finished a line, add a NL, unless this line should not have
3372 * one. */
3373 if (lnum != curbuf->b_op_end.lnum
3374 || !curbuf->b_p_bin
3375 || (lnum != curbuf->b_no_eol_lnum
3376 && (lnum != curbuf->b_ml.ml_line_count
3377 || curbuf->b_p_eol)))
3378 {
3379 WriteFile(g_hChildStd_IN_Wr, "\n", 1, &ignored, NULL);
3380 }
3381
3382 ++lnum;
3383 if (lnum > curbuf->b_op_end.lnum)
3384 break;
3385
3386 lp = ml_get(lnum);
3387 written = 0;
3388 }
3389 else if (len > 0)
3390 written += len;
3391 }
3392
3393 /* finished all the lines, close pipe */
3394 CloseHandle(g_hChildStd_IN_Wr);
3395 ExitThread(0);
3396 }
3397
3398
3399 # define BUFLEN 100 /* length for buffer, stolen from unix version */
3400
3401 /*
3402 * This function read from the children's stdout and write the
3403 * data on screen or in the buffer accordingly.
3404 */
3405 static void
3406 dump_pipe(int options,
3407 HANDLE g_hChildStd_OUT_Rd,
3408 garray_T *ga,
3409 char_u buffer[],
3410 DWORD *buffer_off)
3411 {
3412 DWORD availableBytes = 0;
3413 DWORD i;
3414 int c;
3415 char_u *p;
3416 int ret;
3417 DWORD len;
3418 DWORD toRead;
3419 int repeatCount;
3420
3421 /* we query the pipe to see if there is any data to read
3422 * to avoid to perform a blocking read */
3423 ret = PeekNamedPipe(g_hChildStd_OUT_Rd, /* pipe to query */
3424 NULL, /* optional buffer */
3425 0, /* buffe size */
3426 NULL, /* number of read bytes */
3427 &availableBytes, /* available bytes total */
3428 NULL); /* byteLeft */
3429
3430 repeatCount = 0;
3431 /* We got real data in the pipe, read it */
3432 while (ret != 0 && availableBytes > 0 && availableBytes > 0)
3433 {
3434 repeatCount++;
3435 toRead =
3436 # ifdef FEAT_MBYTE
3437 (DWORD)(BUFLEN - *buffer_off);
3438 # else
3439 (DWORD)BUFLEN;
3440 # endif
3441 toRead = availableBytes < toRead ? availableBytes : toRead;
3442 ReadFile(g_hChildStd_OUT_Rd, buffer
3443 # ifdef FEAT_MBYTE
3444 + *buffer_off, toRead
3445 # else
3446 , toRead
3447 # endif
3448 , &len, NULL);
3449
3450 /* If we haven't read anything, there is a problem */
3451 if (len == 0)
3452 break;
3453
3454 availableBytes -= len;
3455
3456 if (options & SHELL_READ)
3457 {
3458 /* Do NUL -> NL translation, append NL separated
3459 * lines to the current buffer. */
3460 for (i = 0; i < len; ++i)
3461 {
3462 if (buffer[i] == NL)
3463 append_ga_line(ga);
3464 else if (buffer[i] == NUL)
3465 ga_append(ga, NL);
3466 else
3467 ga_append(ga, buffer[i]);
3468 }
3469 }
3470 # ifdef FEAT_MBYTE
3471 else if (has_mbyte)
3472 {
3473 int l;
3474
3475 len += *buffer_off;
3476 buffer[len] = NUL;
3477
3478 /* Check if the last character in buffer[] is
3479 * incomplete, keep these bytes for the next
3480 * round. */
3481 for (p = buffer; p < buffer + len; p += l)
3482 {
3483 l = mb_cptr2len(p);
3484 if (l == 0)
3485 l = 1; /* NUL byte? */
3486 else if (MB_BYTE2LEN(*p) != l)
3487 break;
3488 }
3489 if (p == buffer) /* no complete character */
3490 {
3491 /* avoid getting stuck at an illegal byte */
3492 if (len >= 12)
3493 ++p;
3494 else
3495 {
3496 *buffer_off = len;
3497 return;
3498 }
3499 }
3500 c = *p;
3501 *p = NUL;
3502 msg_puts(buffer);
3503 if (p < buffer + len)
3504 {
3505 *p = c;
3506 *buffer_off = (DWORD)((buffer + len) - p);
3507 mch_memmove(buffer, p, *buffer_off);
3508 return;
3509 }
3510 *buffer_off = 0;
3511 }
3512 # endif /* FEAT_MBYTE */
3513 else
3514 {
3515 buffer[len] = NUL;
3516 msg_puts(buffer);
3517 }
3518
3519 windgoto(msg_row, msg_col);
3520 cursor_on();
3521 out_flush();
3522 }
3523 }
3524
3525 /*
3526 * Version of system to use for windows NT > 5.0 (Win2K), use pipe
3527 * for communication and doesn't open any new window.
3528 */
3529 static int
3530 mch_system_piped(char *cmd, int options)
3531 {
3532 STARTUPINFO si;
3533 PROCESS_INFORMATION pi;
3534 DWORD ret = 0;
3535
3536 HANDLE g_hChildStd_IN_Rd = NULL;
3537 HANDLE g_hChildStd_IN_Wr = NULL;
3538 HANDLE g_hChildStd_OUT_Rd = NULL;
3539 HANDLE g_hChildStd_OUT_Wr = NULL;
3540
3541 char_u buffer[BUFLEN + 1]; /* reading buffer + size */
3542 DWORD len;
3543
3544 /* buffer used to receive keys */
3545 char_u ta_buf[BUFLEN + 1]; /* TypeAHead */
3546 int ta_len = 0; /* valid bytes in ta_buf[] */
3547
3548 DWORD i;
3549 int c;
3550 int noread_cnt = 0;
3551 garray_T ga;
3552 int delay = 1;
3553 # ifdef FEAT_MBYTE
3554 DWORD buffer_off = 0; /* valid bytes in buffer[] */
3555 # endif
3556
3557 SECURITY_ATTRIBUTES saAttr;
3558
3559 /* Set the bInheritHandle flag so pipe handles are inherited. */
3560 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
3561 saAttr.bInheritHandle = TRUE;
3562 saAttr.lpSecurityDescriptor = NULL;
3563
3564 if ( ! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0)
3565 /* Ensure the read handle to the pipe for STDOUT is not inherited. */
3566 || ! pSetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)
3567 /* Create a pipe for the child process's STDIN. */
3568 || ! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)
3569 /* Ensure the write handle to the pipe for STDIN is not inherited. */
3570 || ! pSetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) )
3571 {
3572 CloseHandle(g_hChildStd_IN_Rd);
3573 CloseHandle(g_hChildStd_IN_Wr);
3574 CloseHandle(g_hChildStd_OUT_Rd);
3575 CloseHandle(g_hChildStd_OUT_Wr);
3576 MSG_PUTS(_("\nCannot create pipes\n"));
3577 }
3578
3579 si.cb = sizeof(si);
3580 si.lpReserved = NULL;
3581 si.lpDesktop = NULL;
3582 si.lpTitle = NULL;
3583 si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
3584
3585 /* set-up our file redirection */
3586 si.hStdError = g_hChildStd_OUT_Wr;
3587 si.hStdOutput = g_hChildStd_OUT_Wr;
3588 si.hStdInput = g_hChildStd_IN_Rd;
3589 si.wShowWindow = SW_HIDE;
3590 si.cbReserved2 = 0;
3591 si.lpReserved2 = NULL;
3592
3593 if (options & SHELL_READ)
3594 ga_init2(&ga, 1, BUFLEN);
3595
3596 /* Now, run the command */
3597 CreateProcess(NULL, /* Executable name */
3598 cmd, /* Command to execute */
3599 NULL, /* Process security attributes */
3600 NULL, /* Thread security attributes */
3601
3602 // this command can be litigeous, handle inheritence was
3603 // deactivated for pending temp file, but, if we deactivate
3604 // it, the pipes don't work for some reason.
3605 TRUE, /* Inherit handles, first deactivated,
3606 * but needed */
3607 CREATE_DEFAULT_ERROR_MODE, /* Creation flags */
3608 NULL, /* Environment */
3609 NULL, /* Current directory */
3610 &si, /* Startup information */
3611 &pi); /* Process information */
3612
3613
3614 /* Close our unused side of the pipes */
3615 CloseHandle(g_hChildStd_IN_Rd);
3616 CloseHandle(g_hChildStd_OUT_Wr);
3617
3618 if (options & SHELL_WRITE)
3619 {
3620 HANDLE thread =
3621 CreateThread(NULL, /* security attributes */
3622 0, /* default stack size */
3623 sub_process_writer, /* function to be executed */
3624 g_hChildStd_IN_Wr, /* parameter */
3625 0, /* creation flag, start immediately */
3626 NULL); /* we don't care about thread id */
3627 CloseHandle(thread);
3628 g_hChildStd_IN_Wr = NULL;
3629 }
3630
3631 /* Keep updating the window while waiting for the shell to finish. */
3632 for (;;)
3633 {
3634 MSG msg;
3635
3636 if (PeekMessage(&msg, (HWND)NULL, 0, 0, PM_REMOVE))
3637 {
3638 TranslateMessage(&msg);
3639 DispatchMessage(&msg);
3640 }
3641
3642 /* write pipe information in the window */
3643 if ((options & (SHELL_READ|SHELL_WRITE))
3644 # ifdef FEAT_GUI
3645 || gui.in_use
3646 # endif
3647 )
3648 {
3649 len = 0;
3650 if (!(options & SHELL_EXPAND)
3651 && ((options &
3652 (SHELL_READ|SHELL_WRITE|SHELL_COOKED))
3653 != (SHELL_READ|SHELL_WRITE|SHELL_COOKED)
3654 # ifdef FEAT_GUI
3655 || gui.in_use
3656 # endif
3657 )
3658 && (ta_len > 0 || noread_cnt > 4))
3659 {
3660 if (ta_len == 0)
3661 {
3662 /* Get extra characters when we don't have any. Reset the
3663 * counter and timer. */
3664 noread_cnt = 0;
3665 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
3666 gettimeofday(&start_tv, NULL);
3667 # endif
3668 len = ui_inchar(ta_buf, BUFLEN, 10L, 0);
3669 }
3670 if (ta_len > 0 || len > 0)
3671 {
3672 /*
3673 * For pipes: Check for CTRL-C: send interrupt signal to
3674 * child. Check for CTRL-D: EOF, close pipe to child.
3675 */
3676 if (len == 1 && cmd != NULL)
3677 {
3678 if (ta_buf[ta_len] == Ctrl_C)
3679 {
3680 /* Learn what exit code is expected, for
3681 * now put 9 as SIGKILL */
3682 TerminateProcess(pi.hProcess, 9);
3683 }
3684 if (ta_buf[ta_len] == Ctrl_D)
3685 {
3686 CloseHandle(g_hChildStd_IN_Wr);
3687 g_hChildStd_IN_Wr = NULL;
3688 }
3689 }
3690
3691 /* replace K_BS by <BS> and K_DEL by <DEL> */
3692 for (i = ta_len; i < ta_len + len; ++i)
3693 {
3694 if (ta_buf[i] == CSI && len - i > 2)
3695 {
3696 c = TERMCAP2KEY(ta_buf[i + 1], ta_buf[i + 2]);
3697 if (c == K_DEL || c == K_KDEL || c == K_BS)
3698 {
3699 mch_memmove(ta_buf + i + 1, ta_buf + i + 3,
3700 (size_t)(len - i - 2));
3701 if (c == K_DEL || c == K_KDEL)
3702 ta_buf[i] = DEL;
3703 else
3704 ta_buf[i] = Ctrl_H;
3705 len -= 2;
3706 }
3707 }
3708 else if (ta_buf[i] == '\r')
3709 ta_buf[i] = '\n';
3710 # ifdef FEAT_MBYTE
3711 if (has_mbyte)
3712 i += (*mb_ptr2len_len)(ta_buf + i,
3713 ta_len + len - i) - 1;
3714 # endif
3715 }
3716
3717 /*
3718 * For pipes: echo the typed characters. For a pty this
3719 * does not seem to work.
3720 */
3721 for (i = ta_len; i < ta_len + len; ++i)
3722 {
3723 if (ta_buf[i] == '\n' || ta_buf[i] == '\b')
3724 msg_putchar(ta_buf[i]);
3725 # ifdef FEAT_MBYTE
3726 else if (has_mbyte)
3727 {
3728 int l = (*mb_ptr2len)(ta_buf + i);
3729
3730 msg_outtrans_len(ta_buf + i, l);
3731 i += l - 1;
3732 }
3733 # endif
3734 else
3735 msg_outtrans_len(ta_buf + i, 1);
3736 }
3737 windgoto(msg_row, msg_col);
3738 out_flush();
3739
3740 ta_len += len;
3741
3742 /*
3743 * Write the characters to the child, unless EOF has been
3744 * typed for pipes. Write one character at a time, to
3745 * avoid losing too much typeahead. When writing buffer
3746 * lines, drop the typed characters (only check for
3747 * CTRL-C).
3748 */
3749 if (options & SHELL_WRITE)
3750 ta_len = 0;
3751 else if (g_hChildStd_IN_Wr != NULL)
3752 {
3753 WriteFile(g_hChildStd_IN_Wr, (char*)ta_buf,
3754 1, &len, NULL);
3755 // if we are typing in, we want to keep things reactive
3756 delay = 1;
3757 if (len > 0)
3758 {
3759 ta_len -= len;
3760 mch_memmove(ta_buf, ta_buf + len, ta_len);
3761 }
3762 }
3763 }
3764 }
3765 }
3766
3767 if (ta_len)
3768 ui_inchar_undo(ta_buf, ta_len);
3769
3770 if (WaitForSingleObject(pi.hProcess, delay) != WAIT_TIMEOUT)
3771 {
3772 dump_pipe(options, g_hChildStd_OUT_Rd,
3773 &ga, buffer, &buffer_off);
3774 break;
3775 }
3776
3777 ++noread_cnt;
3778 dump_pipe(options, g_hChildStd_OUT_Rd,
3779 &ga, buffer, &buffer_off);
3780
3781 /* We start waiting for a very short time and then increase it, so
3782 * that we respond quickly when the process is quick, and don't
3783 * consume too much overhead when it's slow. */
3784 if (delay < 50)
3785 delay += 10;
3786 }
3787
3788 /* Close the pipe */
3789 CloseHandle(g_hChildStd_OUT_Rd);
3790 if (g_hChildStd_IN_Wr != NULL)
3791 CloseHandle(g_hChildStd_IN_Wr);
3792
3793 WaitForSingleObject(pi.hProcess, INFINITE);
3794
3795 /* Get the command exit code */
3796 GetExitCodeProcess(pi.hProcess, &ret);
3797
3798 if (options & SHELL_READ)
3799 {
3800 if (ga.ga_len > 0)
3801 {
3802 append_ga_line(&ga);
3803 /* remember that the NL was missing */
3804 curbuf->b_no_eol_lnum = curwin->w_cursor.lnum;
3805 }
3806 else
3807 curbuf->b_no_eol_lnum = 0;
3808 ga_clear(&ga);
3809 }
3810
3811 /* Close the handles to the subprocess, so that it goes away */
3812 CloseHandle(pi.hThread);
3813 CloseHandle(pi.hProcess);
3814
3815 return ret;
3816 }
3817
3818 static int
3819 mch_system(char *cmd, int options)
3820 {
3821 /* if we can pipe and the shelltemp option is off */
3822 if (allowPiping && !p_stmp)
3823 return mch_system_piped(cmd, options);
3824 else
3825 return mch_system_classic(cmd, options);
3826 }
3318 #else 3827 #else
3319 3828
3320 # define mch_system(c, o) system(c) 3829 # define mch_system(c, o) system(c)
3321 3830
3322 #endif 3831 #endif
3386 { 3895 {
3387 /* we use "command" or "cmd" to start the shell; slow but easy */ 3896 /* we use "command" or "cmd" to start the shell; slow but easy */
3388 char_u *newcmd; 3897 char_u *newcmd;
3389 long_u cmdlen = ( 3898 long_u cmdlen = (
3390 #ifdef FEAT_GUI_W32 3899 #ifdef FEAT_GUI_W32
3391 STRLEN(vimrun_path) + 3900 (allowPiping && !p_stmp ? 0 : STRLEN(vimrun_path)) +
3392 #endif 3901 #endif
3393 STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10); 3902 STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10);
3394 3903
3395 newcmd = lalloc(cmdlen, TRUE); 3904 newcmd = lalloc(cmdlen, TRUE);
3396 if (newcmd != NULL) 3905 if (newcmd != NULL)
3495 "See :help win32-vimrun for more information."), 4004 "See :help win32-vimrun for more information."),
3496 _("Vim Warning"), 4005 _("Vim Warning"),
3497 MB_ICONWARNING); 4006 MB_ICONWARNING);
3498 need_vimrun_warning = FALSE; 4007 need_vimrun_warning = FALSE;
3499 } 4008 }
3500 if (!s_dont_use_vimrun) 4009 if (!s_dont_use_vimrun && (!allowPiping || p_stmp))
3501 /* Use vimrun to execute the command. It opens a console 4010 /* Use vimrun to execute the command. It opens a console
3502 * window, which can be closed without killing Vim. */ 4011 * window, which can be closed without killing Vim. */
3503 vim_snprintf((char *)newcmd, cmdlen, "%s%s%s %s %s", 4012 vim_snprintf((char *)newcmd, cmdlen, "%s%s%s %s %s",
3504 vimrun_path, 4013 vimrun_path,
3505 (msg_silent != 0 || (options & SHELL_DOOUT)) 4014 (msg_silent != 0 || (options & SHELL_DOOUT))
3519 settmode(TMODE_RAW); /* set to raw mode */ 4028 settmode(TMODE_RAW); /* set to raw mode */
3520 4029
3521 /* Print the return value, unless "vimrun" was used. */ 4030 /* Print the return value, unless "vimrun" was used. */
3522 if (x != 0 && !(options & SHELL_SILENT) && !emsg_silent 4031 if (x != 0 && !(options & SHELL_SILENT) && !emsg_silent
3523 #if defined(FEAT_GUI_W32) 4032 #if defined(FEAT_GUI_W32)
3524 && ((options & SHELL_DOOUT) || s_dont_use_vimrun) 4033 && ((options & SHELL_DOOUT) || s_dont_use_vimrun
4034 || (allowPiping && !p_stmp))
3525 #endif 4035 #endif
3526 ) 4036 )
3527 { 4037 {
3528 smsg(_("shell returned %d"), x); 4038 smsg(_("shell returned %d"), x);
3529 msg_putchar('\n'); 4039 msg_putchar('\n');