1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
|
/*
* WCMD - Wine-compatible command line interface - batch interface.
*
* (C) 1999 D A Pickles
*
*/
#include "wcmd.h"
void WCMD_batch_command (char *line);
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];
extern BATCH_CONTEXT *context;
/****************************************************************************
* 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. Called is 1 for a CALL, 0 otherwise.
*
* 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.
*/
void WCMD_batch (char *file, char *command, int called) {
HANDLE h;
char string[MAX_PATH];
BATCH_CONTEXT *prev_context;
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;
}
/*
* Create a context structure for this batch file.
*/
prev_context = context;
context = (BATCH_CONTEXT *)LocalAlloc (LMEM_FIXED, sizeof (BATCH_CONTEXT));
context -> h = h;
context -> command = command;
context -> shift_count = 0;
context -> prev_context = prev_context;
/*
* 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)) {
if (string[0] != ':') { /* Skip over labels */
WCMD_batch_command (string);
}
}
CloseHandle (h);
/*
* If invoked by a CALL, we return to the context of our caller. Otherwise return
* to the caller's caller.
*/
LocalFree ((HANDLE)context);
if ((prev_context != NULL) && (!called)) {
CloseHandle (prev_context -> h);
context = prev_context -> prev_context;
LocalFree ((HANDLE)prev_context);
}
else {
context = prev_context;
}
}
/****************************************************************************
* WCMD_batch_command
*
* Execute one line from a batch file, expanding parameters.
*/
void WCMD_batch_command (char *line) {
DWORD status;
char cmd[1024];
char *p, *s, *t;
int i;
if (echo_mode && (line[0] != '@')) WCMD_output ("%s", line);
status = ExpandEnvironmentStrings (line, cmd, sizeof(cmd));
if (!status) {
WCMD_print_error ();
return;
}
p = cmd;
while ((p = strchr(p, '%'))) {
i = *(p+1) - '0';
if ((i >= 0) && (i <= 9)) {
s = strdup (p+2);
t = WCMD_parameter (context -> command, i + context -> shift_count, NULL);
strcpy (p, t);
strcat (p, s);
free (s);
}
}
WCMD_process_command (cmd);
}
/*******************************************************************
* WCMD_parameter - extract a parameter from a command line.
*
* Returns the 'n'th space-delimited parameter on the command line (zero-based).
* Parameter is in static storage overwritten on the next call.
* Parameters in quotes (and brackets) are handled.
* Also returns a pointer to the location of the parameter in the command line.
*/
char *WCMD_parameter (char *s, int n, char **where) {
int i = 0;
static char param[MAX_PATH];
char *p;
p = param;
while (TRUE) {
switch (*s) {
case ' ':
s++;
break;
case '"':
if (where != NULL) *where = s;
s++;
while ((*s != '\0') && (*s != '"')) {
*p++ = *s++;
}
if (i == n) {
*p = '\0';
return param;
}
if (*s == '"') s++;
param[0] = '\0';
i++;
p = param;
break;
case '(':
if (where != NULL) *where = s;
s++;
while ((*s != '\0') && (*s != ')')) {
*p++ = *s++;
}
if (i == n) {
*p = '\0';
return param;
}
if (*s == ')') s++;
param[0] = '\0';
i++;
p = param;
break;
case '\0':
return param;
default:
if (where != NULL) *where = s;
while ((*s != '\0') && (*s != ' ')) {
*p++ = *s++;
}
if (i == n) {
*p = '\0';
return param;
}
param[0] = '\0';
i++;
p = param;
}
}
}
/****************************************************************************
* 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. Also need to lose
* the LF (or CRLF) from the line.
*/
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) && (s == p))) return NULL;
if (*s == '\n') bytes = 0;
else if (*s != '\r') {
s++;
n--;
}
*s = '\0';
} while ((bytes == 1) && (n > 1));
return p;
}
|