Subversion Repositories SvarDOS

Compare Revisions

Ignore whitespace Rev 956 → Rev 957

/svarcom/trunk/cmd/call.c
0,0 → 1,49
/* This file is part of the SvarCOM project and is published under the terms
* of the MIT license.
*
* Copyright (C) 2021-2022 Mateusz Viste
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
 
/*
* calls one batch program from another.
*
* CALL [drive:][path]filename [batch-parameters]
*
* batch-parameters Specifies any command-line information required by the
* batch program.
*/
 
static enum cmd_result cmd_call(struct cmd_funcparam *p) {
if (cmd_ishlp(p)) {
outputnl("Calls one batch program from another");
outputnl("");
outputnl("CALL [drive:][path]filename [batch-parameters]");
return(CMD_OK);
}
 
/* no argument? do nothing */
if (p->argc == 0) return(CMD_OK);
 
/* change the command by moving batch filename and arguments to the start of the string */
memmove((void *)(p->cmdline), p->cmdline + p->argoffset, strlen(p->cmdline + p->argoffset) + 1);
 
return(CMD_CHANGED_BY_CALL); /* notify callee that command needs to be reevaluated */
}
/svarcom/trunk/cmd.c
22,10 → 22,15
* DEALINGS IN THE SOFTWARE.
*/
 
/* entry point for internal commands
* matches internal commands and executes them
* returns -1 or exit code if processed
* returns -2 if command unrecognized
/* entry point for internal commands, it matches internal commands and
* executes them.
*
* returns one of the following values:
* CMD_OK command executed successfully
* CMD_FAIL command ended in error
* CMD_CHANGED command-line has been modified (used by IF)
* CMD_CHANGED_BY_CALL command-line has been modified by CALL
* CMD_NOTFOUND command unrecognized
*/
 
#include <i86.h>
65,6 → 70,7
 
#include "cmd/_notimpl.c"
#include "cmd/break.c"
#include "cmd/call.c"
#include "cmd/cd.c"
#include "cmd/chcp.c"
#include "cmd/cls.c"
99,6 → 105,7
 
const struct CMD_ID INTERNAL_CMDS[] = {
{"BREAK", cmd_break},
{"CALL", cmd_call},
{"CD", cmd_cd},
{"CHCP", cmd_chcp},
{"CHDIR", cmd_cd},
/svarcom/trunk/cmd.h
29,10 → 29,11
 
/* what cmd_process may return */
enum cmd_result {
CMD_OK, /* command executed and succeeded */
CMD_FAIL, /* command executed and failed */
CMD_NOTFOUND, /* no such command (not an internal command) */
CMD_CHANGED /* command-line transformed, please reparse it */
CMD_OK, /* command executed and succeeded */
CMD_FAIL, /* command executed and failed */
CMD_NOTFOUND, /* no such command (not an internal command) */
CMD_CHANGED, /* command-line transformed, please reparse it */
CMD_CHANGED_BY_CALL /* command-line transformed by CALL */
};
 
/* process internal commands */
/svarcom/trunk/command.c
315,7 → 315,11
}
 
 
static void run_as_external(char *buff, const char *cmdline, unsigned short envseg, struct rmod_props far *rmod, struct redir_data *redir, unsigned char delete_stdin_file) {
/* a few internal flags */
#define DELETE_STDIN_FILE 1
#define CALL_FLAG 2
 
static void run_as_external(char *buff, const char *cmdline, unsigned short envseg, struct rmod_props far *rmod, struct redir_data *redir, unsigned char flags) {
char *cmdfile = buff + 512;
const char far *pathptr;
int lookup;
430,31 → 434,39
 
/* special handling of batch files */
if ((ext != NULL) && (imatch(ext, "bat"))) {
/* free the bat-context linked list, if present, and replace it with a new entry */
while (rmod->bat != NULL) {
struct batctx far *victim = rmod->bat;
rmod->bat = rmod->bat->parent;
rmod_ffree(victim);
struct batctx far *newbat;
 
/* remember the echo flag (in case bat file disables echo, only when starting first bat) */
if (rmod->bat == NULL) {
rmod->flags &= ~FLAG_ECHO_BEFORE_BAT;
if (rmod->flags & FLAG_ECHOFLAG) rmod->flags |= FLAG_ECHO_BEFORE_BAT;
}
rmod->bat = rmod_fmalloc(sizeof(struct batctx), rmod->rmodseg, "SVBATCTX");
if (rmod->bat == NULL) {
outputnl("INTERNAL ERR: OUT OF MEMORY");
 
/* if bat is not called via a CALL, then free the bat-context linked list */
if ((flags & CALL_FLAG) == 0) {
while (rmod->bat != NULL) {
struct batctx far *victim = rmod->bat;
rmod->bat = rmod->bat->parent;
rmod_ffree(victim);
}
}
/* allocate a new bat context */
newbat = rmod_fcalloc(sizeof(struct batctx), rmod->rmodseg, "SVBATCTX");
if (newbat == NULL) {
nls_outputnl_doserr(8); /* insufficient memory */
return;
}
_fmemset(rmod->bat, 0, sizeof(struct batctx));
 
/* copy truename of the bat file to rmod buff */
_fstrcpy(rmod->bat->fname, cmdfile);
 
/* fill the newly allocated batctx structure */
_fstrcpy(newbat->fname, cmdfile); /* truename of the BAT file */
/* explode args of the bat file and store them in rmod buff */
cmd_explode(buff, cmdline, NULL);
_fmemcpy(rmod->bat->argv, buff, sizeof(rmod->bat->argv));
_fmemcpy(newbat->argv, buff, sizeof(newbat->argv));
 
/* reset the 'next line to execute' counter */
rmod->bat->nextline = 0;
/* remember the echo flag (in case bat file disables echo) */
rmod->flags &= ~FLAG_ECHO_BEFORE_BAT;
if (rmod->flags & FLAG_ECHOFLAG) rmod->flags |= FLAG_ECHO_BEFORE_BAT;
/* push the new bat to the top of rmod's linked list */
newbat->parent = rmod->bat;
rmod->bat = newbat;
 
return;
}
 
466,7 → 478,7
char far *farptr = MK_FP(rmod->rmodseg, RMOD_OFFSET_STDINFILE);
char far *delstdin = MK_FP(rmod->rmodseg, RMOD_OFFSET_STDIN_DEL);
_fstrcpy(farptr, redir->stdinfile);
if (delete_stdin_file) {
if (flags & DELETE_STDIN_FILE) {
*delstdin = redir->stdinfile[0];
} else {
*delstdin = 0;
744,6 → 756,7
}
 
 
 
int main(void) {
static struct config cfg;
static unsigned short far *rmod_envseg;
754,7 → 767,7
static struct redir_data redirprops;
static enum cmd_result cmdres;
static unsigned short i; /* general-purpose variable for short-lived things */
static unsigned char delete_stdin_file;
static unsigned char flags;
 
rmod = rmod_find(BUFFER_len);
if (rmod == NULL) {
828,10 → 841,10
if (rmod->awaitingcmd[0] != 0) {
_fstrcpy(cmdline, rmod->awaitingcmd);
rmod->awaitingcmd[0] = 0;
delete_stdin_file = 1;
flags |= DELETE_STDIN_FILE;
goto EXEC_CMDLINE;
} else {
delete_stdin_file = 0;
flags &= ~DELETE_STDIN_FILE;
}
 
/* skip user input if I have a command to exec (/C or /K) */
847,7 → 860,7
struct batctx far *victim = rmod->bat;
rmod->bat = rmod->bat->parent;
rmod_ffree(victim);
/* end of batch? then restore echo flag as it was before running the bat file */
/* end of batch? then restore echo flag as it was before running the (first) bat file */
if (rmod->bat == NULL) {
rmod->flags &= ~FLAG_ECHOFLAG;
if (rmod->flags & FLAG_ECHO_BEFORE_BAT) rmod->flags |= FLAG_ECHOFLAG;
898,16 → 911,22
}
 
/* try matching (and executing) an internal command */
cmdres = cmd_process(rmod, *rmod_envseg, cmdline, BUFFER, sizeof(BUFFER), &redirprops, delete_stdin_file);
cmdres = cmd_process(rmod, *rmod_envseg, cmdline, BUFFER, sizeof(BUFFER), &redirprops, flags & DELETE_STDIN_FILE);
if ((cmdres == CMD_OK) || (cmdres == CMD_FAIL)) {
/* internal command executed */
continue;
} else if (cmdres == CMD_CHANGED) { /* cmdline changed, needs to be reprocessed */
goto EXEC_CMDLINE;
} else if (cmdres == CMD_CHANGED_BY_CALL) { /* cmdline changed *specifically* by CALL */
/* the distinction is important since it changes the way batch files are processed */
flags |= CALL_FLAG;
goto EXEC_CMDLINE;
} else if (cmdres == CMD_NOTFOUND) {
/* this was not an internal command, try matching an external command */
run_as_external(BUFFER, cmdline, *rmod_envseg, rmod, &redirprops, delete_stdin_file);
/* perhaps this is a newly launched BAT file */
run_as_external(BUFFER, cmdline, *rmod_envseg, rmod, &redirprops, flags);
flags &= ~CALL_FLAG; /* reset callflag to make sure it is processed only once */
 
/* is it a newly launched BAT file? */
if ((rmod->bat != NULL) && (rmod->bat->nextline == 0)) goto SKIP_NEWLINE;
/* run_as_external() does not return on success, if I am still alive then
* external command failed to execute */
/svarcom/trunk/history.txt
3,6 → 3,11
=== SvarCOM's history / changelog ===
 
 
=== ver 2022.1 (xx.xx.xxxx) ==================================================
 
- added CALL support for calling batch files from within batch files
 
 
=== ver 2022.0 (01.02.2022) ==================================================
 
- added "global executable links" support (new command: LN)
/svarcom/trunk/rmodinit.c
228,9 → 228,10
 
 
/* allocates bytes of far memory, flags it as belonging to rmod
* the new block can be optionally flagged as 'ident' (if not null)
* the new block can be optionally flagged as 'ident' (if not null) and zero
* out the newly allocated memory.
* returns a far ptr to the allocated block, or NULL on error */
void far *rmod_fmalloc(unsigned short bytes, unsigned short rmod_seg, char *ident) {
void far *rmod_fcalloc(unsigned short bytes, unsigned short rmod_seg, char *ident) {
unsigned short far *owner;
unsigned short newseg = 0;
 
289,11 → 290,14
}
}
 
/* zero out the memory before handing it out */
_fmemset(MK_FP(newseg, 0), 0, bytes);
 
return(MK_FP(newseg, 0));
}
 
 
/* free memory previously allocated by rmod_ffmalloc() */
/* free memory previously allocated by rmod_fcalloc() */
void rmod_ffree(void far *ptr) {
unsigned short ptrseg;
unsigned short myseg = 0;
/svarcom/trunk/rmodinit.h
68,8 → 68,13
struct rmod_props far *rmod_find(unsigned short rmodcore_len);
void rmod_updatecomspecptr(unsigned short rmod_seg, unsigned short env_seg);
 
/* allocate */
void far *rmod_fmalloc(unsigned short bytes, unsigned short rmod_seg, char *ident);
/* allocates bytes of far memory, flags it as belonging to rmod
* the new block can be optionally flagged as 'ident' (if not null) and zero
* out the newly allocated memory.
* returns a far ptr to the allocated block, or NULL on error */
void far *rmod_fcalloc(unsigned short bytes, unsigned short rmod_seg, char *ident);
 
/* free memory previously allocated by rmod_fcalloc() */
void rmod_ffree(void far *ptr);
 
#endif
/svarcom/trunk/todo.txt
8,7 → 8,7
=== HIGH PRIORITY ============================================================
 
int 24h handler (abort, retry, fail, ignore)
advanced batch constructs: CALL, FOR, GOTO
advanced batch constructs: FOR, GOTO
IF EXIST on an empty drive should not lead to the 'Abort, Retry, Fail' prompt