Added Wine command-line interpreter.
This commit is contained in:
parent
5cec819d11
commit
74f440eabf
|
@ -5300,6 +5300,7 @@ programs/progman/Makefile
|
|||
programs/regtest/Makefile
|
||||
programs/regapi/Makefile
|
||||
programs/view/Makefile
|
||||
programs/wcmd/Makefile
|
||||
programs/winhelp/Makefile
|
||||
programs/winver/Makefile
|
||||
rc/Makefile
|
||||
|
@ -5469,6 +5470,7 @@ programs/progman/Makefile
|
|||
programs/regtest/Makefile
|
||||
programs/regapi/Makefile
|
||||
programs/view/Makefile
|
||||
programs/wcmd/Makefile
|
||||
programs/winhelp/Makefile
|
||||
programs/winver/Makefile
|
||||
rc/Makefile
|
||||
|
|
|
@ -802,6 +802,7 @@ programs/progman/Makefile
|
|||
programs/regtest/Makefile
|
||||
programs/regapi/Makefile
|
||||
programs/view/Makefile
|
||||
programs/wcmd/Makefile
|
||||
programs/winhelp/Makefile
|
||||
programs/winver/Makefile
|
||||
rc/Makefile
|
||||
|
|
|
@ -8,6 +8,7 @@ SUBDIRS = \
|
|||
regapi \
|
||||
regtest \
|
||||
view \
|
||||
wcmd \
|
||||
winhelp \
|
||||
winver
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
Makefile
|
||||
wcmd
|
||||
wcmdrc.s
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
v0.10 - 2 June 1999
|
||||
Additional help text and error codes.
|
||||
|
||||
v0.09 - 5 May 1999
|
||||
Directory byte counts and disk free space are reported with commas and in 64-bit.
|
||||
File sizes have commas but are computed in 32 bits.
|
||||
Handling of DIR /S on non-current path corrected.
|
||||
DEL with wildcard or directory name works correctly.
|
||||
|
||||
v0.08 - 21 Mar 1999
|
||||
Invoke an AUTOEXEC.BAT file if it exists in the root directory of the startup drive.
|
||||
|
||||
v0.07 - 8 Mar 1999
|
||||
Can now be compiled as a WineLib app (conditional code added).
|
||||
Additional help text.
|
||||
Icon added to resources (the Wine-glass).
|
||||
|
||||
v0.06 - 23 Feb 1999
|
||||
Help text moved into resource file to allow localisation.
|
||||
Simple batch files (without parameters) can be executed.
|
||||
|
||||
v0.05 - 17 Feb 1999
|
||||
Fixed problem with DIR command & long, complex relative paths.
|
||||
DIR /S and /P implemented.
|
||||
Date and time in PROMPT localised.
|
||||
More work on batch files (they are echoed to screen but not executed).
|
||||
|
||||
v0.04 - 7 Feb 1999
|
||||
Command-line qualifiers /c /q /k implemented (as NT's CMD.EXE).
|
||||
ECHO command implemented, though echo mode is not honoured.
|
||||
Environment variables in commands (eg %envvar%) expanded.
|
||||
REN and COPY added, but no wildcard support or relative paths.
|
||||
Filenames in quotes now handled.
|
||||
PAUSE command.
|
||||
Preliminary coding for batch files.
|
||||
|
||||
v0.03 - 5 Feb 1999
|
||||
Added relative path and alternate drive support to DIR, also free disk space
|
||||
(32-bit only!).
|
||||
|
||||
v0.02 - 27 Jan 1999
|
||||
Added change-drive code.
|
||||
|
||||
v0.01 - 25 Jan 1999
|
||||
Initial version.
|
|
@ -0,0 +1,43 @@
|
|||
DEFS = -DWINELIB
|
||||
TOPSRCDIR = @top_srcdir@
|
||||
TOPOBJDIR = ../..
|
||||
SRCDIR = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
MODULE = none
|
||||
PROGRAMS = wcmd
|
||||
ALL_LIBS = $(WINELIB) $(X_LIBS) $(XLIB) $(LIBS)
|
||||
RCFLAGS = -w32 -h
|
||||
WRCEXTRA = -A -t -p $*
|
||||
|
||||
C_SRCS = \
|
||||
batch.c \
|
||||
builtins.c \
|
||||
directory.c \
|
||||
wcmdmain.c
|
||||
|
||||
RC_SRCS = \
|
||||
wcmdrc.rc
|
||||
|
||||
all: check_wrc $(PROGRAMS)
|
||||
|
||||
depend:: $(RC_SRCS:.rc=.h)
|
||||
|
||||
@MAKE_RULES@
|
||||
|
||||
#this line is needed to prevent winestub.o being linked
|
||||
WINESTUB =
|
||||
|
||||
wcmd: $(OBJS)
|
||||
$(CC) -o wcmd $(OBJS) $(LDOPTIONS) $(ALL_LIBS)
|
||||
|
||||
install: dummy
|
||||
$(INSTALL_PROGRAM) wcmd $(bindir)/wcmd
|
||||
|
||||
uninstall: dummy
|
||||
$(RM) $(bindir)/wcmd
|
||||
|
||||
$(RC_SRCS:.rc=.s): $(WRC)
|
||||
|
||||
dummy:
|
||||
|
||||
### Dependencies:
|
|
@ -0,0 +1,50 @@
|
|||
WCMD - A Command-Line Interface for WINE
|
||||
Copyright (C) 1999 D Pickles (davep@nugate.demon.co.uk)
|
||||
Open Source software published under the Wine Licence and Warranty.
|
||||
|
||||
This is an Alpha version and is very much "work in progress".
|
||||
|
||||
WHAT'S INCLUDED
|
||||
- Sources
|
||||
- A Makefile for compiling with LibWine. Build Wine with "-enable-dll" first.
|
||||
- A Makefile for Borland C++ (needs editing for directories).
|
||||
|
||||
WHAT'S MISSING
|
||||
- Redirection, shell parameters and pipes
|
||||
- Command-line qualifiers for most builtin commands
|
||||
- MOVE command (plus the batch-only ones)
|
||||
- Wildcards and relative paths in COPY and RENAME
|
||||
- Set functionality in DATE, TIME, ATTRIB, SET, LABEL
|
||||
- Full internationalisation of the text (and commands?).
|
||||
|
||||
WHAT DOESN'T WORK
|
||||
- At present it is not possible to launch Windows GDI programs from the command
|
||||
line. This is result of the way the CreateProcess() API call is implemented in
|
||||
Wine, and will be fixed in a later Wine release.
|
||||
- The ATTRIB command reports all files having their Archive flag set, and the
|
||||
READONLY setting depends on the Unix file permissions. All other flags are
|
||||
always clear. The Wine attributes API calls map to the Unix stat() function
|
||||
which cannot handle the other attributes available in DOS.
|
||||
- Date/timestamps of files in the DIR listing are shown using the current
|
||||
locale. As there is AFAIK no way to set the locale, they will always appear in
|
||||
US format.
|
||||
- Line editing and command recall doesn't work due to missing functionality in
|
||||
Wine.
|
||||
- File sizes in the DIR function are all given in 32 bits, though totals and
|
||||
free space are computed to 64 bits.
|
||||
- DIR/S fails if there is no matching file in the starting directory, ie
|
||||
"DIR C:\TEMP\*.c /S" doesn't work if there is no file matching *.c in C:\TEMP
|
||||
but one does exist in a lower directory.
|
||||
- Copy, rename, move, need the source and destination to be specified fully
|
||||
with an absolute or relative path but no wildcards or partial filenames.
|
||||
- Simple batch files work, ie a list of commands as they would be typed. However
|
||||
invoking a batch file from within another invokes the CALL function, control
|
||||
returns to the calling batch file when the subfile exits.
|
||||
|
||||
WINE OR WIN32 BINARY?
|
||||
Wcmd can be built as a Wine binary, or (using a Win32 compiler) as a Win32 .EXE
|
||||
image. The Wine binary is simpler to invoke from the U**x command line or from
|
||||
a GUI such as KDE, however it is not possible to invoke a second shell using the
|
||||
"WCMD /C filename" syntax. Conversely a Win32 application can be invoked from a
|
||||
Win32 GUI such as Program Manager but that needs starting under Wine first.
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* WCMD - Wine-compatible command line interface - batch interface.
|
||||
*
|
||||
* (C) 1999 D A Pickles
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "wcmd.h"
|
||||
|
||||
void WCMD_batch_command (HANDLE h, char *command);
|
||||
char *WCMD_parameter (char *s, int n);
|
||||
BOOL WCMD_go_to (HANDLE h, char *label);
|
||||
|
||||
extern HANDLE STDin, STDout;
|
||||
extern char nyi[];
|
||||
extern char newline[];
|
||||
extern char version_string[];
|
||||
extern int echo_mode;
|
||||
extern char quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH];
|
||||
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_batch
|
||||
*
|
||||
* Open and execute a batch file.
|
||||
* On entry *command includes the complete command line beginning with the name
|
||||
* of the batch file (if a CALL command was entered the CALL has been removed).
|
||||
* *file is the name of the file, which might not exist and may not have the
|
||||
* .BAT suffix on.
|
||||
*
|
||||
* We need to handle recursion correctly, since one batch program might call another.
|
||||
*/
|
||||
|
||||
void WCMD_batch (char *file, char *command) {
|
||||
|
||||
HANDLE h;
|
||||
char string[MAX_PATH];
|
||||
int n;
|
||||
|
||||
strcpy (string, file);
|
||||
CharLower (string);
|
||||
if (strstr (string, ".bat") == NULL) strcat (string, ".bat");
|
||||
h = CreateFile (string, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
WCMD_output ("File %s not found\n", string);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Work through the file line by line. Specific batch commands are processed here,
|
||||
* the rest are handled by the main command processor.
|
||||
*/
|
||||
|
||||
while (WCMD_fgets (string, sizeof(string), h)) {
|
||||
n = strlen (string);
|
||||
if (string[n-1] == '\n') string[n-1] = '\0';
|
||||
if (string[n-2] == '\r') string[n-2] = '\0'; /* Under Windoze we get CRLF! */
|
||||
WCMD_batch_command (h, string);
|
||||
}
|
||||
CloseHandle (h);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_batch_command
|
||||
*
|
||||
* Execute one line from a batch file.
|
||||
*/
|
||||
|
||||
void WCMD_batch_command (HANDLE h, char *command) {
|
||||
|
||||
DWORD status;
|
||||
char cmd[1024];
|
||||
|
||||
if (echo_mode && (command[0] != '@')) WCMD_output ("%s", command);
|
||||
status = ExpandEnvironmentStrings (command, cmd, sizeof(cmd));
|
||||
if (!status) {
|
||||
WCMD_print_error ();
|
||||
return;
|
||||
}
|
||||
WCMD_process_command (cmd);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_go_to
|
||||
*
|
||||
* Batch file jump instruction. Not the most efficient algorithm ;-)
|
||||
* Returns FALSE if the specified label cannot be found - the file pointer is
|
||||
* then at EOF.
|
||||
*/
|
||||
|
||||
BOOL WCMD_go_to (HANDLE h, char *label) {
|
||||
|
||||
char string[MAX_PATH];
|
||||
|
||||
SetFilePointer (h, 0, NULL, FILE_BEGIN);
|
||||
while (WCMD_fgets (string, sizeof(string), h)) {
|
||||
if ((string[0] == ':') && (strcmp (&string[1], label) == 0)) return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* WCMD_parameter - extract a parameter from a command line.
|
||||
*
|
||||
* Returns the 'n'th space-delimited parameter on the command line.
|
||||
* Parameter is in static storage overwritten on the next call.
|
||||
* Parameters in quotes are handled.
|
||||
*/
|
||||
|
||||
char *WCMD_parameter (char *s, int n) {
|
||||
|
||||
int i = -1;
|
||||
static char param[MAX_PATH];
|
||||
char *p;
|
||||
|
||||
p = param;
|
||||
while (TRUE) {
|
||||
switch (*s) {
|
||||
case ' ':
|
||||
s++;
|
||||
break;
|
||||
case '"':
|
||||
s++;
|
||||
while ((*s != '\0') && (*s != '"')) {
|
||||
*p++ = *s++;
|
||||
}
|
||||
if (i == n) {
|
||||
*p = '\0';
|
||||
return param;
|
||||
}
|
||||
else {
|
||||
param[0] = '\0';
|
||||
i++;
|
||||
}
|
||||
if (*s == '"') s++;
|
||||
break;
|
||||
case '\0':
|
||||
return param;
|
||||
default:
|
||||
while ((*s != '\0') && (*s != ' ')) {
|
||||
*p++ = *s++;
|
||||
}
|
||||
if (i == n) {
|
||||
*p = '\0';
|
||||
return param;
|
||||
}
|
||||
else {
|
||||
param[0] = '\0';
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_fgets
|
||||
*
|
||||
* Get one line from a batch file. We can't use the native f* functions because
|
||||
* of the filename syntax differences between DOS and Unix.
|
||||
*/
|
||||
|
||||
char *WCMD_fgets (char *s, int n, HANDLE h) {
|
||||
|
||||
DWORD bytes;
|
||||
BOOL status;
|
||||
char *p;
|
||||
|
||||
p = s;
|
||||
do {
|
||||
status = ReadFile (h, s, 1, &bytes, NULL);
|
||||
if ((status == 0) || (bytes == 0)) return NULL;
|
||||
if (*s == '\n') bytes = 0;
|
||||
*++s = '\0';
|
||||
n--;
|
||||
} while ((bytes == 1) && (n > 1));
|
||||
return p;
|
||||
}
|
|
@ -0,0 +1,645 @@
|
|||
/*
|
||||
* WCMD - Wine-compatible command line interface - built-in functions.
|
||||
*
|
||||
* (C) 1999 D A Pickles
|
||||
*
|
||||
* On entry to each function, global variables quals, param1, param2 contain
|
||||
* the qualifiers (uppercased and concatenated) and parameters entered, with
|
||||
* environment-variable and batch parameter substitution already done.
|
||||
*/
|
||||
|
||||
/*
|
||||
* FIXME:
|
||||
* - No support for redirection, pipes, batch files, shell parameters
|
||||
* - 32-bit limit on file sizes in DIR command
|
||||
* - Lots of functionality missing from builtins
|
||||
* - Messages etc need international support
|
||||
*/
|
||||
|
||||
#include "wcmd.h"
|
||||
|
||||
extern HANDLE STDin, STDout;
|
||||
extern HINSTANCE hinst;
|
||||
extern char *inbuilt[];
|
||||
extern char nyi[];
|
||||
extern char newline[];
|
||||
extern char version_string[];
|
||||
extern char anykey[];
|
||||
extern int echo_mode;
|
||||
extern char quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH];
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_call
|
||||
*
|
||||
* Call another batch file.
|
||||
*/
|
||||
|
||||
void WCMD_call () {
|
||||
|
||||
WCMD_output (nyi);
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_clear_screen
|
||||
*
|
||||
* Clear the terminal screen.
|
||||
*/
|
||||
|
||||
void WCMD_clear_screen () {
|
||||
|
||||
WCMD_output (nyi);
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_change_tty
|
||||
*
|
||||
* Change the default i/o device (ie redirect STDin/STDout).
|
||||
*/
|
||||
|
||||
void WCMD_change_tty () {
|
||||
|
||||
WCMD_output (nyi);
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_copy
|
||||
*
|
||||
* Copy a file or wildcarded set.
|
||||
* FIXME: No wildcard support
|
||||
* FIXME: Needs output file to be fully specified (can't just enter directory)
|
||||
*/
|
||||
|
||||
void WCMD_copy () {
|
||||
|
||||
DWORD count;
|
||||
WIN32_FIND_DATA fd;
|
||||
HANDLE hff;
|
||||
BOOL force, status;
|
||||
static char *overwrite = "Overwrite file (Y/N)?";
|
||||
char string[8], outpath[MAX_PATH];
|
||||
|
||||
if ((strchr(param1,'*') != NULL) && (strchr(param1,'%') != NULL)) {
|
||||
WCMD_output ("Wildcards not yet supported\n");
|
||||
return;
|
||||
}
|
||||
GetFullPathName (param2, sizeof(outpath), outpath, NULL);
|
||||
force = (strstr (quals, "/Y") != NULL);
|
||||
if (!force) {
|
||||
hff = FindFirstFile (outpath, &fd);
|
||||
if (hff != INVALID_HANDLE_VALUE) {
|
||||
FindClose (hff);
|
||||
WCMD_output (overwrite);
|
||||
ReadFile (STDin, string, sizeof(string), &count, NULL);
|
||||
if (toupper(string[0]) == 'Y') force = TRUE;
|
||||
}
|
||||
else force = TRUE;
|
||||
}
|
||||
if (force) {
|
||||
status = CopyFile (param1, outpath, FALSE);
|
||||
if (!status) WCMD_print_error ();
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_create_dir
|
||||
*
|
||||
* Create a directory.
|
||||
*/
|
||||
|
||||
void WCMD_create_dir () {
|
||||
|
||||
if (!CreateDirectory (param1, NULL)) WCMD_print_error ();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_delete
|
||||
*
|
||||
* Delete a file or wildcarded set.
|
||||
*
|
||||
*/
|
||||
|
||||
void WCMD_delete (int recurse) {
|
||||
|
||||
WIN32_FIND_DATA fd;
|
||||
HANDLE hff;
|
||||
char fpath[MAX_PATH];
|
||||
char *p;
|
||||
|
||||
hff = FindFirstFile (param1, &fd);
|
||||
if (hff == INVALID_HANDLE_VALUE) {
|
||||
WCMD_output ("File Not Found\n");
|
||||
return;
|
||||
}
|
||||
if ((strchr(param1,'*') == NULL) && (strchr(param1,'?') == NULL)
|
||||
&& (!recurse) && (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
strcat (param1, "\\*");
|
||||
WCMD_delete (1);
|
||||
return;
|
||||
}
|
||||
if ((strchr(param1,'*') != NULL) || (strchr(param1,'?') != NULL)) {
|
||||
strcpy (fpath, param1);
|
||||
do {
|
||||
p = strrchr (fpath, '\\');
|
||||
if (p != NULL) {
|
||||
*++p = '\0';
|
||||
strcat (fpath, fd.cFileName);
|
||||
}
|
||||
else strcpy (fpath, fd.cFileName);
|
||||
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
if (!DeleteFile (fpath)) WCMD_print_error ();
|
||||
}
|
||||
} while (FindNextFile(hff, &fd) != 0);
|
||||
FindClose (hff);
|
||||
}
|
||||
else {
|
||||
if (!DeleteFile (param1)) WCMD_print_error ();
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_echo
|
||||
*
|
||||
* Echo input to the screen (or not). We don't try to emulate the bugs
|
||||
* in DOS (try typing "ECHO ON AGAIN" for an example).
|
||||
*/
|
||||
|
||||
void WCMD_echo (char *command) {
|
||||
|
||||
static char *eon = "Echo is ON\n", *eoff = "Echo is OFF\n";
|
||||
int count;
|
||||
|
||||
count = strlen(command);
|
||||
if (count == 0) {
|
||||
if (echo_mode) WCMD_output (eon);
|
||||
else WCMD_output (eoff);
|
||||
return;
|
||||
}
|
||||
if ((count == 1) && (command[0] == '.')) {
|
||||
WCMD_output (newline);
|
||||
return;
|
||||
}
|
||||
if (lstrcmpi(command, "ON") == 0) {
|
||||
echo_mode = 1;
|
||||
return;
|
||||
}
|
||||
if (lstrcmpi(command, "OFF") == 0) {
|
||||
echo_mode = 0;
|
||||
return;
|
||||
}
|
||||
WCMD_output (command);
|
||||
WCMD_output (newline);
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_for
|
||||
*
|
||||
* Batch file loop processing.
|
||||
*/
|
||||
|
||||
void WCMD_for () {
|
||||
|
||||
WCMD_output (nyi);
|
||||
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* WCMD_give_help
|
||||
*
|
||||
* Simple on-line help. Help text is stored in the resource file.
|
||||
*/
|
||||
|
||||
void WCMD_give_help (char *command) {
|
||||
|
||||
int i;
|
||||
char buffer[2048];
|
||||
|
||||
command = WCMD_strtrim_leading_spaces(command);
|
||||
if (lstrlen(command) == 0) {
|
||||
LoadString (hinst, 1000, buffer, sizeof(buffer));
|
||||
WCMD_output (buffer);
|
||||
}
|
||||
else {
|
||||
for (i=0; i<=WCMD_EXIT; i++) {
|
||||
if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
|
||||
param1, -1, inbuilt[i], -1) == 2) {
|
||||
LoadString (hinst, i, buffer, sizeof(buffer));
|
||||
WCMD_output (buffer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
WCMD_output ("No help available for %s\n", param1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_if
|
||||
*
|
||||
* Batch file conditional.
|
||||
*/
|
||||
|
||||
void WCMD_if () {
|
||||
|
||||
WCMD_output (nyi);
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_move
|
||||
*
|
||||
* Move a file, directory tree or wildcarded set of files.
|
||||
*/
|
||||
|
||||
void WCMD_move () {
|
||||
|
||||
WCMD_output (nyi);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_pause
|
||||
*
|
||||
* Wait for keyboard input.
|
||||
*/
|
||||
|
||||
void WCMD_pause () {
|
||||
|
||||
DWORD count;
|
||||
char string[32];
|
||||
|
||||
WCMD_output (anykey);
|
||||
ReadFile (STDin, string, sizeof(string), &count, NULL);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_remove_dir
|
||||
*
|
||||
* Delete a directory.
|
||||
*/
|
||||
|
||||
void WCMD_remove_dir () {
|
||||
|
||||
if (!RemoveDirectory (param1)) WCMD_print_error ();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_rename
|
||||
*
|
||||
* Rename a file.
|
||||
* FIXME: Needs input and output files to be fully specified.
|
||||
*/
|
||||
|
||||
void WCMD_rename () {
|
||||
|
||||
int status;
|
||||
static char *dirmsg = "Input file is a directory. Use the MOVE command\n\n";
|
||||
|
||||
if ((strchr(param1,'*') != NULL) || (strchr(param1,'%') != NULL)) {
|
||||
WCMD_output ("Wildcards not yet supported\n");
|
||||
return;
|
||||
}
|
||||
status = GetFileAttributes (param1);
|
||||
if ((status != -1) && (status & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
WCMD_output (dirmsg);
|
||||
return;
|
||||
}
|
||||
status = MoveFile (param1, param2);
|
||||
if (!status) WCMD_print_error ();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* WCMD_setshow_attrib
|
||||
*
|
||||
* Display and optionally sets DOS attributes on a file or directory
|
||||
*
|
||||
* FIXME: Wine currently uses the Unix stat() function to get file attributes.
|
||||
* As a result only the Readonly flag is correctly reported, the Archive bit
|
||||
* is always set and the rest are not implemented. We do the Right Thing anyway.
|
||||
*
|
||||
*/
|
||||
|
||||
void WCMD_setshow_attrib () {
|
||||
|
||||
DWORD count;
|
||||
HANDLE hff;
|
||||
WIN32_FIND_DATA fd;
|
||||
char flags[9] = {" "};
|
||||
|
||||
if (lstrlen(param1) == 0) {
|
||||
GetCurrentDirectory (sizeof(param1), param1);
|
||||
strcat (param1, "\\*");
|
||||
}
|
||||
|
||||
hff = FindFirstFile (param1, &fd);
|
||||
if (hff == INVALID_HANDLE_VALUE) {
|
||||
WCMD_output ("File Not Found\n");
|
||||
}
|
||||
else {
|
||||
do {
|
||||
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
if (fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {
|
||||
flags[0] = 'H';
|
||||
}
|
||||
if (fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) {
|
||||
flags[1] = 'S';
|
||||
}
|
||||
if (fd.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) {
|
||||
flags[2] = 'A';
|
||||
}
|
||||
if (fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
|
||||
flags[3] = 'R';
|
||||
}
|
||||
if (fd.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) {
|
||||
flags[4] = 'T';
|
||||
}
|
||||
if (fd.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) {
|
||||
flags[5] = 'C';
|
||||
}
|
||||
WCMD_output ("%s %s\n", flags, fd.cFileName);
|
||||
for (count=0; count < 8; count++) flags[count] = ' ';
|
||||
}
|
||||
} while (FindNextFile(hff, &fd) != 0);
|
||||
}
|
||||
FindClose (hff);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* WCMD_setshow_default
|
||||
*
|
||||
* Set/Show the current default directory
|
||||
*/
|
||||
|
||||
void WCMD_setshow_default () {
|
||||
|
||||
BOOL status;
|
||||
char string[1024];
|
||||
|
||||
if (strlen(param1) == 0) {
|
||||
GetCurrentDirectory (sizeof(string), string);
|
||||
strcat (string, "\n");
|
||||
WCMD_output (string);
|
||||
}
|
||||
else {
|
||||
status = SetCurrentDirectory (param1);
|
||||
if (!status) {
|
||||
WCMD_print_error ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_setshow_date
|
||||
*
|
||||
* Set/Show the system date
|
||||
* FIXME: Can't change date yet
|
||||
*/
|
||||
|
||||
void WCMD_setshow_date () {
|
||||
|
||||
char curdate[64], buffer[64];
|
||||
DWORD count;
|
||||
|
||||
if (lstrlen(param1) == 0) {
|
||||
if (GetDateFormat (LOCALE_USER_DEFAULT, 0, NULL, NULL,
|
||||
curdate, sizeof(curdate))) {
|
||||
WCMD_output ("Current Date is %s\nEnter new date: ", curdate);
|
||||
ReadFile (STDin, buffer, sizeof(buffer), &count, NULL);
|
||||
if (count > 2) {
|
||||
WCMD_output (nyi);
|
||||
}
|
||||
}
|
||||
else WCMD_print_error ();
|
||||
}
|
||||
else {
|
||||
WCMD_output (nyi);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_setshow_env
|
||||
*
|
||||
* Set/Show the environment variables
|
||||
*
|
||||
* FIXME: need to sort variables into order for display?
|
||||
*/
|
||||
|
||||
void WCMD_setshow_env (char *s) {
|
||||
|
||||
LPVOID env;
|
||||
char *p;
|
||||
int status;
|
||||
|
||||
if (strlen(param1) == 0) {
|
||||
env = GetEnvironmentStrings ();
|
||||
p = (char *) env;
|
||||
while (*p) {
|
||||
WCMD_output ("%s\n", p);
|
||||
p += lstrlen(p) + 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
p = strchr (s, '=');
|
||||
if (p == NULL) {
|
||||
WCMD_output ("Command Syntax: SET variable=value\n");
|
||||
return;
|
||||
}
|
||||
*p++ = '\0';
|
||||
status = SetEnvironmentVariable (s, p);
|
||||
if (!status) WCMD_print_error();
|
||||
}
|
||||
WCMD_output (newline);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_setshow_path
|
||||
*
|
||||
* Set/Show the path environment variable
|
||||
*/
|
||||
|
||||
void WCMD_setshow_path () {
|
||||
|
||||
char string[1024];
|
||||
DWORD status;
|
||||
|
||||
if (strlen(param1) == 0) {
|
||||
status = GetEnvironmentVariable ("PATH", string, sizeof(string));
|
||||
if (status != 0) {
|
||||
WCMD_output ("PATH=%s\n", string);
|
||||
}
|
||||
else {
|
||||
WCMD_output ("PATH not found\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
status = SetEnvironmentVariable ("PATH", param1);
|
||||
if (!status) WCMD_print_error();
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_setshow_prompt
|
||||
*
|
||||
* Set or show the command prompt.
|
||||
*/
|
||||
|
||||
void WCMD_setshow_prompt () {
|
||||
|
||||
char *s;
|
||||
|
||||
if (strlen(param1) == 0) {
|
||||
SetEnvironmentVariable ("PROMPT", NULL);
|
||||
}
|
||||
else {
|
||||
s = param1;
|
||||
while ((*s == '=') || (*s == ' ')) s++;
|
||||
if (strlen(s) == 0) {
|
||||
SetEnvironmentVariable ("PROMPT", NULL);
|
||||
}
|
||||
else SetEnvironmentVariable ("PROMPT", s);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_setshow_time
|
||||
*
|
||||
* Set/Show the system time
|
||||
* FIXME: Can't change time yet
|
||||
*/
|
||||
|
||||
void WCMD_setshow_time () {
|
||||
|
||||
char curtime[64], buffer[64];
|
||||
DWORD count;
|
||||
|
||||
if (strlen(param1) == 0) {
|
||||
if (GetTimeFormat (LOCALE_USER_DEFAULT, 0, NULL, NULL,
|
||||
curtime, sizeof(curtime))) {
|
||||
WCMD_output ("Current Time is %s\nEnter new time: ", curtime);
|
||||
ReadFile (STDin, buffer, sizeof(buffer), &count, NULL);
|
||||
if (count > 2) {
|
||||
WCMD_output (nyi);
|
||||
}
|
||||
}
|
||||
else WCMD_print_error ();
|
||||
}
|
||||
else {
|
||||
WCMD_output (nyi);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_shift
|
||||
*
|
||||
* Shift batch parameters.
|
||||
*/
|
||||
|
||||
void WCMD_shift () {
|
||||
|
||||
WCMD_output (nyi);
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_type
|
||||
*
|
||||
* Copy a file to standard output.
|
||||
*/
|
||||
|
||||
void WCMD_type () {
|
||||
|
||||
HANDLE h;
|
||||
char buffer[512];
|
||||
DWORD count;
|
||||
|
||||
h = CreateFile (param1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
WCMD_print_error ();
|
||||
return;
|
||||
}
|
||||
while (ReadFile (h, buffer, sizeof(buffer), &count, NULL)) {
|
||||
if (count == 0) break; /* ReadFile reports success on EOF! */
|
||||
WriteFile (STDout, buffer, count, &count, NULL);
|
||||
}
|
||||
CloseHandle (h);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_verify
|
||||
*
|
||||
* Display verify flag.
|
||||
*/
|
||||
|
||||
void WCMD_verify () {
|
||||
|
||||
WCMD_output (nyi);
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_version
|
||||
*
|
||||
* Display version info.
|
||||
*/
|
||||
|
||||
void WCMD_version () {
|
||||
|
||||
WCMD_output (version_string);
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_volume
|
||||
*
|
||||
* Display volume info and/or set volume label. Returns 0 if error.
|
||||
*/
|
||||
|
||||
int WCMD_volume (int mode, char *path) {
|
||||
|
||||
DWORD count, serial;
|
||||
char string[MAX_PATH], label[MAX_PATH], curdir[MAX_PATH];
|
||||
BOOL status;
|
||||
static char syntax[] = "Syntax Error\n\n";
|
||||
|
||||
if (lstrlen(path) == 0) {
|
||||
status = GetCurrentDirectory (sizeof(curdir), curdir);
|
||||
if (!status) {
|
||||
WCMD_print_error ();
|
||||
return 0;
|
||||
}
|
||||
status = GetVolumeInformation (NULL, label, sizeof(label), &serial, NULL,
|
||||
NULL, NULL, 0);
|
||||
}
|
||||
else {
|
||||
if ((path[1] != ':') || (lstrlen(path) != 2)) {
|
||||
WriteFile (STDout, syntax, strlen(syntax), &count, NULL);
|
||||
return 0;
|
||||
}
|
||||
wsprintf (curdir, "%s\\", path);
|
||||
status = GetVolumeInformation (curdir, label, sizeof(label), &serial, NULL,
|
||||
NULL, NULL, 0);
|
||||
}
|
||||
if (!status) {
|
||||
WCMD_print_error ();
|
||||
return 0;
|
||||
}
|
||||
WCMD_output ("Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n",
|
||||
curdir[0], label, HIWORD(serial), LOWORD(serial));
|
||||
if (mode) {
|
||||
WCMD_output ("Volume label (11 characters, ENTER for none)?");
|
||||
ReadFile (STDin, string, sizeof(string), &count, NULL);
|
||||
if (lstrlen(path) != 0) {
|
||||
if (!SetVolumeLabel (curdir, string)) WCMD_print_error ();
|
||||
}
|
||||
else {
|
||||
if (!SetVolumeLabel (NULL, string)) WCMD_print_error ();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,301 @@
|
|||
/*
|
||||
* WCMD - Wine-compatible command line interface - Directory functions.
|
||||
*
|
||||
* (C) 1999 D A Pickles
|
||||
*
|
||||
* On entry, global variables quals, param1, param2 contain
|
||||
* the qualifiers (uppercased and concatenated) and parameters entered, with
|
||||
* environment-variable and batch parameter substitution already done.
|
||||
*/
|
||||
|
||||
/*
|
||||
* FIXME:
|
||||
* - 32-bit limit on individual file sizes (directories and free space are 64-bit)
|
||||
* - DIR /S fails if the starting directory is not the current default.
|
||||
*/
|
||||
|
||||
#include "wcmd.h"
|
||||
|
||||
int WCMD_dir_sort (const void *a, const void *b);
|
||||
void WCMD_list_directory (char *path, int level);
|
||||
char * WCMD_filesize64 (__int64 n);
|
||||
char * WCMD_filesize32 (int n);
|
||||
char * WCMD_strrev (char *buff);
|
||||
|
||||
|
||||
extern HANDLE STDin, STDout;
|
||||
extern char nyi[];
|
||||
extern char newline[];
|
||||
extern char version_string[];
|
||||
extern char anykey[];
|
||||
extern int echo_mode;
|
||||
extern char quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH];
|
||||
|
||||
int file_total, dir_total, line_count, page_mode, recurse;
|
||||
__int64 byte_total;
|
||||
|
||||
/*****************************************************************************
|
||||
* WCMD_directory
|
||||
*
|
||||
* List a file directory.
|
||||
* FIXME: /S switch only works for the current directory
|
||||
*
|
||||
*/
|
||||
|
||||
void WCMD_directory () {
|
||||
|
||||
char path[MAX_PATH], drive[8];
|
||||
int status;
|
||||
__int64 free_space;
|
||||
DWORD spc, bps, fc, capacity;
|
||||
|
||||
line_count = 5;
|
||||
page_mode = (strstr(quals, "/P") != NULL);
|
||||
recurse = (strstr(quals, "/S") != NULL);
|
||||
if (param1[0] == '\0') strcpy (param1, ".");
|
||||
GetFullPathName (param1, sizeof(path), path, NULL);
|
||||
lstrcpyn (drive, path, 3);
|
||||
status = WCMD_volume (0, drive);
|
||||
if (!status) {
|
||||
return;
|
||||
}
|
||||
WCMD_list_directory (path, 0);
|
||||
lstrcpyn (drive, path, 4);
|
||||
GetDiskFreeSpace (drive, &spc, &bps, &fc, &capacity);
|
||||
free_space = bps * spc * fc;
|
||||
WCMD_output (" %18s bytes free\n\n", WCMD_filesize64 (free_space));
|
||||
if (recurse) {
|
||||
WCMD_output ("Total files listed:\n%8d files%25s bytes\n%8d directories\n\n",
|
||||
file_total, WCMD_filesize64 (byte_total), dir_total);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* WCMD_list_directory
|
||||
*
|
||||
* List a single file directory. This function (and those below it) can be called
|
||||
* recursively when the /S switch is used.
|
||||
*
|
||||
* FIXME: Assumes individual files are less than 2**32 bytes.
|
||||
* FIXME: Entries sorted by name only. Should we support DIRCMD??
|
||||
* FIXME: Assumes 24-line display for the /P qualifier.
|
||||
* FIXME: Other command qualifiers not supported.
|
||||
* FIXME: DIR /S FILENAME fails if at least one matching file is not found in the top level.
|
||||
*/
|
||||
|
||||
void WCMD_list_directory (char *search_path, int level) {
|
||||
|
||||
char string[1024], datestring[32], timestring[32];
|
||||
char mem_err[] = "Memory Allocation Error";
|
||||
char *p;
|
||||
DWORD count;
|
||||
WIN32_FIND_DATA *fd;
|
||||
FILETIME ft;
|
||||
SYSTEMTIME st;
|
||||
HANDLE hff;
|
||||
int status, dir_count, file_count, entry_count, i;
|
||||
__int64 byte_count;
|
||||
|
||||
dir_count = 0;
|
||||
file_count = 0;
|
||||
entry_count = 0;
|
||||
byte_count = 0;
|
||||
|
||||
/*
|
||||
* If the path supplied does not include a wildcard, and the endpoint of the
|
||||
* path references a directory, we need to list the *contents* of that
|
||||
* directory not the directory file itself.
|
||||
*/
|
||||
|
||||
if ((strchr(search_path, '*') == NULL) && (strchr(search_path, '%') == NULL)) {
|
||||
status = GetFileAttributes (search_path);
|
||||
if ((status != -1) && (status & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
if (search_path[strlen(search_path)-1] == '\\') {
|
||||
strcat (search_path, "*");
|
||||
}
|
||||
else {
|
||||
strcat (search_path, "\\*");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fd = malloc (sizeof(WIN32_FIND_DATA));
|
||||
hff = FindFirstFile (search_path, fd);
|
||||
if (hff == INVALID_HANDLE_VALUE) {
|
||||
WCMD_output ("File Not Found\n");
|
||||
free (fd);
|
||||
return;
|
||||
}
|
||||
do {
|
||||
entry_count++;
|
||||
fd = realloc (fd, (entry_count+1)*sizeof(WIN32_FIND_DATA));
|
||||
if (fd == NULL) {
|
||||
FindClose (hff);
|
||||
WCMD_output (mem_err);
|
||||
return;
|
||||
}
|
||||
} while (FindNextFile(hff, (fd+entry_count)) != 0);
|
||||
FindClose (hff);
|
||||
qsort (fd, entry_count, sizeof(WIN32_FIND_DATA), WCMD_dir_sort);
|
||||
if (level != 0) WCMD_output ("\n\n");
|
||||
WCMD_output ("Directory of %s\n\n", search_path);
|
||||
if (page_mode) {
|
||||
line_count += 2;
|
||||
if (line_count > 23) {
|
||||
line_count = 0;
|
||||
WCMD_output (anykey);
|
||||
ReadFile (STDin, string, sizeof(string), &count, NULL);
|
||||
}
|
||||
}
|
||||
for (i=0; i<entry_count; i++) {
|
||||
FileTimeToLocalFileTime (&(fd+i)->ftLastWriteTime, &ft);
|
||||
FileTimeToSystemTime (&ft, &st);
|
||||
GetDateFormat (0, DATE_SHORTDATE, &st, NULL, datestring,
|
||||
sizeof(datestring));
|
||||
GetTimeFormat (0, TIME_NOSECONDS, &st,
|
||||
NULL, timestring, sizeof(timestring));
|
||||
if ((fd+i)->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
dir_count++;
|
||||
WCMD_output ("%8s %8s <DIR> %s\n",
|
||||
datestring, timestring, (fd+i)->cFileName);
|
||||
}
|
||||
else {
|
||||
file_count++;
|
||||
byte_count += (fd+i)->nFileSizeLow;
|
||||
WCMD_output ("%8s %8s %10s %s\n",
|
||||
datestring, timestring,
|
||||
WCMD_filesize32((fd+i)->nFileSizeLow), (fd+i)->cFileName);
|
||||
}
|
||||
if (page_mode) {
|
||||
if (++line_count > 23) {
|
||||
line_count = 0;
|
||||
WCMD_output (anykey);
|
||||
ReadFile (STDin, string, sizeof(string), &count, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (file_count == 1) {
|
||||
WCMD_output (" 1 file %25s bytes\n", WCMD_filesize64 (byte_count));
|
||||
}
|
||||
else {
|
||||
WCMD_output ("%8d files %24s bytes\n", file_count, WCMD_filesize64 (byte_count));
|
||||
}
|
||||
if (page_mode) {
|
||||
if (++line_count > 23) {
|
||||
line_count = 0;
|
||||
WCMD_output (anykey);
|
||||
ReadFile (STDin, string, sizeof(string), &count, NULL);
|
||||
}
|
||||
}
|
||||
byte_total = byte_total + byte_count;
|
||||
file_total = file_total + file_count;
|
||||
dir_total = dir_total + dir_count;
|
||||
if (dir_count == 1) WCMD_output ("1 directory ");
|
||||
else WCMD_output ("%8d directories", dir_count);
|
||||
if (page_mode) {
|
||||
if (++line_count > 23) {
|
||||
line_count = 0;
|
||||
WCMD_output (anykey);
|
||||
ReadFile (STDin, string, sizeof(string), &count, NULL);
|
||||
}
|
||||
}
|
||||
for (i=0; i<entry_count; i++) {
|
||||
if ((recurse) &&
|
||||
((fd+i)->cFileName[0] != '.') &&
|
||||
((fd+i)->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
// GetFullPathName ((fd+i)->cFileName, sizeof(string), string, NULL);
|
||||
p = strrchr (search_path, '\\');
|
||||
lstrcpyn (string, search_path, (p-search_path+2));
|
||||
lstrcat (string, (fd+i)->cFileName);
|
||||
lstrcat (string, p);
|
||||
WCMD_list_directory (string, 1);
|
||||
}
|
||||
}
|
||||
free (fd);
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* WCMD_filesize64
|
||||
*
|
||||
* Convert a 64-bit number into a character string, with commas every three digits.
|
||||
* Result is returned in a static string overwritten with each call.
|
||||
* FIXME: There must be a better algorithm!
|
||||
*/
|
||||
|
||||
char * WCMD_filesize64 (__int64 n) {
|
||||
|
||||
__int64 q;
|
||||
int r, i;
|
||||
char *p;
|
||||
static char buff[32];
|
||||
|
||||
p = buff;
|
||||
i = -3;
|
||||
do {
|
||||
if ((++i)%3 == 1) *p++ = ',';
|
||||
q = n / 10;
|
||||
r = n - (q * 10);
|
||||
*p++ = r + '0';
|
||||
*p = '\0';
|
||||
n = q;
|
||||
} while (n != 0);
|
||||
WCMD_strrev (buff);
|
||||
return buff;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* WCMD_filesize32
|
||||
*
|
||||
* Convert a 32-bit number into a character string, with commas every three digits.
|
||||
* Result is returned in a static string overwritten with each call.
|
||||
* FIXME: There must be a better algorithm!
|
||||
*/
|
||||
|
||||
char * WCMD_filesize32 (int n) {
|
||||
|
||||
int r, i;
|
||||
char *p, *q;
|
||||
static char buff1[16], buff2[16];
|
||||
|
||||
wsprintf (buff1, "%i", n);
|
||||
r = lstrlen (buff1);
|
||||
WCMD_strrev (buff1);
|
||||
p = buff1;
|
||||
q = buff2;
|
||||
for (i=0; i<r; i++) {
|
||||
if ((i-2)%3 == 1) *q++ = ',';
|
||||
*q++ = *p++;
|
||||
}
|
||||
*q = '\0';
|
||||
WCMD_strrev (buff2);
|
||||
return buff2;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* WCMD_strrev
|
||||
*
|
||||
* Reverse a character string in-place (strrev() is not available under unixen :-( ).
|
||||
*/
|
||||
|
||||
char * WCMD_strrev (char *buff) {
|
||||
|
||||
int r, i;
|
||||
char b;
|
||||
|
||||
r = lstrlen (buff);
|
||||
for (i=0; i<r/2; i++) {
|
||||
b = buff[i];
|
||||
buff[i] = buff[r-i-1];
|
||||
buff[r-i-1] = b;
|
||||
}
|
||||
return (buff);
|
||||
}
|
||||
|
||||
|
||||
int WCMD_dir_sort (const void *a, const void *b) {
|
||||
|
||||
return (lstrcmpi(((WIN32_FIND_DATA *)a)->cFileName,
|
||||
((WIN32_FIND_DATA *)b)->cFileName));
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
#-----------------------------------------------------------------------------
|
||||
VERSION = BCB.01
|
||||
#-----------------------------------------------------------------------------
|
||||
!ifndef BCB
|
||||
BCB = $(MAKEDIR)\..
|
||||
!endif
|
||||
PROJECT = wcmd.exe
|
||||
OBJFILES = builtins.obj wcmdmain.obj directory.obj batch.obj
|
||||
RESFILES = wcmdrc.rc
|
||||
RESDEPEN = $(RESFILES)
|
||||
LIBFILES =
|
||||
DEFFILE =
|
||||
#-----------------------------------------------------------------------------
|
||||
CFLAG1 = -c
|
||||
CFLAG2 = -H=C:\BC\PROJECTS\CMD.CSM -nC:\BC\PROJECTS\CMD \
|
||||
-IC:\BC\INCLUDE;C:\BC\PROJECTS\CMD
|
||||
PFLAGS = -U$(BCB)\lib\obj -jph -m
|
||||
RFLAGS = -I$(BCB)\include;C:\BC\INCLUDE;C:\BC\PROJECTS\CMD
|
||||
LFLAGS = -ap -Tpe -c -x -L$(BCB)\lib;$(BCB)\lib\obj;C:\BC\LIB
|
||||
IFLAGS = -i
|
||||
LINKER = tlink32
|
||||
#-----------------------------------------------------------------------------
|
||||
ALLOBJ = c0x32.obj $(OBJFILES)
|
||||
ALLRES = $(RESFILES)
|
||||
ALLLIB = $(LIBFILES) noeh32.lib import32.lib cw32mt.lib
|
||||
# ---------------------------------------------------------------------------
|
||||
.autodepend
|
||||
|
||||
$(PROJECT): $(OBJFILES) $(RESDEPEN) $(DEFFILE)
|
||||
$(BCB)\BIN\$(LINKER) @&&!
|
||||
$(LFLAGS) +
|
||||
$(ALLOBJ), +
|
||||
$(PROJECT),, +
|
||||
$(ALLLIB), +
|
||||
$(DEFFILE), +
|
||||
$(ALLRES)
|
||||
!
|
||||
|
||||
.cpp.obj:
|
||||
$(BCB)\BIN\bcc32 $(CFLAG1) $(CFLAG2) -o$* $*
|
||||
|
||||
.c.obj:
|
||||
$(BCB)\BIN\bcc32 $(CFLAG1) $(CFLAG2) -o$* $**
|
||||
|
||||
.rc.res:
|
||||
$(BCB)\BIN\brcc32 $(RFLAGS) $<
|
||||
#-----------------------------------------------------------------------------
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* WCMD - Wine-compatible command line interface.
|
||||
*
|
||||
* (C) 1999 D A Pickles
|
||||
*/
|
||||
|
||||
|
||||
#define IDI_ICON1 1
|
||||
#include <windows.h>
|
||||
#ifndef RC_INVOKED
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef WINELIB
|
||||
#include <winbase.h>
|
||||
#include <wincon.h>
|
||||
#endif /* !WINELIB */
|
||||
|
||||
void WCMD_batch (char *, char *);
|
||||
void WCMD_call (void);
|
||||
void WCMD_change_tty (void);
|
||||
void WCMD_clear_screen (void);
|
||||
void WCMD_copy (void);
|
||||
void WCMD_create_dir (void);
|
||||
void WCMD_delete (int recurse);
|
||||
void WCMD_directory (void);
|
||||
void WCMD_echo (char *);
|
||||
void WCMD_for (void);
|
||||
void WCMD_give_help (char *command);
|
||||
void WCMD_if (void);
|
||||
void WCMD_move (void);
|
||||
void WCMD_output (char *format, ...);
|
||||
void WCMD_parse (char *s, char *q, char *p1, char *p2);
|
||||
void WCMD_pause (void);
|
||||
void WCMD_print_error (void);
|
||||
void WCMD_process_command (char *command);
|
||||
void WCMD_remove_dir (void);
|
||||
void WCMD_rename (void);
|
||||
void WCMD_run_program (char *command);
|
||||
void WCMD_setshow_attrib (void);
|
||||
void WCMD_setshow_date (void);
|
||||
void WCMD_setshow_default (void);
|
||||
void WCMD_setshow_env (char *command);
|
||||
void WCMD_setshow_path (void);
|
||||
void WCMD_setshow_prompt (void);
|
||||
void WCMD_setshow_time (void);
|
||||
void WCMD_shift (void);
|
||||
void WCMD_show_prompt (void);
|
||||
void WCMD_type (void);
|
||||
void WCMD_verify (void);
|
||||
void WCMD_version (void);
|
||||
int WCMD_volume (int mode, char *command);
|
||||
|
||||
char *WCMD_fgets (char *s, int n, HANDLE stream);
|
||||
char *WCMD_strtrim_leading_spaces (char *string);
|
||||
void WCMD_strtrim_trailing_spaces (char *string);
|
||||
#endif /* !RC_INVOKED */
|
||||
|
||||
/*
|
||||
* Serial nos of builtin commands. These constants must be in step with
|
||||
* the list of strings defined in WCMD.C, and WCMD_EXIT *must* always be
|
||||
* the last one.
|
||||
*
|
||||
* Yes it *would* be nice to use an enumeration here, but the Resource
|
||||
* Compiler won't accept resource IDs from enumerations :-(
|
||||
*/
|
||||
|
||||
#define WCMD_ATTRIB 0
|
||||
#define WCMD_CALL 1
|
||||
#define WCMD_CD 2
|
||||
#define WCMD_CHDIR 3
|
||||
#define WCMD_CLS 4
|
||||
#define WCMD_COPY 5
|
||||
#define WCMD_CTTY 6
|
||||
#define WCMD_DATE 7
|
||||
#define WCMD_DEL 8
|
||||
#define WCMD_DIR 9
|
||||
#define WCMD_ECHO 10
|
||||
#define WCMD_ERASE 11
|
||||
#define WCMD_FOR 12
|
||||
#define WCMD_GOTO 13
|
||||
#define WCMD_HELP 14
|
||||
#define WCMD_IF 15
|
||||
#define WCMD_LABEL 16
|
||||
#define WCMD_MD 17
|
||||
#define WCMD_MKDIR 18
|
||||
#define WCMD_MOVE 19
|
||||
#define WCMD_PATH 20
|
||||
#define WCMD_PAUSE 21
|
||||
#define WCMD_PROMPT 22
|
||||
#define WCMD_REM 23
|
||||
#define WCMD_REN 24
|
||||
#define WCMD_RENAME 25
|
||||
#define WCMD_RD 26
|
||||
#define WCMD_RMDIR 27
|
||||
#define WCMD_SET 28
|
||||
#define WCMD_SHIFT 29
|
||||
#define WCMD_TIME 30
|
||||
#define WCMD_TYPE 31
|
||||
#define WCMD_VERIFY 32
|
||||
#define WCMD_VER 33
|
||||
#define WCMD_VOL 34
|
||||
#define WCMD_EXIT 35
|
||||
|
||||
|
|
@ -0,0 +1,556 @@
|
|||
/*
|
||||
* WCMD - Wine-compatible command line interface.
|
||||
*
|
||||
* (C) 1999 D A Pickles
|
||||
*/
|
||||
|
||||
/*
|
||||
* FIXME:
|
||||
* - No support for redirection, pipes, batch commands
|
||||
* - 32-bit limit on file sizes in DIR command
|
||||
* - Cannot handle parameters in quotes
|
||||
* - Lots of functionality missing from builtins
|
||||
*/
|
||||
|
||||
#include "wcmd.h"
|
||||
|
||||
#ifdef WINELIB
|
||||
/* external declaration here because we don't want to depend on Wine headers */
|
||||
#ifdef __cplusplus
|
||||
extern "C" HINSTANCE MAIN_WinelibInit( int *argc, char *argv[] );
|
||||
#else
|
||||
extern HINSTANCE MAIN_WinelibInit( int *argc, char *argv[] );
|
||||
#endif
|
||||
#endif /* WINELIB */
|
||||
|
||||
char *inbuilt[] = {"ATTRIB", "CALL", "CD", "CHDIR", "CLS", "COPY", "CTTY",
|
||||
"DATE", "DEL", "DIR", "ECHO", "ERASE", "FOR", "GOTO",
|
||||
"HELP", "IF", "LABEL", "MD", "MKDIR", "MOVE", "PATH", "PAUSE",
|
||||
"PROMPT", "REM", "REN", "RENAME", "RD", "RMDIR", "SET", "SHIFT",
|
||||
"TIME", "TYPE", "VERIFY", "VER", "VOL", "EXIT"};
|
||||
|
||||
HANDLE STDin, STDout;
|
||||
HINSTANCE hinst;
|
||||
int echo_mode = 1;
|
||||
char nyi[] = "Not Yet Implemented\n\n";
|
||||
char newline[] = "\n";
|
||||
char version_string[] = "WCMD Version 0.10\n\n";
|
||||
char anykey[] = "Press any key to continue: ";
|
||||
char quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH];
|
||||
|
||||
/*****************************************************************************
|
||||
* Main entry point. This is a console application so we have a main() not a
|
||||
* winmain().
|
||||
*/
|
||||
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
|
||||
char string[1024], args[MAX_PATH], param[MAX_PATH];
|
||||
int status, i;
|
||||
DWORD count;
|
||||
HANDLE h;
|
||||
|
||||
#ifdef WINELIB
|
||||
if (!(hinst = MAIN_WinelibInit( &argc, argv ))) return 0;
|
||||
#else
|
||||
hinst = 0;
|
||||
#endif
|
||||
|
||||
args[0] = param[0] = '\0';
|
||||
if (argc > 1) {
|
||||
for (i=1; i<argc; i++) {
|
||||
if (argv[i][0] == '/') {
|
||||
strcat (args, argv[i]);
|
||||
}
|
||||
else {
|
||||
strcat (param, argv[i]);
|
||||
strcat (param, " ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a console and set it up.
|
||||
*/
|
||||
|
||||
status = FreeConsole ();
|
||||
if (!status) WCMD_print_error();
|
||||
status = AllocConsole();
|
||||
if (!status) WCMD_print_error();
|
||||
STDout = GetStdHandle (STD_OUTPUT_HANDLE);
|
||||
STDin = GetStdHandle (STD_INPUT_HANDLE);
|
||||
SetConsoleMode (STDin, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT |
|
||||
ENABLE_PROCESSED_INPUT);
|
||||
|
||||
/*
|
||||
* Execute any command-line options.
|
||||
*/
|
||||
|
||||
if (strstr(args, "/q") != NULL) {
|
||||
WCMD_echo ("OFF");
|
||||
}
|
||||
|
||||
if (strstr(args, "/c") != NULL) {
|
||||
WCMD_process_command (param);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strstr(args, "/k") != NULL) {
|
||||
WCMD_process_command (param);
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is an AUTOEXEC.BAT file, try to execute it.
|
||||
*/
|
||||
|
||||
GetFullPathName ("\\autoexec.bat", sizeof(string), string, NULL);
|
||||
h = CreateFile (string, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if (h != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle (h);
|
||||
// WCMD_batch (string, " ");
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop forever getting commands and executing them.
|
||||
*/
|
||||
|
||||
WCMD_version ();
|
||||
while (TRUE) {
|
||||
WCMD_show_prompt ();
|
||||
ReadFile (STDin, string, sizeof(string), &count, NULL);
|
||||
if (count > 1) {
|
||||
string[count-1] = '\0'; /* ReadFile output is not null-terminated! */
|
||||
if (string[count-2] == '\r') string[count-2] = '\0'; /* Under Windoze we get CRLF! */
|
||||
if (lstrlen (string) != 0) {
|
||||
WCMD_process_command (string);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Process one command. If the command is EXIT this routine does not return.
|
||||
* We will recurse through here executing batch files.
|
||||
*/
|
||||
|
||||
|
||||
void WCMD_process_command (char *command) {
|
||||
|
||||
char cmd[1024];
|
||||
char *p;
|
||||
int status, i;
|
||||
DWORD count;
|
||||
|
||||
/*
|
||||
* Throw away constructs we don't support yet
|
||||
*/
|
||||
|
||||
if ((strchr(command,'<') != NULL) || (strchr(command,'>') != NULL)) {
|
||||
WCMD_output ("Redirection not yet implemented\n");
|
||||
return;
|
||||
}
|
||||
if (strchr(command,'|') != NULL) {
|
||||
WCMD_output ("Pipes not yet implemented\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand up environment variables.
|
||||
*/
|
||||
|
||||
status = ExpandEnvironmentStrings (command, cmd, sizeof(cmd));
|
||||
if (!status) {
|
||||
WCMD_print_error ();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Changing default drive has to be handled as a special case.
|
||||
*/
|
||||
|
||||
if ((cmd[1] == ':') && IsCharAlpha (cmd[0]) && (strlen(cmd) == 2)) {
|
||||
status = SetCurrentDirectory (cmd);
|
||||
if (!status) WCMD_print_error ();
|
||||
return;
|
||||
}
|
||||
WCMD_output (newline);
|
||||
|
||||
/*
|
||||
* Check if the command entered is internal. If it is, pass the rest of the
|
||||
* line down to the command. If not try to run a program.
|
||||
*/
|
||||
|
||||
count = 0;
|
||||
while (IsCharAlphaNumeric(cmd[count])) {
|
||||
count++;
|
||||
}
|
||||
for (i=0; i<=WCMD_EXIT; i++) {
|
||||
if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
|
||||
cmd, count, inbuilt[i], -1) == 2) break;
|
||||
}
|
||||
p = WCMD_strtrim_leading_spaces (&cmd[count]);
|
||||
WCMD_parse (p, quals, param1, param2);
|
||||
switch (i) {
|
||||
|
||||
case WCMD_ATTRIB:
|
||||
WCMD_setshow_attrib ();
|
||||
break;
|
||||
case WCMD_CALL:
|
||||
WCMD_batch (param1, p);
|
||||
break;
|
||||
case WCMD_CD:
|
||||
case WCMD_CHDIR:
|
||||
WCMD_setshow_default ();
|
||||
break;
|
||||
case WCMD_CLS:
|
||||
WCMD_clear_screen ();
|
||||
break;
|
||||
case WCMD_COPY:
|
||||
WCMD_copy ();
|
||||
break;
|
||||
case WCMD_CTTY:
|
||||
WCMD_change_tty ();
|
||||
break;
|
||||
case WCMD_DATE:
|
||||
WCMD_setshow_date ();
|
||||
break;
|
||||
case WCMD_DEL:
|
||||
case WCMD_ERASE:
|
||||
WCMD_delete (0);
|
||||
break;
|
||||
case WCMD_DIR:
|
||||
WCMD_directory ();
|
||||
break;
|
||||
case WCMD_ECHO:
|
||||
WCMD_echo (p);
|
||||
break;
|
||||
case WCMD_FOR:
|
||||
WCMD_for ();
|
||||
break;
|
||||
case WCMD_GOTO:
|
||||
break;
|
||||
case WCMD_HELP:
|
||||
WCMD_give_help (p);
|
||||
break;
|
||||
case WCMD_IF:
|
||||
WCMD_if ();
|
||||
break;
|
||||
case WCMD_LABEL:
|
||||
WCMD_volume (1, p);
|
||||
break;
|
||||
case WCMD_MD:
|
||||
case WCMD_MKDIR:
|
||||
WCMD_create_dir ();
|
||||
break;
|
||||
case WCMD_MOVE:
|
||||
WCMD_move ();
|
||||
break;
|
||||
case WCMD_PATH:
|
||||
WCMD_setshow_path ();
|
||||
break;
|
||||
case WCMD_PAUSE:
|
||||
WCMD_pause ();
|
||||
break;
|
||||
case WCMD_PROMPT:
|
||||
WCMD_setshow_prompt ();
|
||||
break;
|
||||
case WCMD_REM:
|
||||
break;
|
||||
case WCMD_REN:
|
||||
case WCMD_RENAME:
|
||||
WCMD_rename ();
|
||||
break;
|
||||
case WCMD_RD:
|
||||
case WCMD_RMDIR:
|
||||
WCMD_remove_dir ();
|
||||
break;
|
||||
case WCMD_SET:
|
||||
WCMD_setshow_env (p);
|
||||
break;
|
||||
case WCMD_SHIFT:
|
||||
WCMD_shift ();
|
||||
break;
|
||||
case WCMD_TIME:
|
||||
WCMD_setshow_time ();
|
||||
break;
|
||||
case WCMD_TYPE:
|
||||
WCMD_type ();
|
||||
break;
|
||||
case WCMD_VER:
|
||||
WCMD_version ();
|
||||
break;
|
||||
case WCMD_VERIFY:
|
||||
WCMD_verify ();
|
||||
break;
|
||||
case WCMD_VOL:
|
||||
WCMD_volume (0, p);
|
||||
break;
|
||||
case WCMD_EXIT:
|
||||
ExitProcess (0);
|
||||
default:
|
||||
WCMD_run_program (cmd);
|
||||
};
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* WCMD_run_program
|
||||
*
|
||||
* Execute a command line as an external program. If no extension given then
|
||||
* precedence is given to .BAT files. Must allow recursion.
|
||||
*
|
||||
* FIXME: Case sensitivity in suffixes!
|
||||
*/
|
||||
|
||||
void WCMD_run_program (char *command) {
|
||||
|
||||
STARTUPINFO st;
|
||||
PROCESS_INFORMATION pe;
|
||||
BOOL status;
|
||||
HANDLE h;
|
||||
char filetorun[MAX_PATH];
|
||||
|
||||
WCMD_parse (command, quals, param1, param2); /* Quick way to get the filename */
|
||||
if (strpbrk (param1, "\\:") == NULL) { /* No explicit path given */
|
||||
if ((strchr (param1, '.') == NULL) || (strstr (param1, ".bat") != NULL)) {
|
||||
if (SearchPath (NULL, param1, ".bat", sizeof(filetorun), filetorun, NULL)) {
|
||||
WCMD_batch (filetorun, command);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* Explicit path given */
|
||||
if (strstr (param1, ".bat") != NULL) {
|
||||
WCMD_batch (param1, command);
|
||||
return;
|
||||
}
|
||||
if (strchr (param1, '.') == NULL) {
|
||||
strcpy (filetorun, param1);
|
||||
strcat (filetorun, ".bat");
|
||||
h = CreateFile (filetorun, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if (h != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle (h);
|
||||
WCMD_batch (param1, command);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* No batch file found, assume executable */
|
||||
|
||||
ZeroMemory (&st, sizeof(STARTUPINFO));
|
||||
st.cb = sizeof(STARTUPINFO);
|
||||
status = CreateProcess (NULL, command, NULL, NULL, FALSE,
|
||||
0, NULL, NULL, &st, &pe);
|
||||
if (!status) {
|
||||
WCMD_print_error ();
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* WCMD_show_prompt
|
||||
*
|
||||
* Display the prompt on STDout
|
||||
*
|
||||
*/
|
||||
|
||||
void WCMD_show_prompt () {
|
||||
|
||||
int status;
|
||||
char out_string[MAX_PATH], curdir[MAX_PATH], prompt_string[MAX_PATH];
|
||||
char *p, *q;
|
||||
|
||||
status = GetEnvironmentVariable ("PROMPT", prompt_string, sizeof(prompt_string));
|
||||
if ((status == 0) || (status > sizeof(prompt_string))) {
|
||||
lstrcpy (prompt_string, "$N$G");
|
||||
}
|
||||
p = prompt_string;
|
||||
q = out_string;
|
||||
*q = '\0';
|
||||
while (*p != '\0') {
|
||||
if (*p != '$') {
|
||||
*q++ = *p++;
|
||||
*q = '\0';
|
||||
}
|
||||
else {
|
||||
p++;
|
||||
switch (toupper(*p)) {
|
||||
case '$':
|
||||
*q++ = '$';
|
||||
break;
|
||||
case 'B':
|
||||
*q++ = '|';
|
||||
break;
|
||||
case 'D':
|
||||
GetDateFormat (LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, q, MAX_PATH);
|
||||
while (*q) q++;
|
||||
break;
|
||||
case 'E':
|
||||
*q++ = '\E';
|
||||
break;
|
||||
case 'G':
|
||||
*q++ = '>';
|
||||
break;
|
||||
case 'L':
|
||||
*q++ = '<';
|
||||
break;
|
||||
case 'N':
|
||||
status = GetCurrentDirectory (sizeof(curdir), curdir);
|
||||
if (status) {
|
||||
*q++ = curdir[0];
|
||||
}
|
||||
break;
|
||||
case 'P':
|
||||
status = GetCurrentDirectory (sizeof(curdir), curdir);
|
||||
if (status) {
|
||||
lstrcat (q, curdir);
|
||||
while (*q) q++;
|
||||
}
|
||||
break;
|
||||
case 'Q':
|
||||
*q++ = '=';
|
||||
break;
|
||||
case 'T':
|
||||
GetTimeFormat (LOCALE_USER_DEFAULT, 0, NULL, NULL, q, MAX_PATH);
|
||||
while (*q) q++;
|
||||
break;
|
||||
case '_':
|
||||
*q++ = '\n';
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
*q = '\0';
|
||||
}
|
||||
}
|
||||
WCMD_output (out_string);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* WCMD_print_error
|
||||
*
|
||||
* Print the message for GetLastError - not much use yet as Wine doesn't have
|
||||
* the messages available, so we show meaningful messages for the most likely.
|
||||
*/
|
||||
|
||||
void WCMD_print_error () {
|
||||
LPVOID lpMsgBuf;
|
||||
DWORD error_code;
|
||||
|
||||
error_code = GetLastError ();
|
||||
switch (error_code) {
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
WCMD_output ("File Not Found\n");
|
||||
break;
|
||||
case ERROR_PATH_NOT_FOUND:
|
||||
WCMD_output ("Path Not Found\n");
|
||||
break;
|
||||
default:
|
||||
FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL, error_code,
|
||||
MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
|
||||
(LPTSTR) &lpMsgBuf, 0, NULL);
|
||||
WCMD_output (lpMsgBuf);
|
||||
LocalFree ((HLOCAL)lpMsgBuf);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* WCMD_parse - parse a command into parameters and qualifiers.
|
||||
*
|
||||
* On exit, all qualifiers are concatenated into q, the first string
|
||||
* not beginning with "/" is in p1 and the
|
||||
* second in p2. Any subsequent non-qualifier strings are lost.
|
||||
* Parameters in quotes are handled.
|
||||
*/
|
||||
|
||||
void WCMD_parse (char *s, char *q, char *p1, char *p2) {
|
||||
|
||||
int p = 0;
|
||||
|
||||
*q = *p1 = *p2 = '\0';
|
||||
while (TRUE) {
|
||||
switch (*s) {
|
||||
case '/':
|
||||
*q++ = *s++;
|
||||
while ((*s != '\0') && (*s != ' ') && *s != '/') {
|
||||
*q++ = toupper (*s++);
|
||||
}
|
||||
*q = '\0';
|
||||
break;
|
||||
case ' ':
|
||||
s++;
|
||||
break;
|
||||
case '"':
|
||||
s++;
|
||||
while ((*s != '\0') && (*s != '"')) {
|
||||
if (p == 0) *p1++ = *s++;
|
||||
else if (p == 1) *p2++ = *s++;
|
||||
else s++;
|
||||
}
|
||||
if (p == 0) *p1 = '\0';
|
||||
if (p == 1) *p2 = '\0';
|
||||
p++;
|
||||
if (*s == '"') s++;
|
||||
break;
|
||||
case '\0':
|
||||
return;
|
||||
default:
|
||||
while ((*s != '\0') && (*s != ' ') && (*s != '/')) {
|
||||
if (p == 0) *p1++ = *s++;
|
||||
else if (p == 1) *p2++ = *s++;
|
||||
else s++;
|
||||
}
|
||||
if (p == 0) *p1 = '\0';
|
||||
if (p == 1) *p2 = '\0';
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* WCMD_output - send output to current standard output device.
|
||||
*
|
||||
*/
|
||||
|
||||
void WCMD_output (char *format, ...) {
|
||||
|
||||
va_list ap;
|
||||
char string[1024];
|
||||
DWORD count;
|
||||
|
||||
va_start(ap,format);
|
||||
vsprintf (string, format, ap);
|
||||
WriteFile (STDout, string, lstrlen(string), &count, NULL);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
/* Remove leading spaces from a string. Return a pointer to the first
|
||||
* non-space character. Does not modify the input string
|
||||
*/
|
||||
|
||||
char *WCMD_strtrim_leading_spaces (char *string) {
|
||||
|
||||
char *ptr;
|
||||
|
||||
ptr = string;
|
||||
while (*ptr == ' ') ptr++;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* Remove trailing spaces from a string. This routine modifies the input
|
||||
* string by placing a null after the last non-space character
|
||||
*/
|
||||
|
||||
void WCMD_strtrim_trailing_spaces (char *string) {
|
||||
|
||||
char *ptr;
|
||||
|
||||
ptr = string + lstrlen (string) - 1;
|
||||
while ((*ptr == ' ') && (ptr >= string)) {
|
||||
*ptr = '\0';
|
||||
ptr--;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,294 @@
|
|||
|
||||
#include "wcmd.h"
|
||||
|
||||
STRINGTABLE
|
||||
{
|
||||
WCMD_ATTRIB, "Help about ATTRIB\n"
|
||||
WCMD_CALL, "Help about CALL\n"
|
||||
WCMD_CD, "Help about CD\n"
|
||||
WCMD_CHDIR, "Help about CHDIR\n"
|
||||
|
||||
WCMD_CLS,
|
||||
"CLS clears the console screen\n"
|
||||
|
||||
WCMD_COPY, "Help about COPY\n"
|
||||
WCMD_CTTY, "Help about CTTY\n"
|
||||
WCMD_DATE, "Help about DATE\n"
|
||||
WCMD_DEL, "Help about DEL\n"
|
||||
WCMD_DIR, "Help about DIR\n"
|
||||
|
||||
WCMD_ECHO,
|
||||
"ECHO <string> displays <string> on the current terminal device.\
|
||||
\
|
||||
ECHO ON causes all subsequent commands in a batch file to be displayed\
|
||||
on the terminal device before they are executed.\
|
||||
\
|
||||
ECHO OFF reverses the effect of a previous ECHO ON (ECHO is OFF by\
|
||||
default). The ECHO OFF command can be prevented from displaying by\
|
||||
preceding it with an @ sign.\n"
|
||||
|
||||
WCMD_ERASE, "Help about ERASE\n"
|
||||
WCMD_FOR, "Help about FOR\n"
|
||||
WCMD_GOTO, "Help about GOTO\n"
|
||||
WCMD_HELP, "Help about HELP\n"
|
||||
WCMD_IF, "Help about IF\n"
|
||||
WCMD_LABEL, "Help about LABEL\n"
|
||||
WCMD_MD, "Help about MD\n"
|
||||
WCMD_MKDIR, "Help about MKDIR\n"
|
||||
WCMD_MOVE, "Help about MOVE\n"
|
||||
WCMD_PATH,
|
||||
"PATH displays or changes the wcmd search path. \
|
||||
\
|
||||
Entering PATH will display the current PATH setting (initially this is \
|
||||
the value given in your wine.conf file). To change the setting follow the \
|
||||
PATH command with the new value. \
|
||||
\
|
||||
It is also possible to modify the PATH by using the PATH environment \
|
||||
variable, for example: \
|
||||
PATH %PATH%;c:\\temp \n"
|
||||
|
||||
WCMD_PAUSE,
|
||||
"PAUSE displays a message on the screen 'Press Return key to continue'\
|
||||
and waits for the user to press the Return key. It is mainly useful in\
|
||||
batch files to allow the user to read the output of a previous command\
|
||||
before it scrolls off the screen.\n"
|
||||
|
||||
WCMD_PROMPT,
|
||||
"PROMPT sets the command-line prompt.\
|
||||
\
|
||||
The string following the PROMPT command (and the space immediately after)\
|
||||
appears at the beginning of the line when wcmd is waiting for input.\
|
||||
\
|
||||
The following character strings have the special meaning shown:\
|
||||
\
|
||||
$$ Dollar sign $_ Linefeed $b Pipe sign (|)\
|
||||
$d Current date $e Escape $g > sign\
|
||||
$l > sign $n Current drive $p Current path\
|
||||
$q Equal sign $t Current time $v wcmd version\
|
||||
\
|
||||
Note that entering the PROMPT command without a prompt-string resets the\
|
||||
prompt to the default, which is the current drive letter followed by a\
|
||||
greater-than (>) sign.\
|
||||
\
|
||||
The prompt can also be changed by altering the PROMPT environment variable,\
|
||||
so the command 'SET PROMPT=text' has the same effect as 'PROMPT text'\n"
|
||||
|
||||
WCMD_REM,
|
||||
"A command line beginning REM (followed by a space) performs no\
|
||||
action, and can therefore be used as a comment in a batch file.\n"
|
||||
|
||||
WCMD_REN, "Help about REN\n"
|
||||
WCMD_RENAME, "Help about RENAME\n"
|
||||
WCMD_RD, "Help about RD\n"
|
||||
WCMD_RMDIR, "Help about RMDIR\n"
|
||||
|
||||
WCMD_SET,
|
||||
"SET displays or changes the wcmd environment variables.\
|
||||
\
|
||||
SET without parameters shows all of the current environment.\
|
||||
\
|
||||
To create or modify an environment variable the syntax is:\
|
||||
\
|
||||
SET <variable>=<value>\
|
||||
\
|
||||
where <variable> and <value> are character strings. There must be no\
|
||||
spaces either side of the equals sign, nor can the variable or value\
|
||||
have embedded spaces.\
|
||||
\
|
||||
Under Wine, the environment of the underlying operating system is\
|
||||
included into the Win32 environment, there will generally therefore be\
|
||||
many more values than in a native Win32 implementation. Note that it is\
|
||||
not possible to affect the operating system environment from within wcmd.\n"
|
||||
|
||||
WCMD_SHIFT, "Help about SHIFT\n"
|
||||
WCMD_TIME, "Help about TIME\n"
|
||||
|
||||
WCMD_TYPE,
|
||||
"TYPE <filename> copies <filename> to the console device (or elsewhere\
|
||||
if redirected). No check is made that the file is readable text.\n"
|
||||
|
||||
WCMD_VERIFY, "Help about VERIFY\n"
|
||||
|
||||
WCMD_VER,
|
||||
"VER displays the version of wcmd you are running\n"
|
||||
|
||||
WCMD_VOL, "Help about VOL\n"
|
||||
|
||||
WCMD_EXIT,
|
||||
"EXIT terminates the current command session and returns\
|
||||
to the operating system or shell from which you invoked wcmd.\n"
|
||||
|
||||
1000, "WCMD built-in commands are:\
|
||||
ATTRIB\t\tShow or change DOS file attributes\
|
||||
CALL\t\tInvoke a batch file from inside another\
|
||||
CD (CHDIR)\tChange current default directory\
|
||||
CLS\t\tClear the console screen\
|
||||
COPY\t\tCopy file\
|
||||
CTTY\t\tChange input/output device\
|
||||
DATE\t\tShow or change the system date\
|
||||
DEL (ERASE)\tDelete a file or set of files\
|
||||
DIR\t\tList the contents of a directory\
|
||||
ECHO\t\tCopy text directly to the console output\
|
||||
HELP\t\tShow brief help details on a topic\
|
||||
MD (MKDIR)\tCreate a subdirectory\
|
||||
MOVE\t\tMove a file, set of files or directory tree\
|
||||
PATH\t\tSet or show the search path\
|
||||
PROMPT\t\tChange the command prompt\
|
||||
REN (RENAME)\tRename a file\
|
||||
RD (RMDIR)\tDelete a subdirectory\
|
||||
SET\t\tSet or show environment variables\
|
||||
TIME\t\tSet or show the current system time\
|
||||
TYPE\t\tType the contents of a text file\
|
||||
VER\t\tShow the current version of WCMD\
|
||||
VOL\t\tShow the volume label of a disk device\
|
||||
EXIT\t\tClose down WCMD\n\
|
||||
Enter HELP <command> for further information on any of the above commands\n"
|
||||
}
|
||||
LANGUAGE LANG_NEUTRAL,SUBLANG_NEUTRAL
|
||||
|
||||
|
||||
IDI_ICON1 ICON
|
||||
{
|
||||
'00 00 01 00 01 00 20 20 00 01 00 00 00 00 A8 08'
|
||||
'00 00 16 00 00 00 28 00 00 00 20 00 00 00 40 00'
|
||||
'00 00 01 00 08 00 00 00 00 00 80 04 00 00 00 00'
|
||||
'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
|
||||
'00 00 40 00 00 00 80 00 00 00 FF 00 00 00 00 20'
|
||||
'00 00 40 20 00 00 80 20 00 00 FF 20 00 00 00 40'
|
||||
'00 00 40 40 00 00 80 40 00 00 FF 40 00 00 00 60'
|
||||
'00 00 40 60 00 00 80 60 00 00 FF 60 00 00 00 80'
|
||||
'00 00 40 80 00 00 80 80 00 00 FF 80 00 00 00 A0'
|
||||
'00 00 40 A0 00 00 80 A0 00 00 FF A0 00 00 00 C0'
|
||||
'00 00 40 C0 00 00 80 C0 00 00 FF C0 00 00 00 FF'
|
||||
'00 00 40 FF 00 00 80 FF 00 00 FF FF 00 00 00 00'
|
||||
'20 00 40 00 20 00 80 00 20 00 FF 00 20 00 00 20'
|
||||
'20 00 40 20 20 00 80 20 20 00 FF 20 20 00 00 40'
|
||||
'20 00 40 40 20 00 80 40 20 00 FF 40 20 00 00 60'
|
||||
'20 00 40 60 20 00 80 60 20 00 FF 60 20 00 00 80'
|
||||
'20 00 40 80 20 00 80 80 20 00 FF 80 20 00 00 A0'
|
||||
'20 00 40 A0 20 00 80 A0 20 00 FF A0 20 00 00 C0'
|
||||
'20 00 40 C0 20 00 80 C0 20 00 FF C0 20 00 00 FF'
|
||||
'20 00 40 FF 20 00 80 FF 20 00 FF FF 20 00 00 00'
|
||||
'40 00 40 00 40 00 80 00 40 00 FF 00 40 00 00 20'
|
||||
'40 00 40 20 40 00 80 20 40 00 FF 20 40 00 00 40'
|
||||
'40 00 40 40 40 00 80 40 40 00 FF 40 40 00 00 60'
|
||||
'40 00 40 60 40 00 80 60 40 00 FF 60 40 00 00 80'
|
||||
'40 00 40 80 40 00 80 80 40 00 FF 80 40 00 00 A0'
|
||||
'40 00 40 A0 40 00 80 A0 40 00 FF A0 40 00 00 C0'
|
||||
'40 00 40 C0 40 00 80 C0 40 00 FF C0 40 00 00 FF'
|
||||
'40 00 40 FF 40 00 80 FF 40 00 FF FF 40 00 00 00'
|
||||
'60 00 40 00 60 00 80 00 60 00 FF 00 60 00 00 20'
|
||||
'60 00 40 20 60 00 80 20 60 00 FF 20 60 00 00 40'
|
||||
'60 00 40 40 60 00 80 40 60 00 FF 40 60 00 00 60'
|
||||
'60 00 40 60 60 00 80 60 60 00 FF 60 60 00 00 80'
|
||||
'60 00 40 80 60 00 80 80 60 00 FF 80 60 00 00 A0'
|
||||
'60 00 40 A0 60 00 80 A0 60 00 FF A0 60 00 00 C0'
|
||||
'60 00 40 C0 60 00 80 C0 60 00 FF C0 60 00 00 FF'
|
||||
'60 00 40 FF 60 00 80 FF 60 00 FF FF 60 00 00 00'
|
||||
'80 00 40 00 80 00 80 00 80 00 FF 00 80 00 00 20'
|
||||
'80 00 40 20 80 00 80 20 80 00 FF 20 80 00 00 40'
|
||||
'80 00 40 40 80 00 80 40 80 00 FF 40 80 00 00 60'
|
||||
'80 00 40 60 80 00 80 60 80 00 FF 60 80 00 00 80'
|
||||
'80 00 40 80 80 00 80 80 80 00 FF 80 80 00 00 A0'
|
||||
'80 00 40 A0 80 00 80 A0 80 00 FF A0 80 00 00 C0'
|
||||
'80 00 40 C0 80 00 80 C0 80 00 FF C0 80 00 00 FF'
|
||||
'80 00 40 FF 80 00 80 FF 80 00 FF FF 80 00 00 00'
|
||||
'A0 00 40 00 A0 00 80 00 A0 00 FF 00 A0 00 00 20'
|
||||
'A0 00 40 20 A0 00 80 20 A0 00 FF 20 A0 00 00 40'
|
||||
'A0 00 40 40 A0 00 80 40 A0 00 FF 40 A0 00 00 60'
|
||||
'A0 00 40 60 A0 00 80 60 A0 00 FF 60 A0 00 00 80'
|
||||
'A0 00 40 80 A0 00 80 80 A0 00 FF 80 A0 00 00 A0'
|
||||
'A0 00 40 A0 A0 00 80 A0 A0 00 FF A0 A0 00 00 C0'
|
||||
'A0 00 40 C0 A0 00 80 C0 A0 00 FF C0 A0 00 00 FF'
|
||||
'A0 00 40 FF A0 00 80 FF A0 00 FF FF A0 00 00 00'
|
||||
'C0 00 40 00 C0 00 80 00 C0 00 FF 00 C0 00 00 20'
|
||||
'C0 00 40 20 C0 00 80 20 C0 00 FF 20 C0 00 00 40'
|
||||
'C0 00 40 40 C0 00 80 40 C0 00 FF 40 C0 00 00 60'
|
||||
'C0 00 40 60 C0 00 80 60 C0 00 FF 60 C0 00 00 80'
|
||||
'C0 00 40 80 C0 00 80 80 C0 00 FF 80 C0 00 00 A0'
|
||||
'C0 00 40 A0 C0 00 80 A0 C0 00 FF A0 C0 00 00 C0'
|
||||
'C0 00 40 C0 C0 00 80 C0 C0 00 FF C0 C0 00 00 FF'
|
||||
'C0 00 40 FF C0 00 80 FF C0 00 FF FF C0 00 00 00'
|
||||
'FF 00 40 00 FF 00 80 00 FF 00 FF 00 FF 00 00 20'
|
||||
'FF 00 40 20 FF 00 80 20 FF 00 FF 20 FF 00 00 40'
|
||||
'FF 00 40 40 FF 00 80 40 FF 00 FF 40 FF 00 00 60'
|
||||
'FF 00 40 60 FF 00 80 60 FF 00 FF 60 FF 00 00 80'
|
||||
'FF 00 40 80 FF 00 80 80 FF 00 FF 80 FF 00 00 A0'
|
||||
'FF 00 40 A0 FF 00 80 A0 FF 00 FF A0 FF 00 00 C0'
|
||||
'FF 00 40 C0 FF 00 80 C0 FF 00 FF C0 FF 00 00 FF'
|
||||
'FF 00 40 FF FF 00 80 FF FF 00 FF FF FF 00 FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF B6 24 FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF 6D 24 FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF B6 00 B6 FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF 92 00 FF FF 24 FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF 24 FF FF FF FF 92 FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF 24 FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF 92 FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF 6D FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF B6 FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF 6D FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF 92 FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF 6D FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF 6D FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF 24 FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 24'
|
||||
'FF B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 24'
|
||||
'80 81 60 6C FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF 24 81'
|
||||
'C1 81 80 81 20 FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF C0 C1'
|
||||
'80 80 C1 81 C1 20 FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF 81 81'
|
||||
'81 80 81 80 80 80 24 FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF 6D 80 81'
|
||||
'81 80 81 C1 C0 80 80 92 FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF B6 FF FF'
|
||||
'FF FF FF 81 C0 80 80 20 FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF 92 FF FF'
|
||||
'FF FF FF FF C5 C0 80 81 6D FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FB 81 81 24 FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 FF'
|
||||
'FF FF FF FF FF FF FF FF 24 FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF 6D FF'
|
||||
'FF FF FF FF FF FF FF FF 6D FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92'
|
||||
'FF FF FF FF FF FF FF 24 24 FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'92 FF FF FF FF 24 6D FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'92 FF FF 00 92 FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF 24 B6 FF FF FF FF FF FF FF FF FF FF FF 00 00'
|
||||
'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
|
||||
'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
|
||||
'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
|
||||
'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
|
||||
'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
|
||||
'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
|
||||
'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
|
||||
'00 00 00 00 00 00 00 00 00 00 00 00 00 00'
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue