/svarcom/trunk/cmd/_notimpl.c |
---|
0,0 → 1,8 |
/* |
* handler for all "not implemented yet" commands |
*/ |
static int cmd_notimpl(struct cmd_funcparam *p) { |
outputnl("This command is not implemented yet. Sorry!"); |
return(-1); |
} |
/svarcom/trunk/cmd/cd.c |
---|
0,0 → 1,124 |
/* |
* chdir |
* |
* displays the name of or changes the current directory. |
* |
* CHDIR [drive:][path] |
* CD.. |
* |
* Type CD drive: to display the current directory in the specified drive. |
* Type CD without parameters to display the current drive and directory. |
*/ |
/* display current path drive d (A=1, B=2, etc) |
* returns 0 on success, doserr otherwise */ |
static unsigned short cmd_cd_curpathfordrv(char *buff, unsigned char d) { |
unsigned short r = 0; |
buff[0] = d + 'A' - 1; |
buff[1] = ':'; |
buff[2] = '\\'; |
_asm { |
push si |
push ax |
push dx |
mov ah, 0x47 /* get current directory */ |
mov dl, [d] /* A: = 1, B: = 2, etc */ |
mov si, buff /* append cur dir to buffer */ |
add si, 3 /* skip the present drive:\ prefix */ |
int 0x21 |
jnc DONE |
mov [r], ax /* copy result from ax */ |
DONE: |
pop dx |
pop ax |
pop si |
} |
return(r); |
} |
static int cmd_cd(struct cmd_funcparam *p) { |
char *buffptr = p->BUFFER; |
/* CD /? */ |
if (cmd_ishlp(p)) { |
outputnl("Displays the name of or changes the current directory."); |
outputnl(""); |
outputnl("CHDIR [drive:][path]"); |
outputnl("CHDIR[..]"); |
outputnl("CD [drive:][path]"); |
outputnl("CD[..]"); |
outputnl(""); |
outputnl(".. Specifies that you want to change to the parent directory."); |
outputnl(""); |
outputnl("Type CD drive: to display the current directory in the specified drive."); |
outputnl("Type CD without parameters to display the current drive and directory."); |
return(-1); |
} |
/* one argument max */ |
if (p->argc > 1) { |
outputnl("Too many parameters"); |
return(-1); |
} |
/* no argument? display current drive and dir ("CWD") */ |
if (p->argc == 0) { |
unsigned char drv = 0; |
_asm { |
push ax |
push dx |
push si |
mov ah, 0x19 /* get current default drive */ |
int 0x21 /* al = drive (00h = A:, 01h = B:, etc) */ |
inc al /* convert to 1=A, 2=B, etc */ |
mov [drv], al |
} |
cmd_cd_curpathfordrv(buffptr, drv); |
outputnl(buffptr); |
return(-1); |
} |
/* argument can be either a drive (D:) or a path */ |
if (p->argc == 1) { |
const char *arg = p->argv[0]; |
unsigned short err = 0; |
/* drive (CD B:) */ |
if ((arg[0] != '\\') && (arg[1] == ':') && (arg[2] == 0)) { |
unsigned char drive = arg[0]; |
if (drive >= 'a') { |
drive -= ('a' - 1); |
} else { |
drive -= ('A' - 1); |
} |
err = cmd_cd_curpathfordrv(buffptr, drive); |
if (err == 0) outputnl(buffptr); |
} else { /* path */ |
_asm { |
push dx |
push ax |
mov ah, 0x3B /* CHDIR (set current directory) */ |
mov dx, arg |
int 0x21 |
jnc DONE |
mov [err], ax |
DONE: |
pop ax |
pop dx |
} |
} |
if (err != 0) { |
outputnl(doserr(err)); |
} |
} |
return(-1); |
} |
/svarcom/trunk/cmd/del.c |
---|
0,0 → 1,107 |
/* |
* del/erase |
*/ |
static int cmd_del(struct cmd_funcparam *p) { |
const char *delspec = NULL; |
unsigned short err = 0; |
unsigned short confirmflag = 0; |
unsigned short i; |
unsigned short pathlimit = 0; |
char *buff = p->BUFFER; |
struct DTA *dta = (void *)0x80; /* use the default DTA at location 80h in PSP */ |
char *fname = dta->fname; |
if (cmd_ishlp(p)) { |
outputnl("Deletes one or more files."); |
outputnl(""); |
outputnl("DEL [drive:][path]filename [/P]"); |
outputnl("ERASE [drive:][path]filename [/P]"); |
outputnl(""); |
outputnl("[drive:][path]filename Specifies the file(s) to delete."); |
outputnl("/P Prompts for confirmation before deleting each file."); |
return(-1); |
} |
if (p->argc == 0) { |
outputnl("Required parameter missing"); |
return(-1); |
} |
/* scan argv for delspec and possible /p or /v */ |
for (i = 0; i < p->argc; i++) { |
/* delspec? */ |
if (p->argv[i][0] == '/') { |
if (imatch(p->argv[i], "/p")) { |
confirmflag = 1; |
} else { |
output("Invalid switch:"); |
output(" "); |
outputnl(p->argv[i]); |
return(-1); |
} |
} else if (delspec != NULL) { /* otherwise its a delspec */ |
outputnl("Too many parameters"); |
return(-1); |
} else { |
delspec = p->argv[i]; |
} |
} |
/* convert path to canonical form */ |
file_truename(delspec, buff); |
/* is delspec pointing at a directory? if so, add a \*.* */ |
{ int attr = file_getattr(delspec); |
if ((attr > 0) && (attr & DOS_ATTR_DIR)) strcat(buff, "\\????????.???"); |
} |
/* parse delspec in buff and remember where last backslash or slash is */ |
for (i = 0; buff[i] != 0; i++) if (buff[i] == '\\') pathlimit = i + 1; |
/* is this about deleting all content inside a directory? if no per-file |
* confirmation set, ask for a global confirmation */ |
if ((confirmflag == 0) && (imatch(buff + pathlimit, "????????.???"))) { |
outputnl("All files in directory will be deleted!"); |
if (askchoice("Are you sure (Y/N)?", "YN") != 0) return(-1); |
} |
for (i = 0;; i = 1) { |
/* exec FindFirst or FindNext */ |
if (i == 0) { |
err = findfirst(dta, buff, DOS_ATTR_RO | DOS_ATTR_SYS | DOS_ATTR_HID); |
} else { |
err = findnext(dta); |
} |
if (err != 0) break; |
/* ask if confirmation required: PLIK.TXT Delete (Y/N)? */ |
if (confirmflag) { |
strcpy(buff + pathlimit, fname); /* note: buff contained the search pattern but it no longer needed so I can reuse it now */ |
output(buff); |
output(" \t"); |
if (askchoice("Delete (Y/N)?", "YN") != 0) continue; |
} |
/* del found file */ |
_asm { |
mov ah, 0x41 /* delete a file, DS:DX points to an ASCIIZ filespec (no wildcards allowed) */ |
mov dx, fname |
int 0x21 |
jnc DONE |
mov [err], ax |
DONE: |
} |
if (err != 0) { |
output(fname); |
output(": "); |
outputnl(doserr(err)); |
break; |
} |
} |
return(-1); |
} |
/svarcom/trunk/cmd/dir.c |
---|
0,0 → 1,133 |
/* |
* dir |
* |
* Displays a list of files and subdirectories in a directory. |
* |
* DIR [drive:][path][filename] [/P] [/W] [/A[:]attributes] [/O[[:]sortorder]] [/S] [/B] [/L] |
* |
* /P Pauses after each screenful of information. |
* /W Uses wide list format. |
* |
* /A Displays file with specified attributes: |
* D Directories R Read-only files H Hidden files |
* A Ready for archiving S System files - prefix meaning "not" |
* |
* /O List files in sorted order: |
* N by name S by size E by extension |
* D by date G group dirs first - prefix to reverse order |
* |
* /S Displays files in specified directory and all subdirectories. |
* /B Uses bare format (no heading information or summary) |
* /L Uses lowercases |
*/ |
/* NOTE: /A attributes are matched in an exclusive way, ie. only files with |
* the specified attributes are matched. This is different from how DOS |
* itself matches attributes hence DIR cannot rely on the attributes |
* filter within FindFirst. |
* |
* NOTE: Multiple /A are not supported - only the last one is significant. |
*/ |
static int cmd_dir(struct cmd_funcparam *p) { |
const char *filespecptr = NULL; |
struct DTA *dta = (void *)0x80; /* set DTA to its default location at 80h in PSP */ |
int i; |
unsigned short availrows; /* counter of available rows on display (used for /P) */ |
#define DIR_FLAG_PAUSE 1 |
#define DIR_FLAG_WIDE 2 |
#define DIR_FLAG_RECUR 4 |
#define DIR_FLAG_BARE 8 |
#define DIR_FLAG_LCASE 16 |
unsigned char flags = 0; |
// unsigned char attribs_show = 0; /* show only files with ALL these attribs */ |
// unsigned char attribs_hide = 0; /* hide files with ANY of these attribs */ |
if (cmd_ishlp(p)) { |
outputnl("Displays a list of files and subdirectories in a directory"); |
outputnl(""); |
outputnl("DIR [drive:][path][filename] [/P] [/W] [/A[:]attributes] [/O[[:]sortorder]] [/S] [/B] [/L]"); |
outputnl(""); |
outputnl("/P Pauses after each screenful of information"); |
outputnl("/W Uses wide list format"); |
outputnl(""); |
outputnl("/A Displays files with specified attributes:"); |
outputnl(" D Directories R Read-only files H Hidden files"); |
outputnl(" A Ready for archiving S System files - prefix meaning \"not\""); |
outputnl(""); |
outputnl("/O List files in sorted order:"); |
outputnl(" N by name S by size E by extension"); |
outputnl(" D by date G group dirs first - prefix to reverse order"); |
outputnl(""); |
outputnl("/S Displays files in specified directory and all subdirectories"); |
outputnl("/B Uses bare format (no heading information or summary)"); |
outputnl("/L Uses lowercases"); |
/* TODO FIXME REMOVE THIS ONCE ALL IMPLEMENTED */ |
outputnl("\r\n*** THIS COMMAND IS NOT FULLY IMPLEMENTED YET ***"); |
return(-1); |
} |
/* parse command line */ |
for (i = 0; i < p->argc; i++) { |
if (p->argv[i][0] == '/') { |
char arg; |
char neg = 0; |
/* detect negations and get actual argument */ |
if (p->argv[i][1] == '-') neg = 1; |
arg = p->argv[i][1 + neg]; |
/* */ |
switch (arg) { |
case 'a': |
case 'A': |
/* TODO */ |
outputnl("/A NOT IMPLEMENTED YET"); |
return(-1); |
break; |
case 'p': |
case 'P': |
flags |= DIR_FLAG_PAUSE; |
if (neg) flags &= (0xff ^ DIR_FLAG_PAUSE); |
break; |
default: |
outputnl("Invalid switch"); |
return(-1); |
} |
} else { /* filespec */ |
if (filespecptr != NULL) { |
outputnl("Too many parameters"); |
return(-1); |
} |
filespecptr = p->argv[i]; |
} |
} |
if (filespecptr == NULL) filespecptr = "."; |
file_truename(filespecptr, p->BUFFER); |
/* if dir then append \????????.??? */ |
i = file_getattr(p->BUFFER); |
if ((i > 0) && (i & DOS_ATTR_DIR)) strcat(p->BUFFER, "\\????????.???"); |
if (findfirst(dta, p->BUFFER, DOS_ATTR_RO | DOS_ATTR_HID | DOS_ATTR_SYS | DOS_ATTR_DIR | DOS_ATTR_ARC) != 0) return(-1); |
availrows = screen_getheight(); |
outputnl(dta->fname); |
availrows--; |
while (findnext(dta) == 0) { |
outputnl(dta->fname); |
if (flags & DIR_FLAG_PAUSE) { |
availrows--; |
if (availrows < 2) { |
press_any_key(); |
availrows = screen_getheight(); |
} |
} |
} |
return(-1); |
} |
/svarcom/trunk/cmd/exit.c |
---|
0,0 → 1,16 |
/* |
* exit |
* |
* Quits the COMMAND.COM program (command interpreter) |
* |
*/ |
static int cmd_exit(struct cmd_funcparam *p) { |
if (cmd_ishlp(p)) { |
outputnl("EXIT\r\n"); |
outputnl("Quits the COMMAND.COM program (command interpreter)"); |
} else { |
exit(0); |
} |
return(-1); |
} |
/svarcom/trunk/cmd/mkdir.c |
---|
0,0 → 1,50 |
/* |
* mkdir |
*/ |
static int cmd_mkdir(struct cmd_funcparam *p) { |
const char *dname = p->argv[0]; |
unsigned short err = 0; |
if (cmd_ishlp(p)) { |
outputnl("Creates a directory"); |
outputnl(""); |
outputnl("MKDIR [drive:]path"); |
outputnl("MD [drive:]path"); |
return(-1); |
} |
if (p->argc == 0) { |
outputnl("Required parameter missing"); |
return(-1); |
} |
if (p->argc > 1) { |
outputnl("Too many parameters"); |
return(-1); |
} |
if (p->argv[0][0] == '/') { |
outputnl("Invalid parameter"); |
return(-1); |
} |
_asm { |
push ax |
push dx |
mov ah, 0x39 /* create new directory, DS:DX points to ASCIIZ dir name */ |
mov dx, [dname] |
int 0x21 |
jnc DONE |
mov [err], ax |
DONE: |
pop dx |
pop ax |
} |
if (err != 0) outputnl(doserr(err)); |
return(-1); |
} |
/svarcom/trunk/cmd/path.c |
---|
0,0 → 1,67 |
/* |
* path |
* |
* Displays or sets a search path for executable files. |
*/ |
static int cmd_path(struct cmd_funcparam *p) { |
char *buff = p->BUFFER; |
/* help screen (/?) */ |
if (cmd_ishlp(p)) { |
output("Displays or sets a search path for executable files.\r\n" |
"\r\n" |
"PATH [[drive:]path[;...]]\r\n" |
"PATH ;\r\n" |
"\r\n" |
"Type PATH ; to clear all search-path settings and direct DOS to search\r\n" |
"only in the current directory.\r\n" |
"\r\n" |
"Type PATH without parameters to display the current path.\r\n"); |
return(-1); |
} |
/* no parameter - display current path */ |
if (p->argc == 0) { |
char far *curpath = env_lookup(p->env_seg, "PATH"); |
if (curpath == NULL) { |
outputnl("No Path"); |
} else { |
unsigned short i; |
for (i = 0;; i++) { |
buff[i] = curpath[i]; |
if (buff[i] == 0) break; |
} |
outputnl(buff); |
} |
return(-1); |
} |
/* more than 1 parameter */ |
if (p->argc > 1) { |
outputnl("Too many parameters"); |
return(-1); |
} |
/* IF HERE: THERE IS EXACTLY 1 ARGUMENT (argc == 1) */ |
/* reset the PATH string (PATH ;) */ |
if (imatch(p->argv[0], ";")) { |
env_dropvar(p->env_seg, "PATH"); |
return(-1); |
} |
/* otherwise set PATH to whatever is passed on command-line */ |
{ |
unsigned short i; |
strcpy(buff, "PATH="); |
for (i = 0;; i++) { |
buff[i + 5] = p->argv[0][i]; |
if (buff[i + 5] == '\r') break; |
} |
buff[i + 5] = 0; |
env_setvar(p->env_seg, buff); |
} |
return(-1); |
} |
/svarcom/trunk/cmd/prompt.c |
---|
0,0 → 1,37 |
/* |
* prompt |
* |
* Changes the DOS command prompt. |
* |
*/ |
static int cmd_prompt(struct cmd_funcparam *p) { |
if (cmd_ishlp(p)) { |
outputnl("Changes the DOS command prompt."); |
outputnl(""); |
outputnl("PROMPT [new command prompt specification]"); |
return(-1); |
} |
/* no parameter - restore default prompt path */ |
if (p->argc == 0) { |
env_dropvar(p->env_seg, "PROMPT"); |
return(-1); |
} |
/* otherwise set PROMPT to whatever is passed on command-line */ |
{ |
unsigned short i; |
char *buff = p->BUFFER; |
strcpy(buff, "PROMPT="); |
for (i = 0;; i++) { |
buff[i + 7] = p->cmdline[p->argoffset + i]; |
if (buff[i + 7] == '\r') break; |
} |
buff[i + 7] = 0; |
env_setvar(p->env_seg, buff); |
} |
return(-1); |
} |
/svarcom/trunk/cmd/rmdir.c |
---|
0,0 → 1,50 |
/* |
* rmdir |
*/ |
static int cmd_rmdir(struct cmd_funcparam *p) { |
const char *dname = p->argv[0]; |
unsigned short err = 0; |
if (cmd_ishlp(p)) { |
outputnl("Removes (deletes) a directory"); |
outputnl(""); |
outputnl("RMDIR [drive:]path"); |
outputnl("RD [drive:]path"); |
return(-1); |
} |
if (p->argc == 0) { |
outputnl("Required parameter missing"); |
return(-1); |
} |
if (p->argc > 1) { |
outputnl("Too many parameters"); |
return(-1); |
} |
if (p->argv[0][0] == '/') { |
outputnl("Invalid parameter"); |
return(-1); |
} |
_asm { |
push ax |
push dx |
mov ah, 0x3a /* delete a directory, DS:DX points to ASCIIZ dir name */ |
mov dx, [dname] |
int 0x21 |
jnc DONE |
mov [err], ax |
DONE: |
pop dx |
pop ax |
} |
if (err != 0) outputnl(doserr(err)); |
return(-1); |
} |
/svarcom/trunk/cmd/set.c |
---|
0,0 → 1,72 |
/* |
* set [varname[=value]] |
* |
* value cannot contain any '=' character, but it can contain spaces |
* varname can also contain spaces |
*/ |
static int cmd_set(struct cmd_funcparam *p) { |
char far *env = MK_FP(p->env_seg, 0); |
char *buff = p->BUFFER; |
if (cmd_ishlp(p)) { |
outputnl("Displays, sets, or removes DOS environment variables"); |
outputnl(""); |
outputnl("SET [variable=[string]]"); |
outputnl(""); |
outputnl("variable Specifies the environment-variable name"); |
outputnl("string Specifies a series of characters to assign to the variable"); |
outputnl(""); |
outputnl("Type SET without parameters to display the current environment variables."); |
} |
/* no arguments - display content */ |
if (p->argc == 0) { |
while (*env != 0) { |
unsigned short i; |
/* copy string to local buff for display */ |
for (i = 0;; i++) { |
buff[i] = *env; |
env++; |
if (buff[i] == 0) break; |
} |
outputnl(buff); |
} |
} else { /* set variable (do not rely on argv, SET has its own rules...) */ |
const char far *ptr; |
unsigned short i; |
/* locate the first space */ |
for (ptr = p->cmdline; *ptr != ' '; ptr++); |
/* now locate the first non-space: that's where the variable name begins */ |
for (; *ptr == ' '; ptr++); |
/* copy variable to buff and switch it upercase */ |
i = 0; |
for (; *ptr != '='; ptr++) { |
if (*ptr == '\r') goto syntax_err; |
buff[i] = *ptr; |
if ((buff[i] >= 'a') && (buff[i] <= 'z')) buff[i] -= ('a' - 'A'); |
i++; |
} |
/* copy value now */ |
while (*ptr != '\r') { |
buff[i++] = *ptr; |
ptr++; |
} |
/* terminate buff */ |
buff[i] = 0; |
/* commit variable to environment */ |
i = env_setvar(p->env_seg, buff); |
if (i == ENV_INVSYNT) goto syntax_err; |
if (i == ENV_NOTENOM) outputnl("Not enough available space within the environment block"); |
} |
return(-1); |
syntax_err: |
outputnl("Syntax error"); |
return(-1); |
} |
/svarcom/trunk/cmd/type.c |
---|
0,0 → 1,86 |
/* |
* type |
*/ |
static int cmd_type(struct cmd_funcparam *p) { |
char *buff = p->BUFFER; |
const char *fname = p->argv[0]; |
unsigned short err = 0; |
if (cmd_ishlp(p)) { |
outputnl("Displays the contents of a text file."); |
outputnl(""); |
outputnl("TYPE [drive:][path]filename"); |
return(-1); |
} |
if (p->argc == 0) { |
outputnl("Required parameter missing"); |
return(-1); |
} |
if (p->argc > 1) { |
outputnl("Too many parameters"); |
return(-1); |
} |
/* if here then display the file */ |
_asm { |
push ax |
push bx |
push cx |
push dx |
push si |
mov ax, 0x3d00 /* open file via handle, access mode in AL (0 = read) */ |
mov dx, fname |
int 0x21 /* file handle in ax on success (CF clear) */ |
jnc FILE_OPEN_OK |
mov [err], ax /* on error AX contains the DOS err code */ |
jmp FOPENFAIL |
FILE_OPEN_OK: |
/* copy obtained file handle to BX */ |
mov bx, ax |
READNEXTBLOCK: |
/* read file block by block */ |
mov cx, 1024 /* read 1K at a time */ |
mov dx, buff |
mov ah, 0x3f /* read CX bytes from file handle in BX and write to DS:DX */ |
int 0x21 /* CF set on error, AX=errno or AX=number of bytes read */ |
jc GOTERROR /* abort on error */ |
test ax, ax /* EOF? */ |
jz ENDFILE |
/* display read block (AX=len) */ |
mov si, dx /* preset DS:SI to DS:DX (DL will be reused soon) */ |
mov cx, ax /* set loop count to CX */ |
mov ah, 0x02 /* write character in DL to stdout */ |
NEXTCHAR: |
mov dl, [si] |
inc si |
int 0x21 |
loopnz NEXTCHAR /* CX-- ; jnz NEXTCHAR (display CX characters) */ |
/* read (and display) next block */ |
jmp READNEXTBLOCK |
GOTERROR: |
mov [err], ax |
ENDFILE: |
/* close file */ |
mov ah, 0x3e /* close file handle (file handle already in BX) */ |
int 0x21 |
FOPENFAIL: |
pop si |
pop dx |
pop cx |
pop bx |
pop ax |
} |
if (err != 0) outputnl(doserr(err)); |
return(-1); |
} |
/svarcom/trunk/cmd/ver.c |
---|
0,0 → 1,40 |
/* |
* ver |
*/ |
#define PVER "20211027" |
static int cmd_ver(struct cmd_funcparam *p) { |
char *buff = p->BUFFER; |
unsigned char maj = 0, min = 0; |
/* help screen */ |
if (cmd_ishlp(p)) { |
outputnl("Displays the DOS version."); |
return(-1); |
} |
if (p->argc != 0) { |
outputnl("Invalid parameter"); |
return(-1); |
} |
_asm { |
push ax |
push bx |
push cx |
mov ah, 0x30 /* Get DOS version number */ |
int 0x21 /* AL=maj_ver_num AH=min_ver_num BX,CX=OEM */ |
mov [maj], al |
mov [min], ah |
pop cx |
pop bx |
pop ax |
} |
sprintf(buff, "DOS kernel version %u.%u", maj, min); |
outputnl(buff); |
outputnl("SvarCOM shell ver " PVER); |
return(-1); |
} |
/svarcom/trunk/cmd/verify.c |
---|
0,0 → 1,62 |
/* |
* verify |
*/ |
static int cmd_verify(struct cmd_funcparam *p) { |
if (cmd_ishlp(p)) { |
outputnl("Tells DOS whether to verify that files are written correctly to disk."); |
outputnl("\r\nVERIFY [ON | OFF]\r\n"); |
outputnl("Type VERIFY without a parameter to display its current setting."); |
return(-1); |
} |
if (p->argc > 1) { |
outputnl("Too many parameters"); |
return(-1); |
} |
if (p->argc == 0) { |
unsigned char verstate = 0; |
_asm { |
push ax |
mov ah, 0x54 /* Get VERIFY status */ |
int 0x21 /* AL == 0 (off) or AL == 1 (on) */ |
mov [verstate], al |
pop ax |
} |
if (verstate == 0) { |
outputnl("VERIFY is off"); |
} else { |
outputnl("VERIFY is on"); |
} |
return(-1); |
} |
/* argc == 1*/ |
if (imatch(p->argv[0], "on")) { |
_asm { |
push ax |
push dx |
mov ax, 0x2e01 /* set verify ON */ |
xor dl, dl /* apparently required by MS-DOS 2.x */ |
int 0x21 |
pop dx |
pop ax |
} |
} else if (imatch(p->argv[0], "off")) { |
_asm { |
push ax |
push dx |
mov ax, 0x2e00 /* set verify OFF */ |
xor dl, dl /* apparently required by MS-DOS 2.x */ |
int 0x21 |
pop dx |
pop ax |
} |
} else { |
outputnl("Must specify ON or OFF"); |
} |
return(-1); |
} |