Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1109 lines
28 KiB

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
cmds.c
Abstract:
FTP commands
Author:
Richard L Firth (rfirth) 03-Nov-1995
Revision History:
03-Nov-1995 rfirth
Created
--*/
#include "ftpcatp.h"
//
// manifests
//
#define MAX_ARGV 20
#define COMMAND_WHITESPACE TEXT(" ,\r\n")
//
// external functions
//
extern
BOOL
Prompt(
IN LPCTSTR pszPrompt,
OUT LPTSTR* ppszCommand
);
//
// prototypes
//
BOOL dbgbreak(HINTERNET, int, PTCHAR *);
BOOL chdir(HINTERNET, int, PTCHAR *);
BOOL del(HINTERNET, int, PTCHAR *);
BOOL dir(HINTERNET, int, PTCHAR *);
BOOL get(HINTERNET, int, PTCHAR *);
BOOL help(HINTERNET, int, PTCHAR *);
BOOL lcd(HINTERNET, int, char**);
BOOL mkdir(HINTERNET, int, PTCHAR *);
BOOL put(HINTERNET, int, PTCHAR *);
BOOL pwd(HINTERNET, int, PTCHAR *);
BOOL quit(HINTERNET, int, PTCHAR *);
BOOL rb(HINTERNET, int, char**);
BOOL rename_file(HINTERNET, int, PTCHAR *);
BOOL rmdir(HINTERNET, int, PTCHAR *);
BOOL wb(HINTERNET, int, char**);
BOOL toggle_verbose(HINTERNET, int, PTCHAR *);
BOOL set_type(HINTERNET, int, PTCHAR *);
BOOL open_file(HINTERNET, int, PTCHAR *);
BOOL close_file(HINTERNET, int, PTCHAR *);
BOOL read_file(HINTERNET, int, PTCHAR *);
BOOL write_file(HINTERNET, int, PTCHAR *);
BOOL DispatchCommand(LPTSTR, HINTERNET);
#if DBG
BOOL CheckHandles(HINTERNET, int, PTCHAR*);
#endif
//
// external data
//
extern DWORD Verbose;
extern INTERNET_STATUS_CALLBACK PreviousCallback;
extern HINTERNET hCancel;
extern BOOL AsyncMode;
extern HANDLE AsyncEvent;
extern DWORD AsyncResult;
extern DWORD AsyncError;
extern BOOL UseQueryData;
//
// data
//
typedef struct {
LPCSTR pszCommand;
LPCSTR HelpText;
BOOL (*fn)(HINTERNET, int, PTCHAR []);
} COMMAND_ENTRY;
COMMAND_ENTRY Commands[] = {
#if DBG
{"b", "Break into debugger", dbgbreak},
#endif
{"!", "Shell escape", NULL},
{"?", "This list", help},
{"cd", "Change to a remote directory", chdir},
{"close", "Close an open file handle", close_file},
{"dir", "List a directory", dir},
{"del", "Delete a remote file", del},
{"get", "Copy a file from the server", get},
#if DBG
{"hndl", "Get current handle count", CheckHandles},
#endif
{"lcd", "Change local directory", lcd},
{"md", "Create a remote directory", mkdir},
{"open", "Open a file for read or write", open_file},
{"put", "Copy a file to the server", put},
{"pwd", "Display the current directory", pwd},
{"quit", "Terminate this program", quit},
{"rb", "Get/set Read buffer size", rb},
{"rd", "Remove a remote directory", rmdir},
{"read", "Read data from a file", read_file},
{"ren", "Rename a remote file", rename_file},
{"type", "Set transfer type", set_type},
{"verbose", "Toggle verbose mode", toggle_verbose},
{"wb", "Get/set Write buffer size", wb},
{"write", "Write data to a file", write_file},
{NULL, NULL, NULL}
};
BOOL fQuit = FALSE;
DWORD CacheFlags = 0;
HINTERNET FileHandle = NULL;
//
// functions
//
void get_response(HINTERNET hFtp) {
DWORD buflen;
char buffer[2048];
DWORD category;
buflen = sizeof(buffer);
if (InternetGetLastResponseInfo(&category, buffer, &buflen)) {
if (hFtp && (Verbose >= 2)) {
DWORD len = sizeof(DWORD);
DWORD dwFlags;
if (InternetQueryOption(hFtp,
INTERNET_OPTION_REQUEST_FLAGS,
&dwFlags,
&len)) {
if (dwFlags & INTERNET_REQFLAG_FROM_CACHE) {
fprintf(stderr, "****** Got from the cache ***** \n");
} else {
fprintf(stderr, "****** From the wire ***** \n");
}
}
}
if (buflen || (Verbose >= 2)) {
print_response(buffer, buflen, TRUE);
}
} else {
DWORD error;
error = GetLastError();
if (Verbose || (error != ERROR_INSUFFICIENT_BUFFER)) {
LPSTR errString;
errString = (error == ERROR_INSUFFICIENT_BUFFER)
? "InternetGetLastResponseInfo() returns error %d (buflen = %d)\n"
: "InternetGetLastResponseInfo() returns error %d\n"
;
printf(errString, error, buflen);
}
if (error = ERROR_INSUFFICIENT_BUFFER) {
LPSTR errbuf;
if ((errbuf = malloc(buflen)) == NULL) {
printf("error: get_response: malloc(%d) failed\n", buflen);
return;
}
if (InternetGetLastResponseInfo(&category, errbuf, &buflen)) {
if (buflen || (Verbose >= 2)) {
print_response(errbuf, buflen, TRUE);
}
} else {
printf("error: get_response: InternetGetLastResponseInfo() returns error %d (buflen = %d)\n",
GetLastError(),
buflen
);
}
free(errbuf);
}
}
}
BOOL
quit(
IN HINTERNET hFtpSession,
IN int argc,
IN PTCHAR argv[]
)
{
fQuit = TRUE;
return TRUE;
}
BOOL
get(
IN HINTERNET hFtpSession,
IN int argc,
IN PTCHAR argv[]
)
{
LPTSTR pszFilename;
LPTSTR pszLocalfile;
BOOL ok;
if (argc < 2) {
if (!Prompt(TEXT("remote-name: "), &pszFilename)) {
return FALSE;
}
} else {
pszFilename = argv[1];
}
if (argc >= 3) {
pszLocalfile = argv[2];
} else {
pszLocalfile = pszFilename;
}
ok = FtpGetFile(hFtpSession,
pszFilename,
pszLocalfile,
FALSE,
FILE_ATTRIBUTE_NORMAL,
CacheFlags
| FTP_TRANSFER_TYPE_BINARY,
FTPCAT_GET_CONTEXT
);
if (AsyncMode && !ok) {
if (GetLastError() != ERROR_IO_PENDING) {
print_error("get", "FtpGetFile()");
} else {
if (Verbose) {
printf("waiting for async FtpGetFile()...\n");
}
WaitForSingleObject(AsyncEvent, INFINITE);
ok = (BOOL)AsyncResult;
}
}
if (!ok) {
if (AsyncMode) {
SetLastError(AsyncError);
}
print_error("get", "%sFtpGetFile()", AsyncMode ? "async " : "");
} else {
get_response(hFtpSession);
}
return ok;
}
BOOL
put(
IN HINTERNET hFtpSession,
IN int argc,
IN PTCHAR argv[]
)
{
LPTSTR pszFilename;
LPTSTR pszLocalfile;
BOOL ok;
if (argc < 2) {
if (!Prompt(TEXT("remote-name: "), &pszFilename)) {
return FALSE;
}
} else {
pszFilename = argv[1];
}
if (argc >= 3) {
pszLocalfile = argv[2];
} else {
pszLocalfile = pszFilename;
}
ok = FtpPutFile(hFtpSession,
pszLocalfile,
pszFilename,
FTP_TRANSFER_TYPE_BINARY,
FTPCAT_PUT_CONTEXT
);
if (AsyncMode && !ok) {
if (GetLastError() != ERROR_IO_PENDING) {
print_error("put", "FtpPutFile()");
} else {
if (Verbose) {
printf("waiting for async FtpPutFile()...\n");
}
WaitForSingleObject(AsyncEvent, INFINITE);
ok = (BOOL)AsyncResult;
}
}
if (!ok) {
if (AsyncMode) {
SetLastError(AsyncError);
}
print_error("put", "%sFtpPutFile()", AsyncMode ? "async " : "");
} else {
get_response(hFtpSession);
}
return ok;
}
BOOL
rename_file(
IN HINTERNET hFtpSession,
IN int argc,
IN PTCHAR argv[]
)
{
LPTSTR pszTemp;
LPTSTR pszOldFilename;
LPTSTR pszNewFilename;
BOOL ok;
if (argc < 2) {
if (!Prompt(TEXT("Old name: "), &pszTemp)) {
return FALSE;
}
pszOldFilename = lstrdup(pszTemp);
if (pszOldFilename == NULL) {
return FALSE;
}
} else {
pszOldFilename = argv[1];
}
if (argc < 3) {
if (!Prompt(TEXT("New name: "), &pszNewFilename)) {
return FALSE;
}
} else {
pszNewFilename = argv[2];
}
ok = FtpRenameFile(hFtpSession,
pszOldFilename,
pszNewFilename
);
if (AsyncMode && !ok) {
if (GetLastError() != ERROR_IO_PENDING) {
print_error("rename_file", "FtpRenameFile()");
} else {
if (Verbose) {
printf("waiting for async FtpRenameFile()...\n");
}
WaitForSingleObject(AsyncEvent, INFINITE);
ok = (BOOL)AsyncResult;
}
}
if (!ok) {
if (AsyncMode) {
SetLastError(AsyncError);
}
print_error("rename_file", "%sFtpRenameFile()", AsyncMode ? "async " : "");
} else {
get_response(hFtpSession);
}
if (argc < 2) {
LocalFree(pszOldFilename);
}
return ok;
}
BOOL
del(
IN HINTERNET hFtpSession,
IN int argc,
IN PTCHAR argv[]
)
{
LPTSTR pszFilename;
BOOL ok;
if (argc < 2) {
if (!Prompt(TEXT("File name: "), &pszFilename)) {
return FALSE;
}
} else {
pszFilename = argv[1];
}
ok = FtpDeleteFile(hFtpSession, pszFilename);
if (AsyncMode && !ok) {
if (GetLastError() != ERROR_IO_PENDING) {
print_error("del", "FtpDeleteFile()");
} else {
if (Verbose) {
printf("waiting for async FtpDeleteFile()...\n");
}
WaitForSingleObject(AsyncEvent, INFINITE);
ok = (BOOL)AsyncResult;
}
}
if (!ok) {
if (AsyncMode) {
SetLastError(AsyncError);
}
print_error("del",
"%sFtpDeleteFile()",
AsyncMode ? "async " : ""
);
} else {
get_response(hFtpSession);
}
return ok;
}
BOOL
mkdir(
IN HINTERNET hFtpSession,
IN int argc,
IN PTCHAR argv[]
)
{
LPTSTR pszDirname;
BOOL ok;
if (argc < 2) {
if (!Prompt(TEXT("Directory name: "), &pszDirname)) {
return FALSE;
}
} else {
pszDirname = argv[1];
}
ok = FtpCreateDirectory(hFtpSession,
pszDirname
);
if (AsyncMode && !ok) {
if (GetLastError() != ERROR_IO_PENDING) {
print_error("mkdir", "FtpCreateDirectory()");
} else {
if (Verbose) {
printf("waiting for async FtpCreateDirectory()...\n");
}
WaitForSingleObject(AsyncEvent, INFINITE);
ok = (BOOL)AsyncResult;
}
}
if (!ok) {
if (AsyncMode) {
SetLastError(AsyncError);
}
print_error("mkdir", "%sFtpCreateDirectory()", AsyncMode ? "async " : "");
} else {
get_response(hFtpSession);
}
return ok;
}
BOOL
chdir(
IN HINTERNET hFtpSession,
IN int argc,
IN PTCHAR argv[]
)
{
LPTSTR pszDirname;
BOOL ok;
if (argc < 2) {
if (!Prompt(TEXT("Directory name: "), &pszDirname)) {
return FALSE;
}
} else {
pszDirname = argv[1];
}
ok = FtpSetCurrentDirectory(hFtpSession,
pszDirname
);
if (AsyncMode && !ok) {
if (GetLastError() != ERROR_IO_PENDING) {
print_error("chdir", "FtpSetCurrentDirectory()");
} else {
if (Verbose) {
printf("waiting for async FtpSetCurrentDirectory()...\n");
}
WaitForSingleObject(AsyncEvent, INFINITE);
ok = (BOOL)AsyncResult;
}
}
if (!ok) {
if (AsyncMode) {
SetLastError(AsyncError);
}
print_error("chdir", "%sFtpSetCurrentDirectory()", AsyncMode ? "async " : "");
} else {
get_response(hFtpSession);
}
return ok;
}
BOOL
rmdir(
IN HINTERNET hFtpSession,
IN int argc,
IN PTCHAR argv[]
)
{
LPTSTR pszDirname;
BOOL ok;
if (argc < 2) {
if (!Prompt(TEXT("Directory name: "), &pszDirname)) {
return FALSE;
}
} else {
pszDirname = argv[1];
}
ok = FtpRemoveDirectory(hFtpSession,
pszDirname
);
if (AsyncMode && !ok) {
if (GetLastError() != ERROR_IO_PENDING) {
print_error("rmdir", "FtpRemoveDirectory()");
} else {
if (Verbose) {
printf("waiting for async FtpRemoveDirectory()...\n");
}
WaitForSingleObject(AsyncEvent, INFINITE);
ok = (BOOL)AsyncResult;
}
}
if (!ok) {
if (AsyncMode) {
SetLastError(AsyncError);
}
print_error("rmdir", "%sFtpRemoveDirectory()", AsyncMode ? "async " : "");
} else {
get_response(hFtpSession);
}
return ok;
}
BOOL
dir(
IN HINTERNET hFtpSession,
IN int argc,
IN PTCHAR argv[]
)
{
BOOL ok;
WIN32_FIND_DATA ffd;
SYSTEMTIME st;
LPTSTR pszFileSpec;
TCHAR EmptyExpression[] = "";
HINTERNET hFind;
HINTERNET hPrevious;
static LPSTR month[] = {
"",
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
};
if (argc < 2) {
pszFileSpec = EmptyExpression;
} else {
pszFileSpec = argv[1];
}
hFind = FtpFindFirstFileA(hFtpSession,
pszFileSpec,
&ffd,
CacheFlags, // dwFlags
FTPCAT_FIND_CONTEXT
);
if (AsyncMode && (hFind == NULL)) {
if (GetLastError() == ERROR_IO_PENDING) {
if (Verbose) {
printf("waiting for async FtpFindFirstFile()...\n");
}
WaitForSingleObject(AsyncEvent, INFINITE);
hFind = (HINTERNET)AsyncResult;
if (hFind == NULL) {
SetLastError(AsyncError);
}
}
}
if (hFind == NULL) {
print_error("dir", "%sFtpFindFirstFile()", AsyncMode ? "async " : "");
return FALSE;
}
hPrevious = hCancel;
hCancel = hFind;
get_response(hFind);
putchar('\n');
ok = TRUE;
while (ok) {
if (!FileTimeToSystemTime(&ffd.ftLastWriteTime, &st)) {
printf("| ftLastWriteTime = ERROR\n");
}
printf("%02d-%s-%04d %02d:%02d:%02d %15d bytes %-s%-s%-s%-s%-s%-s %s\n",
st.wDay,
month[st.wMonth],
st.wYear,
st.wHour,
st.wMinute,
st.wSecond,
ffd.nFileSizeLow,
(ffd.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ? "Archive " : "",
(ffd.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) ? "Normal " : "",
(ffd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) ? "System " : "",
(ffd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? "Hidden " : "",
(ffd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? "ReadOnly " : "",
(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? "Directory " : "",
ffd.cFileName
);
if (UseQueryData) {
DWORD error;
DWORD avail;
ok = InternetQueryDataAvailable(hFind, &avail, 0, 0);
if (!ok) {
error = GetLastError();
if (error == ERROR_IO_PENDING) {
if (Verbose) {
printf("waiting for async InternetQueryDataAvailable()...\n");
}
WaitForSingleObject(AsyncEvent, INFINITE);
ok = (BOOL)AsyncResult;
SetLastError(AsyncError);
}
}
if (!ok) {
print_error("dir", "%sSYNC InternetQueryDataAvailable()", AsyncMode ? "A" : "");
break;
}
if (Verbose) {
printf("InternetQueryDataAvailable() returns %d available\n", avail);
}
if (avail == 0) {
break;
}
}
ok = InternetFindNextFile(hFind, &ffd);
if (!ok && AsyncMode) {
if (GetLastError() == ERROR_IO_PENDING) {
if (Verbose) {
printf("waiting for async InternetFindNextFile()...\n");
}
WaitForSingleObject(AsyncEvent, INFINITE);
ok = (BOOL)AsyncResult;
if (!ok) {
SetLastError(AsyncError);
}
}
}
if (!ok) {
if (GetLastError() != ERROR_NO_MORE_FILES) {
print_error("dir", "%sInternetFindNextFile()", AsyncMode ? "async " : "");
break;
}
}
}
putchar('\n');
close_handle(hFind);
hCancel = hPrevious;
return ok;
}
BOOL
pwd(
IN HINTERNET hFtpSession,
IN int argc,
IN PTCHAR argv[]
)
{
BOOL ok;
char* buf;
DWORD len;
len = 0;
ok = FtpGetCurrentDirectory(hFtpSession, NULL, &len);
if (AsyncMode && !ok) {
if (GetLastError() != ERROR_IO_PENDING) {
print_error("pwd", "async FtpGetCurrentDirectory()");
} else {
if (Verbose) {
printf("waiting for async FtpGetCurrentDirectory()...\n");
}
WaitForSingleObject(AsyncEvent, INFINITE);
ok = (BOOL)AsyncResult;
SetLastError(AsyncError);
}
}
if (ok) {
printf("error: FtpGetCurrentDirectory() w/ no buffer returns ok\n");
return FALSE;
} else if (Verbose) {
printf("FtpGetCurrentDirectory() returns %d, %d bytes in cur dir\n",
GetLastError(),
len
);
}
buf = (char*)malloc(len);
ok = FtpGetCurrentDirectory(hFtpSession, buf, &len);
if (AsyncMode && !ok) {
if (GetLastError() != ERROR_IO_PENDING) {
print_error("pwd", "async FtpGetCurrentDirectory()");
} else {
if (Verbose) {
printf("waiting for async FtpGetCurrentDirectory()...\n");
}
WaitForSingleObject(AsyncEvent, INFINITE);
ok = (BOOL)AsyncResult;
SetLastError(AsyncError);
}
}
if (!ok) {
print_error("pwd", "%sFtpGetCurrentDirectory()", AsyncMode ? "async " : "");
} else {
get_response(hFtpSession);
lprintf(TEXT("Current directory: %s\n"), buf);
}
free(buf);
return ok;
}
BOOL help(IN HINTERNET hFtpSession, IN int argc, IN PTCHAR argv[]) {
int i;
for (i = 0; Commands[i].pszCommand != NULL; ++i) {
lprintf(TEXT("\t%s\t%s\n"),
Commands[i].pszCommand,
Commands[i].HelpText
);
}
return TRUE;
}
#if DBG
BOOL CheckHandles(HINTERNET hFtpSession, int argc, PTCHAR argv[]) {
printf("handle count = %d\n", GetProcessHandleCount());
return TRUE;
}
#endif
BOOL lcd(HINTERNET hInternet, int argc, char** argv) {
char curDir[MAX_PATH + 1];
DWORD curDirLen;
if (argc == 2) {
if (!SetCurrentDirectory(argv[1])) {
print_error("lcd", "SetCurrentDirectory()");
return FALSE;
}
} else if (argc != 1) {
printf("error: lcd: incorrect number of arguments\n");
return FALSE;
}
curDirLen = sizeof(curDir);
if (GetCurrentDirectory(curDirLen, curDir)) {
printf("Current directory is %s\n", curDir);
return TRUE;
} else {
print_error("lcd", "GetCurrentDirectory()");
return FALSE;
}
}
BOOL rb(HINTERNET hInternet, int argc, char** argv) {
DWORD value;
DWORD valueLength;
if (argc > 1) {
value = atoi(argv[1]);
if (!InternetSetOption(hInternet,
INTERNET_OPTION_READ_BUFFER_SIZE,
(LPVOID)&value,
sizeof(DWORD)
)) {
print_error("rb", "InternetSetOption()");
return FALSE;
}
}
valueLength = sizeof(value);
if (InternetQueryOption(hInternet,
INTERNET_OPTION_READ_BUFFER_SIZE,
(LPVOID)&value,
&valueLength
)) {
printf("Read buffer size = %d bytes\n", value);
return TRUE;
} else {
print_error("rb", "InternetQueryOption()");
return FALSE;
}
}
BOOL wb(HINTERNET hInternet, int argc, char** argv) {
DWORD value;
DWORD valueLength;
if (argc > 1) {
value = atoi(argv[1]);
if (!InternetSetOption(hInternet,
INTERNET_OPTION_WRITE_BUFFER_SIZE,
(LPVOID)&value,
sizeof(DWORD)
)) {
print_error("wb", "InternetSetOption()");
return FALSE;
}
}
valueLength = sizeof(value);
if (InternetQueryOption(hInternet,
INTERNET_OPTION_WRITE_BUFFER_SIZE,
(LPVOID)&value,
&valueLength
)) {
printf("Write buffer size = %d bytes\n", value);
return TRUE;
} else {
print_error("wb", "InternetQueryOption()");
return FALSE;
}
}
BOOL toggle_verbose(HINTERNET hInternet, int argc, PTCHAR * argv) {
static DWORD PreviousVerbose = 0;
if (Verbose) {
PreviousVerbose = Verbose;
Verbose = 0;
} else {
Verbose = PreviousVerbose;
if (Verbose == 0) {
Verbose = 1;
}
}
printf("Verbose mode is o%s\n", Verbose ? "n" : "ff");
return TRUE;
}
BOOL toggle_callback(HINTERNET hInternet, int argc, PTCHAR * argv) {
INTERNET_STATUS_CALLBACK callback;
if (PreviousCallback != NULL && PreviousCallback != my_callback) {
printf("error: PreviousCallback %x not recognized\n", PreviousCallback);
} else {
PreviousCallback = InternetSetStatusCallback(hInternet, PreviousCallback);
if (PreviousCallback == INTERNET_INVALID_STATUS_CALLBACK) {
print_error("toggle_callback", "InternetSetStatusCallback()");
} else if (PreviousCallback != NULL && PreviousCallback != my_callback) {
printf("error: PreviousCallback %x not recognized\n", PreviousCallback);
} else if (Verbose) {
printf("callback toggled Ok\n");
}
}
printf("Verbose mode is o%s\n", Verbose ? "n" : "ff");
return TRUE;
}
BOOL dbgbreak(HINTERNET hInternet, int argc, PTCHAR * argv) {
DebugBreak();
return TRUE;
}
BOOL set_type(HINTERNET hInternet, int argc, PTCHAR * argv) {
return TRUE;
}
BOOL open_file(HINTERNET hInternet, int argc, PTCHAR * argv) {
HINTERNET hFile;
BOOL bOk;
if (argc < 2) {
printf("error: required filename missing\n");
return FALSE;
}
hFile = FtpOpenFile(hInternet,
argv[1],
GENERIC_READ,
0,
AsyncMode ? FTPCAT_OPEN_CONTEXT : 0
);
if (AsyncMode && !hFile) {
if (GetLastError() != ERROR_IO_PENDING) {
print_error("open_file", "async FtpOpenFile()");
return FALSE;
}
if (Verbose) {
printf("waiting for async FtpOpenFile()...\n");
}
WaitForSingleObject(AsyncEvent, INFINITE);
hFile = (HINTERNET)AsyncResult;
SetLastError(AsyncError);
}
if (!hFile) {
print_error("open_file", "%sFtpOpenFile()", AsyncMode ? "async " : "");
} else {
get_response(hInternet);
printf("returned handle is %#x\n", hFile);
}
return hFile != NULL;
}
BOOL close_file(HINTERNET hInternet, int argc, PTCHAR * argv) {
HINTERNET hFile;
BOOL bOk;
if (argc < 2) {
printf("error: required handle missing\n");
return FALSE;
}
hFile = (HINTERNET)strtol(argv[1], NULL, 0);
bOk = InternetCloseHandle(hFile);
if (!bOk) {
print_error("close_file", "InternetCloseHandle()");
} else if (Verbose) {
printf("handle %#x closed OK\n", hFile);
}
return bOk;
}
BOOL read_file(HINTERNET hInternet, int argc, PTCHAR * argv) {
return TRUE;
}
BOOL write_file(HINTERNET hInternet, int argc, PTCHAR * argv) {
return TRUE;
}
BOOL
DispatchCommand(
IN LPTSTR pszCommand,
IN HINTERNET hFtpSession
)
{
COMMAND_ENTRY *pce;
PTCHAR ArgV[MAX_ARGV];
int index;
int state;
if (*pszCommand == TEXT('!')) {
LPSTR shellPath;
shellPath = getenv("COMSPEC");
if (shellPath == NULL) {
printf("error: COMSPEC environment variable not set\n");
return FALSE;
}
++pszCommand;
while (isspace(*pszCommand)) {
++pszCommand;
}
if (*pszCommand != TEXT('\0')) {
_spawnlp(_P_WAIT, shellPath, "/C", pszCommand, NULL);
} else {
printf("\nSpawning command interpreter. Type \"exit\" to return to FTP\n\n");
_spawnlp(_P_WAIT, shellPath, "/K", NULL);
putchar('\n');
}
return TRUE;
}
state = 0;
index = 0;
while (*pszCommand) {
switch (state) {
case 0:
if (!isspace(*pszCommand)) {
if (*pszCommand == '"') {
state = 2;
} else {
state = 1;
}
ArgV[index++] = (state == 2) ? (pszCommand + 1) : pszCommand;
}
break;
case 1:
if (isspace(*pszCommand)) {
*pszCommand = '\0';
state = 0;
}
break;
case 2:
if (*pszCommand == '"') {
*pszCommand = '\0';
state = 0;
}
break;
}
++pszCommand;
}
if (index == 0) {
return FALSE;
}
for (pce = Commands; pce->pszCommand != NULL; pce++) {
if (lstrcmpi(pce->pszCommand, ArgV[0]) == 0) {
return pce->fn(hFtpSession, index, ArgV);
}
}
if (!lstrcmpi(ArgV[0], "q")) {
return quit(hFtpSession, index, ArgV);
}
printf("error: unrecognized command: \"%s\"\n", ArgV[0]);
return FALSE;
}