cmd.exe: Add support for call :label and goto :label.
This commit is contained in:
parent
365f86fd7e
commit
327d7ef9e6
|
@ -42,9 +42,12 @@ extern DWORD errorlevel;
|
|||
*
|
||||
* We need to handle recursion correctly, since one batch program might call another.
|
||||
* So parameters for this batch file are held in a BATCH_CONTEXT structure.
|
||||
*
|
||||
* To support call within the same batch program, another input parameter is
|
||||
* a label to goto once opened.
|
||||
*/
|
||||
|
||||
void WCMD_batch (char *file, char *command, int called) {
|
||||
void WCMD_batch (char *file, char *command, int called, char *startLabel, HANDLE pgmHandle) {
|
||||
|
||||
#define WCMD_BATCH_EXT_SIZE 5
|
||||
|
||||
|
@ -55,27 +58,33 @@ char extension_exe[WCMD_BATCH_EXT_SIZE] = ".exe";
|
|||
unsigned int i;
|
||||
BATCH_CONTEXT *prev_context;
|
||||
|
||||
for(i=0; (i<(sizeof(extension_batch)/WCMD_BATCH_EXT_SIZE)) &&
|
||||
(h == INVALID_HANDLE_VALUE); i++) {
|
||||
strcpy (string, file);
|
||||
CharLower (string);
|
||||
if (strstr (string, extension_batch[i]) == NULL) strcat (string, extension_batch[i]);
|
||||
h = CreateFile (string, GENERIC_READ, FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
}
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
if (startLabel == NULL) {
|
||||
for(i=0; (i<(sizeof(extension_batch)/WCMD_BATCH_EXT_SIZE)) &&
|
||||
(h == INVALID_HANDLE_VALUE); i++) {
|
||||
strcpy (string, file);
|
||||
CharLower (string);
|
||||
if (strstr (string, extension_exe) == NULL) strcat (string, extension_exe);
|
||||
if (strstr (string, extension_batch[i]) == NULL) strcat (string, extension_batch[i]);
|
||||
h = CreateFile (string, GENERIC_READ, FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (h != INVALID_HANDLE_VALUE) {
|
||||
WCMD_run_program (command, 0);
|
||||
} else {
|
||||
SetLastError (ERROR_FILE_NOT_FOUND);
|
||||
WCMD_print_error ();
|
||||
}
|
||||
return;
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
strcpy (string, file);
|
||||
CharLower (string);
|
||||
if (strstr (string, extension_exe) == NULL) strcat (string, extension_exe);
|
||||
h = CreateFile (string, GENERIC_READ, FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (h != INVALID_HANDLE_VALUE) {
|
||||
WCMD_run_program (command, 0);
|
||||
} else {
|
||||
SetLastError (ERROR_FILE_NOT_FOUND);
|
||||
WCMD_print_error ();
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
DuplicateHandle(GetCurrentProcess(), pgmHandle,
|
||||
GetCurrentProcess(), &h,
|
||||
0, FALSE, DUPLICATE_SAME_ACCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -90,6 +99,12 @@ BATCH_CONTEXT *prev_context;
|
|||
context -> prev_context = prev_context;
|
||||
context -> skip_rest = FALSE;
|
||||
|
||||
/* If processing a call :label, 'goto' the label in question */
|
||||
if (startLabel) {
|
||||
strcpy(param1, startLabel);
|
||||
WCMD_goto();
|
||||
}
|
||||
|
||||
/*
|
||||
* Work through the file line by line. Specific batch commands are processed here,
|
||||
* the rest are handled by the main command processor.
|
||||
|
@ -695,3 +710,40 @@ void WCMD_HandleTildaModifiers(char **start, char *forVariable) {
|
|||
strcat(*start, pos);
|
||||
free(pos);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* WCMD_call - processes a batch call statement
|
||||
*
|
||||
* If there is a leading ':', calls within this batch program
|
||||
* otherwise launches another program.
|
||||
*/
|
||||
void WCMD_call (char *command) {
|
||||
|
||||
/* Run other program if no leading ':' */
|
||||
if (*command != ':') {
|
||||
WCMD_run_program(command, 1);
|
||||
} else {
|
||||
|
||||
char gotoLabel[MAX_PATH];
|
||||
|
||||
strcpy(gotoLabel, param1);
|
||||
|
||||
if (context) {
|
||||
|
||||
LARGE_INTEGER li;
|
||||
|
||||
/* Save the current file position, call the same file,
|
||||
restore position */
|
||||
li.QuadPart = 0;
|
||||
li.LowPart = SetFilePointer(context -> h, li.LowPart,
|
||||
&li.HighPart, FILE_CURRENT);
|
||||
|
||||
WCMD_batch (param1, command, 1, gotoLabel, context->h);
|
||||
|
||||
SetFilePointer(context -> h, li.LowPart,
|
||||
&li.HighPart, FILE_BEGIN);
|
||||
} else {
|
||||
printf("Cannot call batch label outside of a batch script\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -434,6 +434,7 @@ char string[MAX_PATH];
|
|||
return;
|
||||
}
|
||||
if (context != NULL) {
|
||||
char *paramStart = param1;
|
||||
|
||||
/* Handle special :EOF label */
|
||||
if (lstrcmpi (":eof", param1) == 0) {
|
||||
|
@ -441,9 +442,12 @@ char string[MAX_PATH];
|
|||
return;
|
||||
}
|
||||
|
||||
/* Support goto :label as well as goto label */
|
||||
if (*paramStart == ':') paramStart++;
|
||||
|
||||
SetFilePointer (context -> h, 0, NULL, FILE_BEGIN);
|
||||
while (WCMD_fgets (string, sizeof(string), context -> h)) {
|
||||
if ((string[0] == ':') && (lstrcmpi (&string[1], param1) == 0)) return;
|
||||
if ((string[0] == ':') && (lstrcmpi (&string[1], paramStart) == 0)) return;
|
||||
}
|
||||
WCMD_output ("Target to GOTO not found\n");
|
||||
}
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
void WCMD_batch (char *, char *, int);
|
||||
void WCMD_batch (char *, char *, int, char *, HANDLE);
|
||||
void WCMD_call (char *command);
|
||||
void WCMD_change_tty (void);
|
||||
void WCMD_clear_screen (void);
|
||||
void WCMD_copy (void);
|
||||
|
|
|
@ -265,7 +265,7 @@ int main (int argc, char *argv[])
|
|||
if (h != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle (h);
|
||||
#if 0
|
||||
WCMD_batch_command (string);
|
||||
WCMD_batch ((char *)"\\autoexec.bat", (char *)"\\autoexec.bat", 0, NULL, INVALID_HANDLE_VALUE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -422,7 +422,7 @@ void WCMD_process_command (char *command)
|
|||
WCMD_setshow_attrib ();
|
||||
break;
|
||||
case WCMD_CALL:
|
||||
WCMD_run_program (p, 1);
|
||||
WCMD_call (p);
|
||||
break;
|
||||
case WCMD_CD:
|
||||
case WCMD_CHDIR:
|
||||
|
@ -628,14 +628,14 @@ char filetorun[MAX_PATH];
|
|||
if (!ext || !strcasecmp( ext, ".bat"))
|
||||
{
|
||||
if (SearchPath (NULL, param1, ".bat", sizeof(filetorun), filetorun, NULL)) {
|
||||
WCMD_batch (filetorun, command, called);
|
||||
WCMD_batch (filetorun, command, called, NULL, INVALID_HANDLE_VALUE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!ext || !strcasecmp( ext, ".cmd"))
|
||||
{
|
||||
if (SearchPath (NULL, param1, ".cmd", sizeof(filetorun), filetorun, NULL)) {
|
||||
WCMD_batch (filetorun, command, called);
|
||||
WCMD_batch (filetorun, command, called, NULL, INVALID_HANDLE_VALUE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -644,7 +644,7 @@ char filetorun[MAX_PATH];
|
|||
char *ext = strrchr( param1, '.' );
|
||||
if (ext && (!strcasecmp( ext, ".bat" ) || !strcasecmp( ext, ".cmd" )))
|
||||
{
|
||||
WCMD_batch (param1, command, called);
|
||||
WCMD_batch (param1, command, called, NULL, INVALID_HANDLE_VALUE);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -657,7 +657,7 @@ char filetorun[MAX_PATH];
|
|||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (h != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle (h);
|
||||
WCMD_batch (param1, command, called);
|
||||
WCMD_batch (param1, command, called, NULL, INVALID_HANDLE_VALUE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue