Add wildcard support for scp (#283)

1. Expand wildcard for input parameters
2.  add scp tests with wildcard
3. for debug mode, need to enable the log to local log file.
4. update the path to log file
This commit is contained in:
Yanbing 2018-03-11 23:28:52 -07:00 committed by GitHub
parent 9fe39c0c73
commit fb1342f7e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 113 additions and 50 deletions

View File

@ -37,7 +37,7 @@ function Set-OpenSSHTestEnvironment
( (
[string] $OpenSSHBinPath, [string] $OpenSSHBinPath,
[string] $TestDataPath = "$env:SystemDrive\OpenSSHTests", [string] $TestDataPath = "$env:SystemDrive\OpenSSHTests",
[Boolean] $DebugMode = $false, [Switch] $DebugMode,
[Switch] $NoAppVerifier, [Switch] $NoAppVerifier,
[Switch] $PostmortemDebugging, [Switch] $PostmortemDebugging,
[Switch] $NoLibreSSL [Switch] $NoLibreSSL
@ -78,7 +78,7 @@ function Set-OpenSSHTestEnvironment
"UnitTestResultsFile" = $Script:UnitTestResultsFile; # openssh unittest test results file "UnitTestResultsFile" = $Script:UnitTestResultsFile; # openssh unittest test results file
"E2ETestDirectory" = $Script:E2ETestDirectory # the directory of E2E tests "E2ETestDirectory" = $Script:E2ETestDirectory # the directory of E2E tests
"UnitTestDirectory" = $Script:UnitTestDirectory # the directory of unit tests "UnitTestDirectory" = $Script:UnitTestDirectory # the directory of unit tests
"DebugMode" = $DebugMode # run openssh E2E in debug mode "DebugMode" = $DebugMode.IsPresent # run openssh E2E in debug mode
"EnableAppVerifier" = $Script:EnableAppVerifier "EnableAppVerifier" = $Script:EnableAppVerifier
"PostmortemDebugging" = $Script:PostmortemDebugging "PostmortemDebugging" = $Script:PostmortemDebugging
"NoLibreSSL" = $Script:NoLibreSSL "NoLibreSSL" = $Script:NoLibreSSL
@ -173,6 +173,10 @@ WARNING: Following changes will be made to OpenSSH configuration
$targetsshdConfig = Join-Path $OpenSSHConfigPath sshd_config $targetsshdConfig = Join-Path $OpenSSHConfigPath sshd_config
# copy new sshd_config # copy new sshd_config
Copy-Item (Join-Path $Script:E2ETestDirectory sshd_config) $targetsshdConfig -Force Copy-Item (Join-Path $Script:E2ETestDirectory sshd_config) $targetsshdConfig -Force
if($DebugMode) {
$con = (Get-Content $targetsshdConfig | Out-String).Replace("#SyslogFacility AUTH","SyslogFacility LOCAL0")
Set-Content -Path $targetsshdConfig -Value "$con" -Force
}
Start-Service ssh-agent Start-Service ssh-agent

View File

@ -2,7 +2,7 @@
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
$tC = 1 $tC = 1
$tI = 0 $tI = 0
$suite = "authorized_keys_fileperm" $suite = "Cfginclude"
Describe "Tests for ssh config" -Tags "CI" { Describe "Tests for ssh config" -Tags "CI" {
BeforeAll { BeforeAll {
if($OpenSSHTestInfo -eq $null) if($OpenSSHTestInfo -eq $null)
@ -28,8 +28,8 @@ Describe "Tests for ssh config" -Tags "CI" {
# for the first time, delete the existing log files. # for the first time, delete the existing log files.
if ($OpenSSHTestInfo['DebugMode']) if ($OpenSSHTestInfo['DebugMode'])
{ {
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue Clear-Content "$env:ProgramData\ssh\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue Clear-Content "$env:ProgramData\ssh\logs\sshd.log" -Force -ErrorAction SilentlyContinue
Remove-Item -Path (Join-Path $testDir "*log*.log") -Force -ErrorAction SilentlyContinue Remove-Item -Path (Join-Path $testDir "*log*.log") -Force -ErrorAction SilentlyContinue
} }
@ -39,12 +39,12 @@ Describe "Tests for ssh config" -Tags "CI" {
AfterEach { AfterEach {
if( $OpenSSHTestInfo["DebugMode"]) if( $OpenSSHTestInfo["DebugMode"])
{ {
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" "$testDir\agentlog$tC.$tI.log" -Force -ErrorAction SilentlyContinue Copy-Item "$env:ProgramData\ssh\logs\ssh-agent.log" "$testDir\agentlog$tC.$tI.log" -Force -ErrorAction SilentlyContinue
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" "$testDir\sshdlog$tC.$tI.log" -Force -ErrorAction SilentlyContinue Copy-Item "$env:ProgramData\ssh\logs\sshd.log" "$testDir\sshdlog$tC.$tI.log" -Force -ErrorAction SilentlyContinue
#Clear the ssh-agent, sshd logs so that next testcase will get fresh logs. #Clear the ssh-agent, sshd logs so that next testcase will get fresh logs.
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue Clear-Content "$env:ProgramData\ssh\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue Clear-Content "$env:ProgramData\ssh\logs\sshd.log" -Force -ErrorAction SilentlyContinue
} }
$tI++ $tI++
} }

View File

@ -2,6 +2,8 @@
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
#covered -i -p -q -r -v -c -S -C #covered -i -p -q -r -v -c -S -C
#todo: -F, -l and -P should be tested over the network #todo: -F, -l and -P should be tested over the network
$tI = 0
$suite = "SCP"
Describe "Tests for scp command" -Tags "CI" { Describe "Tests for scp command" -Tags "CI" {
BeforeAll { BeforeAll {
if($OpenSSHTestInfo -eq $null) if($OpenSSHTestInfo -eq $null)
@ -9,12 +11,19 @@ Describe "Tests for scp command" -Tags "CI" {
Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments." Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments."
} }
$testDir = "$($OpenSSHTestInfo["TestDataPath"])\$suite"
$fileName1 = "test.txt" $fileName1 = "test.txt"
$fileName2 = "test2.txt" $fileName2 = "test2.txt"
$fileName3 = "test3.txt"
$wildcardFileName1 = "te?t.txt"
$wildcardFileName2 = "test*"
$SourceDirName = "SourceDir" $SourceDirName = "SourceDir"
$SourceDir = Join-Path "$($OpenSSHTestInfo["TestDataPath"])\SCP" $SourceDirName $SourceDir = Join-Path $testDir $SourceDirName
$SourceFilePath = Join-Path $SourceDir $fileName1 $SourceFilePath = Join-Path $SourceDir $fileName1
$SourceFilePath3 = Join-Path $SourceDir $fileName3
$SourceFileWildCardFile1 = Join-Path $SourceDir $wildcardFileName1
$DestinationDir = Join-Path "$($OpenSSHTestInfo["TestDataPath"])\SCP" "DestDir" $DestinationDir = Join-Path "$($OpenSSHTestInfo["TestDataPath"])\SCP" "DestDir"
$DestinationDirWildcardPath = Join-Path "$($OpenSSHTestInfo["TestDataPath"])\SCP" "DestD?r"
$DestinationFilePath = Join-Path $DestinationDir $fileName1 $DestinationFilePath = Join-Path $DestinationDir $fileName1
$NestedSourceDir= Join-Path $SourceDir "nested" $NestedSourceDir= Join-Path $SourceDir "nested"
$NestedSourceFilePath = Join-Path $NestedSourceDir $fileName2 $NestedSourceFilePath = Join-Path $NestedSourceDir $fileName2
@ -23,6 +32,7 @@ Describe "Tests for scp command" -Tags "CI" {
$null = New-item -path $SourceFilePath -ItemType file -force -ErrorAction SilentlyContinue $null = New-item -path $SourceFilePath -ItemType file -force -ErrorAction SilentlyContinue
$null = New-item -path $NestedSourceFilePath -ItemType file -force -ErrorAction SilentlyContinue $null = New-item -path $NestedSourceFilePath -ItemType file -force -ErrorAction SilentlyContinue
"Test content111" | Set-content -Path $SourceFilePath "Test content111" | Set-content -Path $SourceFilePath
"Test content333" | Set-content -Path $SourceFilePath3
"Test content in nested dir" | Set-content -Path $NestedSourceFilePath "Test content in nested dir" | Set-content -Path $NestedSourceFilePath
$null = New-Item $DestinationDir -ItemType directory -Force -ErrorAction SilentlyContinue $null = New-Item $DestinationDir -ItemType directory -Force -ErrorAction SilentlyContinue
$sshcmd = (get-command ssh).Path $sshcmd = (get-command ssh).Path
@ -30,7 +40,6 @@ Describe "Tests for scp command" -Tags "CI" {
$server = $OpenSSHTestInfo["Target"] $server = $OpenSSHTestInfo["Target"]
$port = $OpenSSHTestInfo["Port"] $port = $OpenSSHTestInfo["Port"]
$ssouser = $OpenSSHTestInfo["SSOUser"] $ssouser = $OpenSSHTestInfo["SSOUser"]
$script:logNum = 0
$testData = @( $testData = @(
@{ @{
@ -65,6 +74,22 @@ Describe "Tests for scp command" -Tags "CI" {
Title = 'simple copy remote file to local dir' Title = 'simple copy remote file to local dir'
Source = "test_target:$SourceFilePath" Source = "test_target:$SourceFilePath"
Destination = $DestinationDir Destination = $DestinationDir
},
@{
Title = 'Simple copy local file with wild card name to local dir'
Source = $SourceFileWildCardFile1
Destination = $DestinationDir
},
@{
Title = 'simple copy remote file with wild card name to local dir'
Source = "test_target:$SourceFileWildCardFile1"
Destination = $DestinationDir
},
@{
Title = 'simple copy local file to remote dir with wild card name'
Source = $SourceFilePath
Destination = "test_target:$DestinationFilePath"
Options = "-C -q"
} }
) )
@ -92,8 +117,8 @@ Describe "Tests for scp command" -Tags "CI" {
# for the first time, delete the existing log files. # for the first time, delete the existing log files.
if ($OpenSSHTestInfo['DebugMode']) if ($OpenSSHTestInfo['DebugMode'])
{ {
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue Clear-Content "$env:ProgramData\ssh\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue Clear-Content "$env:ProgramData\ssh\logs\sshd.log" -Force -ErrorAction SilentlyContinue
} }
function CheckTarget { function CheckTarget {
@ -102,14 +127,12 @@ Describe "Tests for scp command" -Tags "CI" {
{ {
if( $OpenSSHTestInfo["DebugMode"]) if( $OpenSSHTestInfo["DebugMode"])
{ {
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\failedagent$script:logNum.log" -Force Copy-Item "$env:ProgramData\ssh\logs\ssh-agent.log" "$testDir\failedagent$tI.log" -Force -ErrorAction SilentlyContinue
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\failedsshd$script:logNum.log" -Force Copy-Item "$env:ProgramData\ssh\logs\sshd.log" "$testDir\failedsshd$tI.log" -Force -ErrorAction SilentlyContinue
$script:logNum++
# clear the ssh-agent, sshd logs so that next testcase will get fresh logs. # clear the ssh-agent, sshd logs so that next testcase will get fresh logs.
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue Clear-Content "$env:ProgramData\ssh\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue Clear-Content "$env:ProgramData\ssh\logs\sshd.log" -Force -ErrorAction SilentlyContinue
} }
return $false return $false
@ -143,6 +166,7 @@ Describe "Tests for scp command" -Tags "CI" {
AfterEach { AfterEach {
Get-ChildItem $DestinationDir -Recurse | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue Get-ChildItem $DestinationDir -Recurse | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
Start-Sleep 1 Start-Sleep 1
$tI++
} }
@ -189,4 +213,19 @@ Describe "Tests for scp command" -Tags "CI" {
$equal | Should Be $true $equal | Should Be $true
} }
} }
It 'File copy: path contains wildcards ' {
$Source = Join-Path $SourceDir $wildcardFileName2
scp -p $Source $DestinationDir
$LASTEXITCODE | Should Be 0
#validate file content. DestPath is the path to the file.
CheckTarget -target $DestinationFilePath | Should Be $true
CheckTarget -target (Join-path $DestinationDir $fileName3) | Should Be $true
$equal = @(Compare-Object (Get-ChildItem -path $Source) (Get-ChildItem -path (join-path $DestinationDir $wildcardFileName2)) -Property Name, Length ).Length -eq 0
$equal | Should Be $true
$equal = @(Compare-Object (Get-ChildItem -path $Source).LastWriteTime.DateTime (Get-ChildItem -path (join-path $DestinationDir $wildcardFileName3)).LastWriteTime.DateTime ).Length -eq 0
$equal | Should Be $true
}
} }

View File

@ -1,5 +1,6 @@
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path} If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
$tI = 0
Describe "SFTP Test Cases" -Tags "CI" { Describe "SFTP Test Cases" -Tags "CI" {
BeforeAll { BeforeAll {
$serverDirectory = $null $serverDirectory = $null
@ -30,10 +31,10 @@ Describe "SFTP Test Cases" -Tags "CI" {
$server = $OpenSSHTestInfo["Target"] $server = $OpenSSHTestInfo["Target"]
$port = $OpenSSHTestInfo["Port"] $port = $OpenSSHTestInfo["Port"]
$ssouser = $OpenSSHTestInfo["SSOUser"] $ssouser = $OpenSSHTestInfo["SSOUser"]
$script:testId = 1
Remove-item (Join-Path $rootDirectory "*.$outputFileName") -Force -ErrorAction SilentlyContinue Remove-item (Join-Path $rootDirectory "*.$outputFileName") -Force -ErrorAction SilentlyContinue
Remove-item (Join-Path $rootDirectory "*.$batchFileName") -Force -ErrorAction SilentlyContinue Remove-item (Join-Path $rootDirectory "*.$batchFileName") -Force -ErrorAction SilentlyContinue
Remove-item (Join-Path $rootDirectory "*.log") -Force -ErrorAction SilentlyContinue
$platform = Get-Platform $platform = Get-Platform
$skip = ($platform -eq [PlatformType]::Windows) -and ($PSVersionTable.PSVersion.Major -le 2) $skip = ($platform -eq [PlatformType]::Windows) -and ($PSVersionTable.PSVersion.Major -le 2)
@ -168,22 +169,22 @@ Describe "SFTP Test Cases" -Tags "CI" {
# for the first time, delete the existing log files. # for the first time, delete the existing log files.
if ($OpenSSHTestInfo['DebugMode']) if ($OpenSSHTestInfo['DebugMode'])
{ {
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue Clear-Content "$env:ProgramData\ssh\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue Clear-Content "$env:ProgramData\ssh\logs\sshd.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" -Force -ErrorAction SilentlyContinue Clear-Content "$env:ProgramData\ssh\logs\sftp-server.log" -Force -ErrorAction SilentlyContinue
} }
function CopyDebugLogs { function CopyDebugLogs {
if($OpenSSHTestInfo["DebugMode"]) if($OpenSSHTestInfo["DebugMode"])
{ {
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent_$script:testId.log" -Force Copy-Item "$env:ProgramData\ssh\logs\ssh-agent.log" "$rootDirectory\ssh-agent_$tI.log" -Force -ErrorAction SilentlyContinue
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd_$script:testId.log" -Force Copy-Item "$env:ProgramData\ssh\logs\sshd.log" "$rootDirectory\sshd_$tI.log" -Force -ErrorAction SilentlyContinue
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server_$script:testId.log" -Force Copy-Item "$env:ProgramData\ssh\logs\sftp-server.log" "$rootDirectory\sftp-server_$tI.log" -Force -ErrorAction SilentlyContinue
# clear the ssh-agent, sshd logs so that next testcase will get fresh logs. # clear the ssh-agent, sshd logs so that next testcase will get fresh logs.
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue Clear-Content "$env:ProgramData\ssh\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue Clear-Content "$env:ProgramData\ssh\logs\sshd.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" -Force -ErrorAction SilentlyContinue Clear-Content "$env:ProgramData\ssh\logs\sftp-server.log" -Force -ErrorAction SilentlyContinue
} }
} }
} }
@ -196,13 +197,13 @@ Describe "SFTP Test Cases" -Tags "CI" {
BeforeEach { BeforeEach {
if($serverDirectory) { Get-ChildItem $serverDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue } if($serverDirectory) { Get-ChildItem $serverDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }
if($clientDirectory) { Get-ChildItem $clientDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue } if($clientDirectory) { Get-ChildItem $clientDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }
$outputFilePath = Join-Path $rootDirectory "$($script:testId).$outputFileName" $outputFilePath = Join-Path $rootDirectory "$tI.$outputFileName"
$batchFilePath = Join-Path $rootDirectory "$($script:testId).$batchFileName" $batchFilePath = Join-Path $rootDirectory "$tI.$batchFileName"
} }
AfterEach { AfterEach {
CopyDebugLogs CopyDebugLogs
$script:testId++ $tI++
} }
It '<Title>' -TestCases:$testData1 { It '<Title>' -TestCases:$testData1 {

53
scp.c
View File

@ -107,6 +107,7 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include "openbsd-compat/glob.h"
#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
#include <vis.h> #include <vis.h>
#endif #endif
@ -489,8 +490,43 @@ main(int argc, char **argv)
/* Copy argv, because we modify it */ /* Copy argv, because we modify it */
newargv = xcalloc(MAXIMUM(argc + 1, 1), sizeof(*newargv)); newargv = xcalloc(MAXIMUM(argc + 1, 1), sizeof(*newargv));
#ifdef WINDOWS
{
/*
* Wildcards are not expanded by shell on Windows; expand them
* Convert '\\' to '/' in path portion to support both Windows and Unix style paths
*/
char *p, *argdup;
int i = 0;
glob_t g;
int expandargc = 0;
memset(&g, 0, sizeof(g));
for (n = 0; n < argc; n++) {
argdup = xstrdup(argv[n]);
if (p = colon(argdup))
convertToForwardslash(p);
else
convertToForwardslash(argdup);
if (glob(argdup, GLOB_NOCHECK, NULL, &g)) {
if (expandargc > argc)
newargv = xreallocarray(newargv, expandargc + 1, sizeof(*newargv));
newargv[expandargc++] = xstrdup(argdup);
} else {
int count = g.gl_matchc > 1 ? g.gl_matchc : 1;
if (expandargc + count > argc - 1)
newargv = xreallocarray(newargv, expandargc + count, sizeof(*newargv));
for (i = 0; i < count; i++)
newargv[expandargc++] = xstrdup(g.gl_pathv[i]);
}
free(argdup);
globfree(&g);
}
argc = expandargc;
}
#else /* !WINDOWS */
for (n = 0; n < argc; n++) for (n = 0; n < argc; n++)
newargv[n] = xstrdup(argv[n]); newargv[n] = xstrdup(argv[n]);
#endif /* !WINDOWS */
argv = newargv; argv = newargv;
__progname = ssh_get_progname(argv[0]); __progname = ssh_get_progname(argv[0]);
@ -609,23 +645,6 @@ main(int argc, char **argv)
remin = STDIN_FILENO; remin = STDIN_FILENO;
remout = STDOUT_FILENO; remout = STDOUT_FILENO;
#ifdef WINDOWS
/*
* To support both Windows and Unix style paths
* convert '\\' to '/' in path portion of rest arguments
*/
{
int i;
char *p;
for (i = 0; i < argc; i++) {
if(p = colon(argv[i]))
convertToForwardslash(p);
else
convertToForwardslash(argv[i]);
}
}
#endif /* WINDOWS */
if (fflag) { if (fflag) {
/* Follow "protocol", send data. */ /* Follow "protocol", send data. */
(void) response(); (void) response();