Subversion Repositories SvarDOS

Compare Revisions

Ignore whitespace Rev 457 → Rev 458

/svarcom/trunk/command.c
268,15 → 268,141
}
 
 
static void run_as_external(char *buff, const char far *cmdline) {
/* tries locating executable fname in path and fille res with result. returns 0 on success,
* -1 on failed match and -2 on failed match + "don't even try with other paths"
* format is filled the offset where extension starts in fname (-1 if not found) */
int lookup_cmd(char *res, const char *fname, const char *path, const char **extptr) {
unsigned short lastbslash = 0xffff;
unsigned short i, len;
unsigned char explicitpath = 0;
 
/* does the original fname had an explicit path prefix or explicit ext? */
*extptr = NULL;
for (i = 0; fname[i] != 0; i++) {
switch (fname[i]) {
case ':':
case '\\':
explicitpath = 1;
*extptr = NULL; /* extension is the last dot AFTER all path delimiters */
break;
case '.':
*extptr = fname + i + 1;
break;
}
}
 
/* normalize filename */
if (file_truename(fname, res) != 0) return(-2);
 
/* printf("truename: %s\r\n", res); */
 
/* figure out where the command starts and if it has an explicit extension */
for (len = 0; res[len] != 0; len++) {
switch (res[len]) {
case '?': /* abort on any wildcard character */
case '*':
return(-2);
case '\\':
lastbslash = len;
break;
}
}
 
/* printf("lastbslash=%u\r\n", lastbslash); */
 
/* if no path prefix in fname (':' or backslash), then assemble path+filename */
if (!explicitpath) {
if (path != NULL) {
i = strlen(path);
} else {
i = 0;
}
if ((i != 0) && (path[i - 1] != '\\')) i++; /* add a byte for inserting a bkslash after path */
memmove(res + i, res + lastbslash + 1, len - lastbslash);
if (i != 0) {
memmove(res, path, i);
res[i - 1] = '\\';
}
}
 
/* if no extension was initially provided, try matching COM, EXE, BAT */
if (*extptr == NULL) {
const char *ext[] = {".COM", ".EXE", ".BAT", NULL};
len = strlen(res);
for (i = 0; ext[i] != NULL; i++) {
strcpy(res + len, ext[i]);
/* printf("? '%s'\r\n", res); */
*extptr = ext[i] + 1;
if (file_getattr(res) >= 0) return(0);
}
} else { /* try finding it as-is */
/* printf("? '%s'\r\n", res); */
if (file_getattr(res) >= 0) return(0);
}
 
/* not found */
if (explicitpath) return(-2); /* don't bother trying other paths, the caller had its own path preset anyway */
return(-1);
}
 
 
static void run_as_external(char *buff, const char far *cmdline, unsigned short envseg) {
char const **argvlist = (void *)(buff + 512);
char *cmdfile = buff + 1024;
const char far *pathptr;
int lookup;
unsigned short i;
const char *ext;
 
cmd_explode(buff, cmdline, argvlist);
cmd_explode(buff + 2048, cmdline, argvlist);
 
/* for (i = 0; argvlist[i] != NULL; i++) printf("arg #%d = '%s'\r\n", i, argvlist[i]); */
 
/* is this a command in curdir? */
lookup = lookup_cmd(cmdfile, argvlist[0], NULL, &ext);
if (lookup == 0) {
/* printf("FOUND LOCAL EXEC FILE: '%s'\r\n", cmdfile); */
goto RUNCMDFILE;
} else if (lookup == -2) {
/* puts("NOT FOUND"); */
return;
}
 
/* try matching something in PATH */
pathptr = env_lookup_val(envseg, "PATH");
if (pathptr == NULL) return;
 
/* try each path in %PATH% */
for (;;) {
for (i = 0;; i++) {
buff[i] = *pathptr;
if ((buff[i] == 0) || (buff[i] == ';')) break;
pathptr++;
}
buff[i] = 0;
lookup = lookup_cmd(cmdfile, argvlist[0], buff, &ext);
if (lookup == 0) break;
if (lookup == -2) return;
if (*pathptr == ';') {
pathptr++;
} else {
return;
}
}
 
RUNCMDFILE:
/* TODO run command through INT 0x21 */
/* TODO copy environment and append full exec path */
/* TODO special handling of batch files */
if ((ext != NULL) && (imatch(ext, "bat"))) {
outputnl("batch processing not supported yet");
return;
}
 
/* printf("Exec: '%s'\r\n", cmdfile); */
 
/* this call should never return, unless the program failed to be executed */
execvp(argvlist[0], argvlist);
execvp(cmdfile, argvlist);
}
 
 
468,7 → 594,7
}
 
/* if here, then this was not an internal command */
run_as_external(BUFFER, cmdline);
run_as_external(BUFFER, cmdline, *rmod_envseg);
 
/* revert stdout (in case it was redirected) */
redir_revert();