Subversion Repositories SvarDOS

Compare Revisions

Ignore whitespace Rev 473 → Rev 474

/svarcom/trunk/command.c
163,7 → 163,9
}
 
 
static void buildprompt(char *s, unsigned short envseg) {
/* builds the prompt string and displays it. buff is filled with a zero-terminated copy of the prompt. */
static void build_and_display_prompt(char *buff, unsigned short envseg) {
char *s = buff;
/* locate the prompt variable or use the default pattern */
const char far *fmt = env_lookup_val(envseg, "PROMPT");
if ((fmt == NULL) || (*fmt == 0)) fmt = "$p$g"; /* fallback to default if empty */
264,7 → 266,8
break;
}
}
*s = '$';
*s = 0;
output(buff);
}
 
 
416,6 → 419,9
for (i = 0; cmdtail[i] != 0; i++) rmod->batargs[i] = cmdtail[i];
/* reset the 'next line to execute' counter */
rmod->batnextline = 0;
/* remember the echo flag (in case bat file disables echo) */
rmod->flags &= ~FLAG_ECHO_BEFORE_BAT;
if (rmod->echoflag) rmod->flags |= FLAG_ECHO_BEFORE_BAT;
return;
}
 
519,34 → 525,87
 
 
/* fetches a line from batch file and write it to buff, increments
* rmod counter on success. returns NULL on failure.
* buff must start with a length byte but the returned pointer must
* skip it. */
static char far *getbatcmd(char *buff, struct rmod_props far *rmod) {
* rmod counter on success. returns 0 on success.
* buff starts with a length byte and is NULL-terminated */
static int getbatcmd(char *buff, struct rmod_props far *rmod) {
unsigned short i;
buff++; /* make room for the len byte */
/* TODO temporary hack to display a dummy message */
if (rmod->batnextline == 0) {
char *msg = "ECHO batch files not supported yet";
for (i = 0; msg[i] != 0; i++) buff[i] = msg[i];
buff[i] = 0;
buff[-1] = i;
} else {
rmod->batfile[0] = 0;
return(NULL);
unsigned short batname_seg = FP_SEG(rmod->batfile);
unsigned short batname_off = FP_OFF(rmod->batfile);
unsigned short filepos_cx = rmod->batnextline >> 16;
unsigned short filepos_dx = rmod->batnextline & 0xffff;
unsigned char blen = 0;
 
buff++; /* make room for the len byte prefix */
 
/* open file, jump to offset filpos, and read data into buff.
* result in blen (unchanged if EOF or failure). */
_asm {
push ax
push bx
push cx
push dx
 
/* open file (read-only) */
mov dx, batname_off
mov ax, batname_seg
push ds /* save DS */
mov ds, ax
mov ax, 0x3d00
int 0x21 /* handle in ax on success */
pop ds /* restore DS */
jc DONE
mov bx, ax /* save handle to bx */
 
/* jump to file offset CX:DX */
mov ax, 0x4200
mov cx, filepos_cx
mov dx, filepos_dx
int 0x21 /* CF clear on success, DX:AX set to cur pos */
jc CLOSEANDQUIT
 
/* read the line into buff */
mov ah, 0x3f
mov cx, 255
mov dx, buff
int 0x21 /* CF clear on success, AX=number of bytes read */
jc CLOSEANDQUIT
mov blen, al
 
CLOSEANDQUIT:
/* close file (handle in bx) */
mov ah, 0x3e
int 0x21
 
DONE:
pop dx
pop cx
pop bx
pop ax
}
/* open file */
/* read until awaiting line */
/* copy line to buff */
/* close file */
/* */
rmod->batnextline++;
if (rmod->batnextline == 0) rmod->batfile[0] = 0; /* max line count reached */
 
/* output command on screen if echo on */
if (rmod->echoflag != 0) outputnl(buff);
/* printf("blen=%u filepos_cx=%u filepos_dx=%u\r\n", blen, filepos_cx, filepos_dx); */
 
return(buff);
/* on EOF - abort processing the bat file */
if (blen == 0) goto OOPS;
 
/* find nearest \n to inc batch offset and replace \r by NULL terminator
* I support all CR/LF, CR- and LF-terminated batch files */
for (i = 0; i < blen; i++) {
if ((buff[i] == '\r') || (buff[i] == '\n')) {
if ((buff[i] == '\r') && ((i+1) < blen) && (buff[i+1] == '\n')) rmod->batnextline += 1;
break;
}
}
buff[i] = 0;
buff[-1] = i;
rmod->batnextline += i + 1;
 
return(0);
 
OOPS:
rmod->batfile[0] = 0;
rmod->batnextline = 0;
return(-1);
}
 
 
592,8 → 651,17
}*/
 
do {
char far *cmdline = rmod->inputbuf + 2;
char far *cmdline;
 
if (rmod->echoflag != 0) outputnl(""); /* terminate the previous command with a CR/LF */
 
SKIP_NEWLINE:
 
/* cancel any redirections that may have been set up before */
redir_revert();
 
cmdline = rmod->inputbuf + 2;
 
/* (re)load translation strings if needed */
nls_langreload(BUFFER, *rmod_envseg);
 
604,45 → 672,43
goto EXEC_CMDLINE;
}
 
if (rmod->echoflag != 0) outputnl(""); /* terminate the previous command with a CR/LF */
 
SKIP_NEWLINE:
 
/* print shell prompt (only if ECHO is enabled) */
if (rmod->echoflag != 0) {
char *promptptr = BUFFER;
buildprompt(promptptr, *rmod_envseg);
_asm {
push ax
push dx
mov ah, 0x09
mov dx, promptptr
int 0x21
pop dx
pop ax
}
}
 
/* revert input history terminator to \r */
if (cmdline[-1] != 0) {
cmdline[(unsigned short)(cmdline[-1])] = '\r';
}
 
/* if batch file is being executed -> fetch next line */
if (rmod->batfile[0] != 0) {
cmdline = getbatcmd(BUFFER + sizeof(BUFFER) - 130, rmod);
if (cmdline == NULL) continue;
char *tmpbuff = BUFFER + sizeof(BUFFER) - 256;
if (getbatcmd(tmpbuff, rmod) != 0) { /* end of batch */
redir_revert(); /* cancel redirections (if there were any) */
/* restore echo flag as it was before running the bat file */
rmod->echoflag = 0;
if (rmod->flags & FLAG_ECHO_BEFORE_BAT) rmod->echoflag = 1;
continue;
}
/* output prompt and command on screen if echo on and command is not
* inhibiting it with the @ prefix */
if ((rmod->echoflag != 0) && (tmpbuff[1] != '@')) {
build_and_display_prompt(BUFFER, *rmod_envseg);
outputnl(tmpbuff + 1);
}
/* strip the @ prefix if present, it is no longer useful */
if (tmpbuff[1] == '@') {
memmove(tmpbuff + 1, tmpbuff + 2, tmpbuff[0] + 1);
tmpbuff[0] -= 1; /* update the length byte */
}
cmdline = tmpbuff + 1;
} else {
/* interactive mode: wait for user command line */
/* interactive mode: display prompt (if echo enabled) and wait for user
* command line */
if (rmod->echoflag != 0) build_and_display_prompt(BUFFER, *rmod_envseg);
/* revert input history terminator to \r so DOS or DOSKEY are not confused */
cmdline[(unsigned short)(cmdline[-1])] = '\r';
/* collect user input */
cmdline_getinput(FP_SEG(rmod->inputbuf), FP_OFF(rmod->inputbuf));
/* replace \r by a zero terminator */
cmdline[(unsigned char)(cmdline[-1])] = 0;
}
 
/* if nothing entered, loop again (but without appending an extra CR/LF) */
if (cmdline[-1] == 0) goto SKIP_NEWLINE;
 
/* replace \r by a zero terminator */
cmdline[(unsigned char)(cmdline[-1])] = 0;
 
/* I jump here when I need to exec an initial command (/C or /K) */
EXEC_CMDLINE:
 
670,7 → 736,7
/* perhaps this is a newly launched BAT file */
if ((rmod->batfile[0] != 0) && (rmod->batnextline == 0)) goto SKIP_NEWLINE;
 
/* revert stdout (in case it was redirected) */
/* revert stdout (so the err msg is not redirected) */
redir_revert();
 
/* run_as_external() does not return on success, if I am still alive then