/svarcom/tags/svarcom-2022.1/cmd/_notimpl.c |
---|
0,0 → 1,32 |
/* This file is part of the SvarCOM project and is published under the terms |
* of the MIT license. |
* |
* Copyright (C) 2021 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. |
*/ |
/* |
* handler for all "not implemented yet" commands |
*/ |
static enum cmd_result cmd_notimpl(struct cmd_funcparam *p) { |
outputnl("This command is not implemented yet. Sorry!"); |
return(CMD_FAIL); |
} |
/svarcom/tags/svarcom-2022.1/cmd/break.c |
---|
0,0 → 1,90 |
/* 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. |
*/ |
/* |
* break |
*/ |
static enum cmd_result cmd_break(struct cmd_funcparam *p) { |
unsigned char brkflag = 0; |
if (cmd_ishlp(p)) { |
nls_outputnl(14,0); /* "Sets or clears extended CTRL+C checking" */ |
outputnl(""); |
outputnl("BREAK [ON | OFF]"); |
outputnl(""); |
nls_outputnl(14,1); /* "Type BREAK without a parameter to display the current BREAK setting." */ |
return(CMD_OK); |
} |
/* no params: display current break state */ |
if (p->argc == 0) { |
_asm { |
push ax |
push dx |
mov ax, 0x3300 /* query break-check flag */ |
int 0x21 /* status (0=OFF, 1=ON) in DL */ |
mov [brkflag], dl |
pop dx |
pop ax |
} |
if (brkflag == 0) { |
nls_outputnl(14,2); /* "BREAK is off" */ |
} else { |
nls_outputnl(14,3); /* "BREAK is on" */ |
} |
return(CMD_OK); |
} |
/* too many params? */ |
if (p->argc > 1) { |
nls_outputnl(0,4); |
return(CMD_FAIL); |
} |
/* exactly 1 parameter - "on" or "off" */ |
if (imatch(p->argv[0], "on")) { |
brkflag = 1; |
} else if (!imatch(p->argv[0], "off")) { |
nls_outputnl(0,6); /* "Invalid parameter" */ |
return(CMD_FAIL); |
} |
/* set break accordingly to brkflag */ |
_asm { |
push ax |
push dx |
mov ax, 0x3301 /* set break-check level */ |
mov dl, [brkflag] /* 0=OFF 1=ON */ |
int 0x21 |
pop dx |
pop ax |
} |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/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)) { |
nls_outputnl(13,0); /* "Calls one batch program from another" */ |
outputnl(""); |
nls_outputnl(13,1); /* "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/tags/svarcom-2022.1/cmd/cd.c |
---|
0,0 → 1,106 |
/* 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. |
*/ |
/* |
* 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. |
*/ |
static enum cmd_result cmd_cd(struct cmd_funcparam *p) { |
char *buffptr = p->BUFFER; |
/* CD /? */ |
if (cmd_ishlp(p)) { |
nls_outputnl(12,0); /* "Displays the name of or changes the current directory." */ |
outputnl(""); |
nls_outputnl(12,1); /* "CHDIR [drive:][path]" */ |
nls_outputnl(12,2); /* "CHDIR[..]" */ |
nls_outputnl(12,3); /* "CD [drive:][path]" */ |
nls_outputnl(12,4); /* "CD[..]" */ |
outputnl(""); |
nls_outputnl(12,5); /* ".. Specifies that you want to change to the parent directory." */ |
outputnl(""); |
nls_outputnl(12,6); /* "Type CD drive: to display the current directory in the specified drive." */ |
nls_outputnl(12,7); /* "Type CD without parameters to display the current drive and directory." */ |
return(CMD_OK); |
} |
/* one argument max */ |
if (p->argc > 1) { |
nls_outputnl(0,4); /* "Too many parameters" */ |
return(CMD_FAIL); |
} |
/* no argument? display current drive and dir ("CWD") */ |
if (p->argc == 0) { |
curpathfordrv(buffptr, 0); |
outputnl(buffptr); |
return(CMD_OK); |
} |
/* 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 = 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) { |
nls_outputnl_doserr(err); |
return(CMD_FAIL); |
} |
} |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/cmd/chcp.c |
---|
0,0 → 1,117 |
/* 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. |
*/ |
/* |
* chcp |
*/ |
static enum cmd_result cmd_chcp(struct cmd_funcparam *p) { |
unsigned short nnn = 0; |
unsigned short errcode = 0; |
if (cmd_ishlp(p)) { |
nls_outputnl(11,0); /* "Displays or sets the active code page number" */ |
outputnl(""); |
nls_outputnl(11,1); /* "CHCP [nnn]" */ |
outputnl(""); |
nls_outputnl(11,2); /* "nnn Specifies a code page number" */ |
outputnl(""); |
nls_outputnl(11,3); /* "Type CHCP without a parameter to display the active code page number." */ |
return(CMD_OK); |
} |
/* too many parameters */ |
if (p->argc > 1) { |
nls_outputnl(0,4); /* "Too many parameters" */ |
return(CMD_FAIL); |
} |
/* one param? must be numeric in range 1+ */ |
if (p->argc == 1) { |
unsigned char nlsfuncflag = 0; |
if (atous(&nnn, p->argv[0]) != 0) { |
nls_outputnl(11,4); /* "Invalid code page number" */ |
return(CMD_FAIL); |
} |
_asm { |
/* verify that NLSFUNC is installed */ |
push ax |
push bx |
mov ax, 0x1400 /* DOS 3+ -- is NLSFUNC.EXE installed? */ |
int 0x2f /* AL = 0xff -> installed */ |
cmp al, 0xff |
jne DONE |
mov [nlsfuncflag], 1 |
/* set code page to nnn */ |
mov ax, 0x6602 /* DOS 3.3+ -- Activate Code Page */ |
mov bx, [nnn] |
int 0x21 /* CF set on error and err code in AX */ |
jnc DONE |
mov [errcode], ax /* store err code in nnn on failure */ |
DONE: |
pop bx |
pop ax |
} |
if (nlsfuncflag == 0) { |
nls_outputnl(11,5); /* "NLSFUNC not installed" */ |
} else if (errcode != 0) { |
nls_outputnl(11,6); /* "Failed to change code page" */ |
return(CMD_FAIL); |
} |
} else { /* no parameter given: display active code page */ |
_asm { |
push ax |
push bx |
push dx |
mov ax, 0x6601 /* DOS 3.3+ -- Query Active Code Page */ |
int 0x21 /* CF set on error, current CP in BX */ |
mov [nnn], bx |
jnc DONE |
mov [errcode], ax |
DONE: |
pop dx |
pop bx |
pop ax |
} |
if (errcode == 0) { |
nls_output(11,7); /* Active code page: */ |
output(" "); |
sprintf(p->BUFFER, "%u", nnn); |
outputnl(p->BUFFER); |
} else { |
nls_outputnl_doserr(errcode); |
return(CMD_FAIL); |
} |
} |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/cmd/cls.c |
---|
0,0 → 1,87 |
/* 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. |
*/ |
/* |
* cls |
*/ |
static enum cmd_result cmd_cls(struct cmd_funcparam *p) { |
unsigned char screenw, screenh; |
const char *ansiesc = "\x1B[2J$"; |
if (cmd_ishlp(p)) { |
nls_outputnl(10,0); /* "Clears the screen" */ |
outputnl(""); |
outputnl("CLS"); |
return(CMD_OK); |
} |
screenw = screen_getwidth(); |
screenh = screen_getheight(); |
_asm { |
/* output an ANSI ESC code for "clear screen" in case the console is |
* some kind of terminal */ |
mov ah, 0x09 /* write $-terminated string to stdout */ |
mov dx, ansiesc |
int 0x21 |
/* check what stdout is set to */ |
mov ax, 0x4400 /* IOCTL query device/flags flags */ |
mov bx, 1 /* file handle (1 = stdout) */ |
int 0x21 /* CF set on error, otherwise DX set with flags */ |
jc DONE /* abort on error */ |
/* DX = 10000010 |
| ||| |
| ||+--- indicates standard output |
| |+---- set if NUL device |
| +----- set if CLOCK device |
+--------- set if handle is a device (ie. not a file) |
in other words, DL & 10001110 (8Eh) should result in 10000010 (82h) |
*/ |
and dl, 0x8e |
cmp dl, 0x82 |
jne DONE /* abort on error */ |
/* scroll vram out of screen */ |
mov ax, 0x0600 /* scroll up entire rectangle */ |
mov bh, 0x07 /* fill screen with white-on-black */ |
xor cx, cx /* upper left location in CH,CL (0,0) */ |
/* DX is bottom right location of rectangle (DH=row, DL=column) */ |
mov dh, [screenh] |
dec dh |
mov dl, [screenw] |
dec dl |
int 0x10 |
/* set cursor to top left corner (0,0) of the screen */ |
mov ah, 0x02 /* set cursor position */ |
xor bh, bh /* page number */ |
xor dx, dx /* location in DH,DL */ |
int 0x10 |
DONE: |
} |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/cmd/copy.c |
---|
0,0 → 1,362 |
/* 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. |
*/ |
/* |
* copy |
*/ |
/* /A - Used to copy ASCII files. Applies to the filename preceding it and to |
* all following filenames. Files will be copied until an end-of-file mark is |
* encountered in the file being copied. If an end-of-file mark is encountered |
* in the file, the rest of the file is not copied. DOS will append an EOF |
* mark at the end of the copied file. |
* |
* /B - Used to copy binary files. Applies to the filename preceding it and to |
* all following filenames. Copied files will be read by size (according to |
* the number of bytes indicated in the file`s directory listing). An EOF mark |
* is not placed at the end of the copied file. |
* |
* /V - Checks after the copy to assure that a file was copied correctly. If |
* the copy cannot be verified, the program will display an error message. |
* Using this option will result in a slower copying process. |
* |
* special case: "COPY A+B+C+D" means "append B, C and D files to the A file" |
* if A does not exist, then "append C and D to B", etc. |
*/ |
struct copy_setup { |
const char *src[64]; |
unsigned short src_count; /* how many sources are declared */ |
char cursrc[256]; /* buffer for currently processed src */ |
char dst[256]; |
unsigned short dstlen; |
char src_asciimode[64]; |
char dst_asciimode; |
char last_asciimode; /* /A or /B impacts the file preceding it and becomes the new default for all files that follow */ |
char verifyflag; |
char lastitemwasplus; |
unsigned short databufsz; |
char databuf[1]; |
}; |
/* copies src to dst, overwriting or appending to the destination. |
* - copy is performed in ASCII mode if asciiflag set (stop at first EOF in src |
* and append an EOF in dst). |
* - returns zero on success, DOS error code on error */ |
static unsigned short cmd_copy_internal(const char *dst, char dstascii, const char *src, char srcascii, unsigned char appendflag, void *buff, unsigned short buffsz) { |
unsigned short errcode = 0; |
unsigned short srch = 0xffff, dsth = 0xffff; |
_asm { |
/* open src */ |
OPENSRC: |
mov ax, 0x3d00 /* DOS 2+ -- open an existing file, read access mode */ |
mov dx, src /* ASCIIZ fname */ |
int 0x21 /* CF clear on success, handle in AX */ |
jc FAIL |
mov [srch], ax /* store src handle in memory */ |
/* check appendflag so I know if I have to try opening dst for append */ |
xor al, al |
or al, [appendflag] |
jz CREATEDST |
/* try opening dst first if appendflag set */ |
mov ax, 0x3d01 /* DOS 2+ -- open an existing file, write access mode */ |
mov dx, dst /* ASCIIZ fname */ |
int 0x21 /* CF clear on success, handle in AX */ |
jc CREATEDST /* failed to open file (file does not exist) */ |
mov [dsth], ax /* store dst handle in memory */ |
/* got file open, LSEEK to end of it now so future data is appended */ |
mov bx, ax /* file handle in BX (was still in AX) */ |
mov ax, 0x4202 /* DOS 2+ -- set file pointer to end of file + CX:DX */ |
xor cx, cx /* offset zero */ |
xor dx, dx /* offset zero */ |
int 0x21 /* CF set on error */ |
jc FAIL |
jmp COPY |
/* create dst */ |
CREATEDST: |
mov ah, 0x3c /* DOS 2+ -- create a file */ |
mov dx, dst |
xor cx, cx /* zero out attributes */ |
int 0x21 /* handle in AX on success, CF set on error */ |
jc FAIL |
mov [dsth], ax /* store dst handle in memory */ |
/* perform actual copy */ |
COPY: |
/* read a block from src */ |
mov ah, 0x3f /* DOS 2+ -- read from file */ |
mov bx, [srch] |
mov cx, [buffsz] |
mov dx, [buff] /* DX points to buffer */ |
int 0x21 /* CF set on error, bytes read in AX (0=EOF) */ |
jc FAIL /* abort on error */ |
/* EOF? (ax == 0) */ |
test ax, ax |
jz ENDOFFILE |
/* write block of AX bytes to dst */ |
mov cx, ax /* block length */ |
mov ah, 0x40 /* DOS 2+ -- write to file (CX bytes from DS:DX) */ |
mov bx, [dsth] /* file handle */ |
/* mov dx, [buff] */ /* DX points to buffer already */ |
int 0x21 /* CF clear and AX=CX on success */ |
jc FAIL |
cmp ax, cx /* sould be equal, otherwise failed */ |
mov ax, 0x08 /* preset to DOS error "Insufficient memory" */ |
jne FAIL |
jmp COPY |
ENDOFFILE: |
/* if dst ascii mode -> add an EOF (ASCII mode not supported for the time being) */ |
jmp CLOSESRC |
FAIL: |
mov [errcode], ax |
CLOSESRC: |
/* close src and dst */ |
mov bx, [srch] |
cmp bx, 0xffff |
je CLOSEDST |
mov ah, 0x3e /* DOS 2+ -- close a file handle */ |
int 0x21 |
CLOSEDST: |
mov bx, [dsth] |
cmp bx, 0xffff |
je DONE |
mov ah, 0x3e /* DOS 2+ -- close a file handle */ |
int 0x21 |
DONE: |
} |
return(errcode); |
} |
static enum cmd_result cmd_copy(struct cmd_funcparam *p) { |
struct copy_setup *setup = (void *)(p->BUFFER); |
unsigned short i; |
unsigned short copiedcount_in = 0, copiedcount_out = 0; /* number of input/output copied files */ |
struct DTA *dta = (void *)0x80; /* use DTA at default location in PSP */ |
if (cmd_ishlp(p)) { |
nls_outputnl(38,0); /* "Copies one or more files to another location." */ |
outputnl(""); |
nls_outputnl(38,1); /* "COPY [/A|/B] source [/A|/B] [+source [/A|/B] [+...]] [destination [/A|/B]] [/V]" */ |
outputnl(""); |
nls_outputnl(38,2); /* "source Specifies the file or files to be copied" */ |
nls_outputnl(38,3); /* "/A Indicates an ASCII text file" */ |
nls_outputnl(38,4); /* "/B Indicates a binary file" */ |
nls_outputnl(38,5); /* "destination Specifies the directory and/or filename for the new file(s)" */ |
nls_outputnl(38,6); /* "/V Verifies that new files are written correctly" */ |
outputnl(""); |
nls_outputnl(38,7); /* "To append files, specify a single file for destination, but multiple (...)" */ |
outputnl(""); |
nls_outputnl(38,8); /* "NOTE: /A and /B are no-ops, provided only for compatibility reasons" */ |
return(CMD_OK); |
} |
/* parse cmdline and fill the setup struct accordingly */ |
memset(setup, 0, sizeof(*setup)); |
setup->databufsz = p->BUFFERSZ - sizeof(*setup); |
for (i = 0; i < p->argc; i++) { |
/* switch? */ |
if (p->argv[i][0] == '/') { |
if ((imatch(p->argv[i], "/a")) || (imatch(p->argv[i], "/b"))) { |
setup->last_asciimode = 'b'; |
if (imatch(p->argv[i], "/a")) setup->last_asciimode = 'a'; |
/* */ |
if (setup->dst[0] != 0) { |
setup->dst_asciimode = setup->last_asciimode; |
} else if (setup->src_count != 0) { |
setup->src_asciimode[setup->src_count - 1] = setup->last_asciimode; |
} |
} else if (imatch(p->argv[i], "/v")) { |
setup->verifyflag = 1; |
} else { |
nls_outputnl(0,2); /* "Invalid switch" */ |
return(CMD_FAIL); |
} |
continue; |
} |
/* not a switch - must be either a source, a destination or a + */ |
if (p->argv[i][0] == '+') { |
/* a plus cannot appear after destination or before first source */ |
if ((setup->dst[0] != 0) || (setup->src_count == 0)) { |
nls_outputnl(0,1); /* "Invalid syntax" */ |
return(CMD_FAIL); |
} |
setup->lastitemwasplus = 1; |
/* a plus may be immediately followed by a filename - if so, emulate |
* a new argument */ |
if (p->argv[i][1] != 0) { |
p->argv[i] += 1; |
i--; |
} |
continue; |
} |
/* src? (first non-switch or something that follows a +) */ |
if ((setup->lastitemwasplus) || (setup->src_count == 0)) { |
setup->src[setup->src_count] = p->argv[i]; |
setup->src_asciimode[setup->src_count] = setup->last_asciimode; |
setup->src_count++; |
setup->lastitemwasplus = 0; |
continue; |
} |
/* must be a dst then */ |
if (setup->dst[0] != 0) { |
nls_outputnl(0,1); /* "Invalid syntax" */ |
return(CMD_FAIL); |
} |
if (file_truename(p->argv[i], setup->dst) != 0) { |
nls_outputnl(0,8); /* "Invalid destination" */ |
return(CMD_FAIL); |
} |
setup->dst_asciimode = setup->last_asciimode; |
/* if dst is a directory then append a backslash */ |
setup->dstlen = path_appendbkslash_if_dir(setup->dst); |
} |
/* DEBUG: output setup content ("if 1" to enable) */ |
#if 0 |
printf("src: "); |
for (i = 0; i < setup->src_count; i++) { |
if (i != 0) printf(", "); |
printf("%s [%c]", setup->src[i], setup->src_asciimode[i]); |
} |
printf("\r\n"); |
printf("dst: %s [%c]\r\n", setup->dst, setup->dst_asciimode); |
printf("verify: %s\r\n", (setup->verifyflag)?"ON":"OFF"); |
#endif |
/* must have at least one source */ |
if (setup->src_count == 0) { |
nls_outputnl(0,7); /* "Required parameter missing" */ |
return(CMD_FAIL); |
} |
/* perform the operation based on setup directives: |
* iterate over every source and copy it to dest */ |
for (i = 0; i < setup->src_count; i++) { |
unsigned short t; |
unsigned short cursrclen; |
unsigned short pathendoffset; |
/* resolve truename of src and write it to buffer */ |
t = file_truename(setup->src[i], setup->cursrc); |
if (t != 0) { |
output(setup->src[i]); |
output(" - "); |
nls_outputnl_doserr(t); |
continue; |
} |
cursrclen = strlen(setup->cursrc); /* remember cursrc length */ |
/* if length zero, skip (not sure why this would be possible, though) */ |
if (cursrclen == 0) continue; |
/* if src does not end with a backslash AND it is a directory then append a backslash */ |
cursrclen = path_appendbkslash_if_dir(setup->cursrc); |
/* if src ends with a '\' then append *.* */ |
if (setup->cursrc[cursrclen - 1] == '\\') { |
strcat(setup->cursrc, "*.*"); |
} |
/* remember where the path in cursrc ends */ |
for (t = 0; setup->cursrc[t] != 0; t++) { |
if (setup->cursrc[t] == '\\') pathendoffset = t + 1; |
} |
/* */ |
if (findfirst(dta, setup->cursrc, 0) != 0) { |
continue; |
} |
do { |
char appendflag; |
if (dta->attr & DOS_ATTR_DIR) continue; /* skip directories */ |
/* compute full path/name of the file */ |
strcpy(setup->cursrc + pathendoffset, dta->fname); |
/* if there was no destination, then YOU are the destination now! |
* this handles situations like COPY a.txt+b.txt+c.txt */ |
if (setup->dst[0] == NULL) { |
strcpy(setup->dst, setup->cursrc); |
setup->dstlen = strlen(setup->dst); |
copiedcount_in++; |
copiedcount_out++; |
continue; |
} |
/* is dst ending with a backslash? then append fname to it */ |
if (setup->dst[setup->dstlen - 1] == '\\') strcpy(setup->dst + setup->dstlen, dta->fname); |
/* now cursrc contains the full source and dst contains the full dest... COPY TIME! */ |
/* if dst file exists already -> overwrite it or append? |
- if dst is a dir (dstlen-1 points at a \\) -> overwrite |
- otherwise: if copiedcount_in==0 overwrite, else append */ |
output(setup->cursrc); |
if ((setup->dst[setup->dstlen - 1] == '\\') || (copiedcount_in == 0)) { |
appendflag = 0; |
output(" > "); |
copiedcount_out++; |
} else { |
appendflag = 1; |
output(" >> "); |
} |
outputnl(setup->dst); |
t = cmd_copy_internal(setup->dst, 0, setup->cursrc, 0, appendflag, setup->databuf, setup->databufsz); |
if (t != 0) { |
nls_outputnl_doserr(t); |
return(CMD_FAIL); |
} |
copiedcount_in++; |
} while (findnext(dta) == 0); |
} |
sprintf(setup->databuf, svarlang_str(38,9)/*"%u file(s) copied"*/, copiedcount_out); |
outputnl(setup->databuf); |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/cmd/date.c |
---|
0,0 → 1,225 |
/* 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. |
*/ |
/* |
* date [date] |
*/ |
/* parse a NULL-terminated string int hour, minutes and seconds, returns 0 on success |
* valid inputs: 0, 7, 5:5, 23:23, 17:54:45, 9p, 9:05, ... |
*/ |
static int cmd_date_parse(const char *s, unsigned short *year, unsigned char *mo, unsigned char *dy, struct nls_patterns *nls) { |
unsigned short i; |
const char *ptrs[2] = {NULL, NULL}; |
*year = 0; |
*mo = 0; |
*dy = 0; |
/* validate input - must contain only chars 0-9 and time separator */ |
for (i = 0; s[i] != 0; i++) { |
switch (s[i]) { |
case '0': |
case '1': |
case '2': |
case '3': |
case '4': |
case '5': |
case '6': |
case '7': |
case '8': |
case '9': |
break; |
default: |
if ((s[i] != nls->datesep[0]) || (i == 0)) return(-1); |
if (ptrs[0] == NULL) { |
ptrs[0] = s + i + 1; |
} else if (ptrs[1] == NULL) { |
ptrs[1] = s + i + 1; |
} else { /* too many separators */ |
return(-1); |
} |
break; |
} |
} |
/* did I get all separators? */ |
if ((ptrs[0] == NULL) || (ptrs[1] == NULL)) goto FAIL; |
/* d/m/y order depends on NLS settings */ |
switch (nls->dateformat) { |
case 0: /* m/d/y */ |
atous(&i, s); |
*mo = i; |
atous(&i, ptrs[0]); |
*dy = i; |
atous(year, ptrs[1]); |
break; |
case 1: /* d/m/y */ |
atous(&i, s); |
*dy = i; |
atous(&i, ptrs[0]); |
*mo = i; |
atous(year, ptrs[1]); |
break; |
default: /* y/m/d */ |
atous(year, s); |
atous(&i, ptrs[0]); |
*mo = i; |
atous(&i, ptrs[1]); |
*dy = i; |
break; |
} |
return(0); |
FAIL: |
*year = 0; |
return(-1); |
} |
/* set system date, return 0 on success */ |
static int cmd_date_set(unsigned short year, unsigned char mo, unsigned char dy) { |
_asm { |
push ax |
push bx |
push cx |
push dx |
mov ax, 0x2b00 /* DOS 1+ -- Set DOS Date */ |
mov cx, [year] /* year (1980-2099) */ |
mov dh, [mo] /* month (1-12) */ |
mov dl, [dy] /* day (1-31) */ |
int 0x21 /* AL = 0 on success */ |
cmp al, 0 |
je DONE |
mov [year], 0 |
DONE: |
pop dx |
pop cx |
pop bx |
pop ax |
} |
if (year == 0) return(-1); |
return(0); |
} |
static enum cmd_result cmd_date(struct cmd_funcparam *p) { |
struct nls_patterns *nls = (void *)(p->BUFFER); |
char *buff = p->BUFFER + sizeof(*nls); |
unsigned short i; |
unsigned short year = 0; |
unsigned char mo, dy; |
if (cmd_ishlp(p)) { |
nls_outputnl(32,0); /* "Displays or sets the system date."); */ |
outputnl(""); |
nls_outputnl(32,1); /* "DATE [date]" */ |
outputnl(""); |
nls_outputnl(32,2); /* "Type DATE with no parameters to display the (...)" */ |
return(CMD_OK); |
} |
i = nls_getpatterns(nls); |
if (i != 0) { |
nls_outputnl_doserr(i); |
return(CMD_FAIL); |
} |
/* display current date if no args */ |
if (p->argc == 0) { |
/* get cur date */ |
_asm { |
push ax |
push cx |
push dx |
mov ah, 0x2a /* DOS 1+ -- Query DOS Date */ |
int 0x21 /* CX=year DH=month DL=day */ |
mov [year], cx |
mov [mo], dh |
mov [dy], dl |
pop dx |
pop cx |
pop ax |
} |
buff[0] = ' '; |
nls_format_date(buff + 1, year, mo, dy, nls); |
nls_output(32,4); /* "Current date is" */ |
outputnl(buff); |
year = 0; |
} else { /* parse date if provided */ |
if ((cmd_date_parse(p->argv[0], &year, &mo, &dy, nls) != 0) || (cmd_date_set(year, mo, dy) != 0)) { |
nls_outputnl(32,3); /* "Invalid date" */ |
year = 0; |
} |
} |
/* ask for date if not provided or if input was malformed */ |
while (year == 0) { |
nls_output(32,5); /* "Enter new date:" */ |
output(" "); |
/* collect user input into buff */ |
_asm { |
push ax |
push bx |
push dx |
mov ah, 0x0a /* DOS 1+ -- Buffered String Input */ |
mov bx, buff |
mov dx, bx |
mov al, 16 |
mov [bx], al /* max input length */ |
mov al, 1 |
mov [bx+1], al /* zero out the "previous entry" length */ |
int 0x21 |
/* terminate the string with a NULL terminator */ |
xor ax, ax |
inc bx |
mov al, [bx] /* read length of input string */ |
mov bx, ax |
add bx, dx |
mov [bx+2], ah |
/* output a \n */ |
mov ah, 2 |
mov dl, 0x0A |
int 0x21 |
pop dx |
pop bx |
pop ax |
} |
if (buff[1] == 0) break; /* empty string = no date change */ |
if ((cmd_date_parse(buff + 2, &year, &mo, &dy, nls) == 0) && (cmd_date_set(year, mo, dy) == 0)) break; |
nls_outputnl(32,3); /* "Invalid date" */ |
} |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/cmd/del.c |
---|
0,0 → 1,143 |
/* 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. |
*/ |
/* |
* del/erase |
*/ |
static enum cmd_result 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)) { |
nls_outputnl(36,0); /* "Deletes one or more files." */ |
outputnl(""); |
nls_outputnl(36,1); /* "DEL [drive:][path]filename [/P]" */ |
nls_outputnl(36,2); /* "ERASE [drive:][path]filename [/P]" */ |
outputnl(""); |
nls_outputnl(36,3); /* "[drive:][path]filename Specifies the file(s) to delete." */ |
nls_outputnl(36,4); /* "/P Prompts for confirmation before deleting each file." */ |
return(CMD_OK); |
} |
if (p->argc == 0) { |
nls_outputnl(0,7); /* "Required parameter missing" */ |
return(CMD_FAIL); |
} |
/* 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 { |
nls_output(0,2); /* "Invalid switch" */ |
output(": "); |
outputnl(p->argv[i]); |
return(CMD_FAIL); |
} |
} else if (delspec != NULL) { /* otherwise its a delspec */ |
nls_outputnl(0,4); /* "Too many parameters" */ |
return(CMD_FAIL); |
} else { |
delspec = p->argv[i]; |
} |
} |
/* convert path to canonical form */ |
file_truename(delspec, buff); |
/* is delspec pointing at a directory? if so, add a \*.* */ |
i = path_appendbkslash_if_dir(buff); |
if (buff[i - 1] == '\\') 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, "????????.???"))) { |
nls_outputnl(36,5); /* "All files in directory will be deleted!" */ |
if (askchoice(svarlang_str(36,6)/*"Are you sure (Y/N)?"*/, svarlang_str(0,10)/*"YN"*/) != 0) return(CMD_FAIL); |
} |
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); |
if (err != 0) { /* report the error only if query had no wildcards */ |
for (i = 0; buff[i] != 0; i++) if (buff[i] == '?') break; |
if (buff[i] == 0) nls_outputnl_doserr(err); |
break; |
} |
} else { |
if (findnext(dta) != 0) break; /* do not report errors on findnext() */ |
} |
/* prep the full path/name of the file in buff */ |
/* NOTE: buff contained the search pattern but it is no longer needed so I |
* can reuse it now */ |
strcpy(buff + pathlimit, fname); |
/* ask if confirmation required: PLIK.TXT Delete (Y/N)? */ |
if (confirmflag) { |
output(buff); |
output(" \t"); |
if (askchoice(svarlang_str(36,7)/*"Delete (Y/N)?"*/, svarlang_str(0,10)) != 0) continue; |
} |
/* del found file */ |
_asm { |
push ax |
push dx |
mov ah, 0x41 /* delete a file, DS:DX points to an ASCIIZ filespec (no wildcards allowed) */ |
mov dx, buff |
int 0x21 |
jnc DONE |
mov [err], ax |
DONE: |
pop dx |
pop ax |
} |
if (err != 0) { |
output(fname); |
output(": "); |
nls_outputnl_doserr(err); |
break; |
} |
} |
if (err == 0) return(CMD_OK); |
return(CMD_FAIL); |
} |
/svarcom/tags/svarcom-2022.1/cmd/dir.c |
---|
0,0 → 1,444 |
/* 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. |
*/ |
/* |
* 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. |
*/ |
#define WCOLWIDTH 15 /* width of a column in wide mode output */ |
/* fills freebytes with free bytes for drv (A=0, B=1, etc) |
* returns DOS ERR code on failure */ |
static unsigned short cmd_dir_df(unsigned long *freebytes, unsigned char drv) { |
unsigned short res = 0; |
unsigned short sects_per_clust = 0, avail_clusts = 0, bytes_per_sect = 0; |
_asm { |
push ax |
push bx |
push cx |
push dx |
mov ah, 0x36 /* DOS 2+ -- Get Disk Free Space */ |
mov dl, [drv] /* A=1, B=2, etc (0 = DEFAULT DRIVE) */ |
inc dl |
int 0x21 /* AX=sects_per_clust, BX=avail_clusts, CX=bytes_per_sect, DX=tot_clusters */ |
cmp ax, 0xffff /* AX=0xffff on error (invalid drive) */ |
jne COMPUTEDF |
mov [res], 0x0f /* fill res with DOS error code 15 ("invalid drive") */ |
jmp DONE |
COMPUTEDF: |
/* freebytes = AX * BX * CX */ |
mov [sects_per_clust], ax |
mov [avail_clusts], bx |
mov [bytes_per_sect], cx |
DONE: |
pop dx |
pop cx |
pop bx |
pop ax |
} |
/* multiple steps to avoid uint16 overflow */ |
*freebytes = sects_per_clust; |
*freebytes *= avail_clusts; |
*freebytes *= bytes_per_sect; |
return(res); |
} |
static void dir_pagination(unsigned short *availrows) { |
*availrows -= 1; |
if (*availrows == 0) { |
press_any_key(); |
*availrows = screen_getheight() - 1; |
} |
} |
/* parse an attr list like "Ar-hS" and fill bitfield into attrfilter_may and attrfilter_must. |
* /AHS -> adds S and H to mandatory attribs ("must") |
* /A-S -> removes S from allowed attribs ("may") |
* returns non-zero on error. */ |
static int dir_parse_attr_list(const char *arg, unsigned char *attrfilter_may, unsigned char *attrfilter_must) { |
for (; *arg != 0; arg++) { |
unsigned char curattr; |
char not; |
if (*arg == '-') { |
not = 1; |
arg++; |
} else { |
not = 0; |
} |
switch (*arg) { |
case 'd': |
case 'D': |
curattr = DOS_ATTR_DIR; |
break; |
case 'r': |
case 'R': |
curattr = DOS_ATTR_RO; |
break; |
case 'a': |
case 'A': |
curattr = DOS_ATTR_ARC; |
break; |
case 'h': |
case 'H': |
curattr = DOS_ATTR_HID; |
break; |
case 's': |
case 'S': |
curattr = DOS_ATTR_SYS; |
break; |
default: |
return(-1); |
} |
/* update res bitfield */ |
if (not) { |
*attrfilter_may &= ~curattr; |
} else { |
*attrfilter_must |= curattr; |
} |
} |
return(0); |
} |
#define DIR_ATTR_DEFAULT (DOS_ATTR_RO | DOS_ATTR_DIR | DOS_ATTR_ARC) |
static enum cmd_result 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 */ |
unsigned short i; |
unsigned short availrows; /* counter of available rows on display (used for /P) */ |
unsigned short wcols = screen_getwidth() / WCOLWIDTH; /* number of columns in wide mode */ |
unsigned char wcolcount; |
struct nls_patterns *nls = (void *)(p->BUFFER + (p->BUFFERSZ / 2)); |
char *buff2 = p->BUFFER + (p->BUFFERSZ / 2) + sizeof(*nls); |
unsigned long summary_fcount = 0; |
unsigned long summary_totsz = 0; |
unsigned char drv = 0; |
unsigned char attrfilter_may = DIR_ATTR_DEFAULT; |
unsigned char attrfilter_must = 0; |
#define DIR_FLAG_PAUSE 1 |
#define DIR_FLAG_RECUR 4 |
#define DIR_FLAG_LCASE 8 |
unsigned char flags = 0; |
#define DIR_OUTPUT_NORM 1 |
#define DIR_OUTPUT_WIDE 2 |
#define DIR_OUTPUT_BARE 3 |
unsigned char format = DIR_OUTPUT_NORM; |
if (cmd_ishlp(p)) { |
nls_outputnl(37,0); /* "Displays a list of files and subdirectories in a directory" */ |
outputnl(""); |
nls_outputnl(37,1); /* "DIR [drive:][path][filename] [/P] [/W] [/A[:]attributes] [/O[[:]sortorder]] [/S] [/B] [/L]" */ |
outputnl(""); |
nls_outputnl(37,2); /* "/P Pauses after each screenful of information" */ |
nls_outputnl(37,3); /* "/W Uses wide list format" */ |
outputnl(""); |
nls_outputnl(37,4); /* "/A Displays files with specified attributes:" */ |
nls_outputnl(37,5); /* " D Directories R Read-only files H Hidden files" */ |
nls_outputnl(37,6); /* " A Ready for archiving S System files - prefix meaning "not"" */ |
outputnl(""); |
nls_outputnl(37,7); /* "/O List files in sorted order:" */ |
nls_outputnl(37,8); /* " N by name S by size E by extension" */ |
nls_outputnl(37,9); /* " D by date G group dirs first - prefix to reverse order" */ |
outputnl(""); |
nls_outputnl(37,10); /* "/S Displays files in specified directory and all subdirectories" */ |
nls_outputnl(37,11); /* "/B Uses bare format (no heading information or summary)" */ |
nls_outputnl(37,12); /* "/L Uses lowercases" */ |
return(CMD_OK); |
} |
i = nls_getpatterns(nls); |
if (i != 0) nls_outputnl_doserr(i); |
/* parse command line */ |
for (i = 0; i < p->argc; i++) { |
if (p->argv[i][0] == '/') { |
const char *arg = p->argv[i] + 1; |
char neg = 0; |
/* detect negations and get actual argument */ |
if (*arg == '-') { |
neg = 1; |
arg++; |
} |
/* */ |
switch (*arg) { |
case 'a': |
case 'A': |
arg++; |
/* preset defaults */ |
attrfilter_may = DIR_ATTR_DEFAULT; |
attrfilter_must = 0; |
/* /-A only allowed without further parameters (used to cancel possible previous /Asmth) */ |
if (neg) { |
if (*arg != 0) { |
nls_outputnl_err(0, 2); /* invalid switch */ |
return(CMD_FAIL); |
} |
} else { |
/* start with "allow everything" */ |
attrfilter_may = (DOS_ATTR_ARC | DOS_ATTR_DIR | DOS_ATTR_HID | DOS_ATTR_SYS | DOS_ATTR_RO); |
if (dir_parse_attr_list(arg, &attrfilter_may, &attrfilter_must) != 0) { |
nls_outputnl_err(0, 3); /* invalid parameter format */ |
return(CMD_FAIL); |
} |
} |
break; |
case 'b': |
case 'B': |
format = DIR_OUTPUT_BARE; |
break; |
case 'l': |
case 'L': |
flags |= DIR_FLAG_LCASE; |
break; |
case 'o': |
case 'O': |
/* TODO */ |
outputnl("/O NOT IMPLEMENTED YET"); |
return(CMD_FAIL); |
break; |
case 'p': |
case 'P': |
flags |= DIR_FLAG_PAUSE; |
if (neg) flags &= (0xff ^ DIR_FLAG_PAUSE); |
break; |
case 's': |
case 'S': |
/* TODO */ |
outputnl("/S NOT IMPLEMENTED YET"); |
return(CMD_FAIL); |
break; |
case 'w': |
case 'W': |
format = DIR_OUTPUT_WIDE; |
break; |
default: |
nls_outputnl_err(0, 2); /* invalid switch */ |
return(CMD_FAIL); |
} |
} else { /* filespec */ |
if (filespecptr != NULL) { |
nls_outputnl_err(0, 4); /* too many parameters */ |
return(CMD_FAIL); |
} |
filespecptr = p->argv[i]; |
} |
} |
if (filespecptr == NULL) filespecptr = "."; |
availrows = screen_getheight() - 2; |
/* special case: "DIR drive:" (truename() fails on "C:" under MS-DOS 6.0) */ |
if ((filespecptr[0] != 0) && (filespecptr[1] == ':') && (filespecptr[2] == 0)) { |
if ((filespecptr[0] >= 'a') && (filespecptr[0] <= 'z')) { |
p->BUFFER[0] = filespecptr[0] - ('a' - 1); |
} else { |
p->BUFFER[0] = filespecptr[0] - ('A' - 1); |
} |
i = curpathfordrv(p->BUFFER, p->BUFFER[0]); |
} else { |
i = file_truename(filespecptr, p->BUFFER); |
} |
if (i != 0) { |
nls_outputnl_doserr(i); |
return(CMD_FAIL); |
} |
if (format != DIR_OUTPUT_BARE) { |
drv = p->BUFFER[0]; |
if (drv >= 'a') { |
drv -= 'a'; |
} else { |
drv -= 'A'; |
} |
cmd_vol_internal(drv, buff2); |
sprintf(buff2, svarlang_str(37,20)/*"Directory of %s"*/, p->BUFFER); |
/* trim at first '?', if any */ |
for (i = 0; buff2[i] != 0; i++) if (buff2[i] == '?') buff2[i] = 0; |
outputnl(buff2); |
outputnl(""); |
availrows -= 3; |
} |
/* if dir: append a backslash (also get its len) */ |
i = path_appendbkslash_if_dir(p->BUFFER); |
/* if ends with a \ then append ????????.??? */ |
if (p->BUFFER[i - 1] == '\\') strcat(p->BUFFER, "????????.???"); |
/* ask DOS for list of files, but only with allowed attribs */ |
i = findfirst(dta, p->BUFFER, attrfilter_may); |
if (i != 0) { |
nls_outputnl_doserr(i); |
return(CMD_FAIL); |
} |
wcolcount = 0; /* may be used for columns counting with wide mode */ |
do { |
/* if mandatory attribs are requested, filter them now */ |
if ((attrfilter_must & dta->attr) != attrfilter_must) continue; |
/* if file contains attributes that are not allowed -> skip */ |
if ((~attrfilter_may & dta->attr) != 0) continue; |
/* turn string lcase (/L) */ |
if (flags & DIR_FLAG_LCASE) _strlwr(dta->fname); /* OpenWatcom extension, probably does not care about NLS so results may be odd with non-A-Z characters... */ |
summary_fcount++; |
if ((dta->attr & DOS_ATTR_DIR) == 0) summary_totsz += dta->size; |
switch (format) { |
case DIR_OUTPUT_NORM: |
/* print fname-space-extension (unless it's "." or "..", then print as-is) */ |
if (dta->fname[0] == '.') { |
output(dta->fname); |
i = strlen(dta->fname); |
while (i++ < 12) output(" "); |
} else { |
file_fname2fcb(buff2, dta->fname); |
memmove(buff2 + 9, buff2 + 8, 4); |
buff2[8] = ' '; |
output(buff2); |
} |
output(" "); |
/* either <DIR> or right aligned 10-chars byte size */ |
memset(buff2, ' ', 10); |
if (dta->attr & DOS_ATTR_DIR) { |
strcpy(buff2 + 10, svarlang_str(37,21)); |
} else { |
_ultoa(dta->size, buff2 + 10, 10); /* OpenWatcom extension */ |
} |
output(buff2 + strlen(buff2) - 10); |
/* two spaces and NLS DATE */ |
buff2[0] = ' '; |
buff2[1] = ' '; |
nls_format_date(buff2 + 2, dta->date_yr + 1980, dta->date_mo, dta->date_dy, nls); |
output(buff2); |
/* one space and NLS TIME */ |
nls_format_time(buff2 + 1, dta->time_hour, dta->time_min, 0xff, nls); |
outputnl(buff2); |
break; |
case DIR_OUTPUT_WIDE: /* display in columns of 12 chars per item */ |
i = strlen(dta->fname); |
if (dta->attr & DOS_ATTR_DIR) { |
i += 2; |
output("["); |
output(dta->fname); |
output("]"); |
} else { |
output(dta->fname); |
} |
while (i++ < WCOLWIDTH) output(" "); |
if (++wcolcount == wcols) { |
wcolcount = 0; |
outputnl(""); |
} else { |
availrows++; /* wide mode is the only one that does not write one line per file */ |
} |
break; |
case DIR_OUTPUT_BARE: |
outputnl(dta->fname); |
break; |
} |
if (flags & DIR_FLAG_PAUSE) dir_pagination(&availrows); |
} while (findnext(dta) == 0); |
if (wcolcount != 0) { |
outputnl(""); /* in wide mode make sure to end on a clear row */ |
if (flags & DIR_FLAG_PAUSE) dir_pagination(&availrows); |
} |
/* print out summary (unless bare output mode) */ |
if (format != DIR_OUTPUT_BARE) { |
unsigned short alignpos; |
/* x file(s) */ |
memset(buff2, ' ', 13); /* 13 is the max len of a 32 bit number with thousand separators (4'000'000'000) */ |
i = nls_format_number(buff2 + 13, summary_fcount, nls); |
alignpos = sprintf(buff2 + 13 + i, " %s ", svarlang_str(37,22)/*"file(s)"*/); |
output(buff2 + i); |
/* xxxx bytes */ |
i = nls_format_number(buff2 + 13, summary_totsz, nls); |
output(buff2 + i); |
output(" "); |
nls_outputnl(37,23); /* "bytes" */ |
if (flags & DIR_FLAG_PAUSE) dir_pagination(&availrows); |
/* xxxx bytes free */ |
i = cmd_dir_df(&summary_totsz, drv); |
if (i != 0) nls_outputnl_doserr(i); |
alignpos += 13 + 13; |
memset(buff2, ' ', alignpos); /* align the freebytes value to same column as totbytes */ |
i = nls_format_number(buff2 + alignpos, summary_totsz, nls); |
output(buff2 + i); |
output(" "); |
nls_outputnl(37,24); /* "bytes free" */ |
if (flags & DIR_FLAG_PAUSE) dir_pagination(&availrows); |
} |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/cmd/echo.c |
---|
0,0 → 1,95 |
/* 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. |
*/ |
/* |
* echo |
*/ |
static enum cmd_result cmd_echo(struct cmd_funcparam *p) { |
const char *arg = p->cmdline + 5; |
/* display help only if /? is the only argument */ |
if ((p->argc == 1) && (imatch(p->argv[0], "/?"))) { |
nls_outputnl(31,0); /* "Displays messages, or turns command-echoing on or off" */ |
outputnl(""); |
outputnl("ECHO [ON | OFF]"); |
nls_outputnl(31,1); /* "ECHO [message]" */ |
outputnl(""); |
nls_outputnl(31,2); /* "Type ECHO without parameters to display the current setting." */ |
return(CMD_OK); |
} |
/* ECHO without any parameter: display current state */ |
if (p->argc == 0) { |
if (p->rmod->flags & FLAG_ECHOFLAG) { |
nls_outputnl(31,3); /* "ECHO is on" */ |
} else { |
nls_outputnl(31,4); /* "ECHO is off" */ |
} |
return(CMD_OK); |
} |
/* ECHO ON */ |
if ((p->argc == 1) && (imatch(p->argv[0], "on"))) { |
p->rmod->flags |= FLAG_ECHOFLAG; |
return(CMD_OK); |
} |
/* ECHO OFF */ |
if ((p->argc == 1) && (imatch(p->argv[0], "off"))) { |
p->rmod->flags &= ~FLAG_ECHOFLAG; |
return(CMD_OK); |
} |
/* ECHO MSG (start at cmdline+5 since first 5 are "ECHO" + separator) */ |
_asm { |
push ax |
push dx |
push si |
mov si, [arg] |
cld /* clear direction flag (DF) so lodsb increments SI */ |
mov ah, 0x02 /* display char from DL */ |
NEXTYBTE: |
lodsb /* load byte at DS:[SI] into AL and inc SI (if DF clear) */ |
or al, al /* is AL == 0? then end of string reached */ |
jz DONE |
mov dl, al |
int 0x21 |
jmp NEXTYBTE |
/* output a final CR/LF */ |
DONE: |
mov dl, 0x0D |
int 0x21 |
mov dl, 0x0A |
int 0x21 |
pop si |
pop dx |
pop ax |
} |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/cmd/exit.c |
---|
0,0 → 1,40 |
/* 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. |
*/ |
/* |
* exit |
* |
* Quits the COMMAND.COM program (command interpreter) |
* |
*/ |
static enum cmd_result cmd_exit(struct cmd_funcparam *p) { |
if (cmd_ishlp(p)) { |
outputnl("EXIT\r\n"); |
nls_outputnl(30,0); /* "Quits the COMMAND.COM program (command interpreter)" */ |
} else { |
sayonara(p->rmod); |
} |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/cmd/for.c |
---|
0,0 → 1,78 |
/* 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. |
*/ |
/* |
* FOR %variable IN (set) DO command [command-parameters] |
* |
* %variable a replaceable parameter name |
* (set) a set of one of more files. Wildcards allowed. |
* command the command to carry out for each matched file |
* command-parameters parameters or switches for the specified command |
* |
* To use FOR in a batch program, use %%variable instead of %variable |
* |
* the set of files must be surrounded by parenthesis, and may contain one |
* or more space-delimited wildcards. Examples: |
* (file.txt other.txt) |
* (*.exe *.com *.bat) |
* (jan*.txt 199201??.txt) |
*/ |
/* Implementation notes: |
* |
* For cannot be nested (no "FOR ... do FOR ..." allowed) |
* |
* When executed, FOR allocates a "FOR context" to RMOD's memory, this context |
* holds the memory state of a FindNext iteration, as well as the command |
* to run on each matched file. |
* |
* This FOR context is looked at by command.c and used to provide a command |
* instead of getting the command from interactive cli or BAT file. Repeats |
* until the FindNext buffer stops matching files. |
* |
* This file only provides the help screen of FOR, as well as the FOR-context |
* initialization. Actual execution happens within command.c. |
*/ |
static enum cmd_result cmd_for(struct cmd_funcparam *p) { |
/* help screen ONLY if /? is the only argument */ |
if ((p->argc == 1) && (imatch(p->argv[0], "/?"))) { |
nls_outputnl(18,0); /* "Runs a specified command for each file in a set of files" */ |
outputnl(""); |
nls_outputnl(18,1); /* "FOR %variable IN (set) DO command [parameters]" */ |
outputnl(""); |
nls_outputnl(18,2); /* "%variable a replaceable parameter name" */ |
nls_outputnl(18,3); /* "(set) a set of one of more files. Wildcards allowed." */ |
nls_outputnl(18,4); /* "command the command to carry out for each matched file" */ |
nls_outputnl(18,5); /* "parameters parameters or switches for the specified command" */ |
outputnl(""); |
nls_outputnl(18,6); /* "To use FOR in a batch program, use %%variable instead of %variable" */ |
return(CMD_OK); |
} |
outputnl("FOR IS NOT IMPLEMENTED YET"); |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/cmd/goto.c |
---|
0,0 → 1,261 |
/* 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. |
*/ |
/* |
* goto label |
* |
* if label does not exist in the currently processed batch file, then a error |
* "Label not found" is displayed and the batch file is aborted. Any parent |
* batches are ALSO aborted. Same behavior if called without any parameter. |
* |
* if called outside of a batch file, this command has no effect (and does not |
* display any error, even when called without any argument). |
* |
* it reacts to /? by outputing its help screen |
* |
* only 1st argument is processed, any extra arguments are ignored (even /?). |
* |
* Labels can be written as: |
* :LABEL |
* :LABEL |
* : LABEL |
* |
* A label can also be followed by one or more space or tabs, followed by |
* anything. The label is parsed only to the first space, tab, end of line or |
* end of file. Hence this would be perfectly ok: |
* |
* :LABEL this is a comment |
* |
* Labels are searched in the batch file from top to bottom and first match |
* is jumped to. Matching labels is case-insensitive (ie. LABEL == LaBeL) |
*/ |
static void goto_close_dos_handle(unsigned short fhandle) { |
_asm { |
push bx |
mov ah, 0x3e |
mov bx, fhandle |
int 0x21 |
pop bx |
} |
} |
static enum cmd_result cmd_goto(struct cmd_funcparam *p) { |
char *buff = NULL; |
const char *label; |
unsigned short bufflen = 0; |
unsigned short fhandle = 0; |
unsigned short doserr = 0; |
unsigned short batname_seg; |
unsigned short batname_off; |
unsigned char eof_reached = 0; |
unsigned short i; |
/* help? reacts only to /? being passed as FIRST argument */ |
if ((p->argc > 0) && imatch(p->argv[0], "/?")) { |
nls_outputnl(17,0); /* "Directs batch processing to a labelled line in the batch program." */ |
outputnl(""); |
nls_outputnl(17,1); /* "GOTO LABEL" */ |
outputnl(""); |
nls_outputnl(17,2); /* "LABEL specifies a text string used in the batch program as a label." */ |
outputnl(""); |
nls_outputnl(17,3); /* "A label is on a line by itself and must be preceded by a colon." */ |
return(CMD_OK); |
} |
/* not inside a batch file? not given any argument? then do nothing */ |
if ((p->rmod->bat == NULL) || (p->argc == 0)) return(CMD_OK); |
/* label is in first arg */ |
label = p->argv[0]; |
/* open batch file (read-only) */ |
batname_seg = FP_SEG(p->rmod->bat->fname); |
batname_off = FP_OFF(p->rmod->bat->fname); |
_asm { |
push bx |
push dx |
mov ax, batname_seg |
push ds /* save ds */ |
mov ds, ax |
mov dx, batname_off |
mov ax, 0x3d00 |
int 0x21 /* handle in ax on success */ |
pop ds |
jnc OPEN_SUCCESS |
mov doserr, ax |
OPEN_SUCCESS: |
mov fhandle, ax /* save file handle */ |
pop dx |
pop bx |
} |
/* file open failed? */ |
if (doserr != 0) { |
nls_outputnl_doserr(doserr); |
return(CMD_FAIL); |
} |
/* reset the rmod bat counter since I will scan all lines from top to bottom */ |
p->rmod->bat->nextline = 0; /* remember this is a byte offset, not a line number */ |
/* read bat file line by line until label is found or EOF */ |
for (;;) { |
/* move any existing data to the start of the buffer */ |
if (bufflen > 0) memmove(p->BUFFER, buff, bufflen); |
buff = p->BUFFER; /* assumption: must be big enough to hold 2 sectors (2 * 512) */ |
/* if buffer has less than 512b then load it with another sector (unless eof) */ |
if ((eof_reached == 0) && (bufflen < 512)) { |
/* load 512b of data into buffer */ |
_asm { |
push ax |
push bx |
push cx |
push dx |
pushf |
mov ah, 0x3f /* read from file handle */ |
mov bx, fhandle /* file handle where to read from */ |
mov cx, 512 /* read 512 bytes (one sector) */ |
mov dx, buff /* target buffer */ |
add dx, bufflen /* data must follow existing pending data */ |
int 0x21 /* CF clear on success and AX=number of bytes read */ |
/* error? */ |
jnc READ_OK |
mov doserr, ax |
READ_OK: |
add bufflen, ax |
/* set eof if amount of bytes read is shorter than cx */ |
cmp ax, cx |
je EOF_NOT_REACHED |
mov eof_reached, byte ptr 1 |
EOF_NOT_REACHED: |
popf |
pop dx |
pop cx |
pop bx |
pop ax |
} |
/* on error close the file and quit */ |
if (doserr != 0) { |
goto_close_dos_handle(fhandle); |
nls_outputnl_doserr(doserr); |
return(CMD_FAIL); |
} |
} |
/* advance buffer to first non-space/non-tab/non-CR/non-LF */ |
while (bufflen > 0) { |
if ((*buff != ' ') && (*buff != '\t') && (*buff != '\r') && (*buff != '\n')) break; |
bufflen--; |
buff++; |
p->rmod->bat->nextline++; |
} |
/* if the line does not start with a colon, then jump to next line */ |
if ((bufflen > 0) && (*buff != ':')) { |
while ((bufflen > 0) && (*buff != '\n')) { |
bufflen--; |
buff++; |
p->rmod->bat->nextline++; |
} |
} |
/* refill buffer if needed */ |
if ((bufflen < 512) && (eof_reached == 0)) continue; |
/* eof? */ |
if (bufflen == 0) break; |
/* skip the colon */ |
if (*buff == ':') { |
bufflen--; |
buff++; |
p->rmod->bat->nextline++; |
} |
/* skip any leading white spaces (space or tab) */ |
while (bufflen > 0) { |
if ((*buff != ' ') && (*buff != '\t')) break; |
bufflen--; |
buff++; |
p->rmod->bat->nextline++; |
} |
/* read the in-file label and compare it with what's in the label buff */ |
for (i = 0;; i++) { |
/* if end of label then check if it is also end of in-file label (ends with space, tab, \r or \n) */ |
if ((i == bufflen) || (buff[i] == ' ') || (buff[i] == '\t') || (buff[i] == '\r') || (buff[i] == '\n')) { |
if (label[i] == 0) { |
/* match found -> close file, skip to end of line and quit */ |
while (bufflen > 0) { |
bufflen--; |
buff++; |
p->rmod->bat->nextline++; |
if (*buff == '\n') break; |
} |
goto_close_dos_handle(fhandle); |
return(CMD_OK); |
} |
break; |
} |
/* end of label = mismatch */ |
if (label[i] == 0) break; |
/* case-insensitive comparison */ |
if ((label[i] & 0xDF) != (buff[i] & 0xDF)) break; |
} |
/* no match, move forward to end of line and repeat */ |
while ((bufflen > 0) && (*buff != '\n')) { |
bufflen--; |
buff++; |
p->rmod->bat->nextline++; |
} |
} |
/* close the batch file handle */ |
goto_close_dos_handle(fhandle); |
/* label not found, display error message and abort all batch scripts */ |
nls_outputnl(17, 10); /* "Label not found" */ |
rmod_free_bat_llist(p->rmod); |
/* restore echo flag as it was before running the (first) bat file */ |
p->rmod->flags &= ~FLAG_ECHOFLAG; |
if (p->rmod->flags & FLAG_ECHO_BEFORE_BAT) p->rmod->flags |= FLAG_ECHOFLAG; |
return(CMD_FAIL); |
} |
/svarcom/tags/svarcom-2022.1/cmd/if.c |
---|
0,0 → 1,138 |
/* 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. |
*/ |
/* |
* if [not] exists |
* if [not] errorlevel 1 |
* if [not] string ==string (string==string and string == string works, too) |
* if [not] errorlevel == 1 <-- I do NOT support this one, even though |
* MSDOS 5 and 6 considers it equivalent to |
* IF ERRORLEVEL 1. This is a misleading and |
* undocumented syntax (does not actually |
* check for equality). |
*/ |
#define JMP_NEXT_ARG(s) while ((*s != ' ') && (*s != 0)) s++; while (*s == ' ') s++; |
static enum cmd_result cmd_if(struct cmd_funcparam *p) { |
unsigned char negflag = 0; |
unsigned short i; |
const char *s = p->cmdline + p->argoffset; |
/* help screen ONLY if /? is the only argument - I do not want to output |
* help for ex. for "if %1 == /? echo ..." */ |
if ((p->argc == 1) && (imatch(p->argv[0], "/?"))) { |
nls_outputnl(35,0); /* "Performs conditional processing in batch programs." */ |
outputnl(""); |
nls_outputnl(35,1); /* "IF [NOT] ERRORLEVEL num command" */ |
nls_outputnl(35,2); /* "IF [NOT] string1==string2 command" */ |
nls_outputnl(35,3); /* "IF [NOT] EXIST filename command" */ |
outputnl(""); |
nls_outputnl(35,4); /* "NOT command is executed only if condition is NOT met" */ |
nls_outputnl(35,5); /* "ERRORLEVEL num condition: last program returned an exit code >= num" */ |
nls_outputnl(35,6); /* "string1==string2 condition: both strings must be equal" */ |
nls_outputnl(35,7); /* "EXIST filename condition: filename exists (wildcards accepted)" */ |
nls_outputnl(35,8); /* "command command to carry out if condition is met" */ |
return(CMD_OK); |
} |
/* negation? */ |
if (imatchlim(s, "NOT ", 4)) { |
negflag = 1; |
JMP_NEXT_ARG(s); |
} |
/* IF ERRORLEVEL x cmd */ |
if (imatchlim(s, "ERRORLEVEL ", 11)) { |
unsigned char far *rmod_exitcode = MK_FP(p->rmod->rmodseg, RMOD_OFFSET_LEXITCODE); |
JMP_NEXT_ARG(s); |
if (*s == 0) goto SYNTAX_ERR; |
/* convert errorlevel to an uint */ |
if ((*s < '0') || (*s > '9')) { |
i = 0xffff; |
} else { |
atous(&i, s); |
} |
/* move s to command */ |
JMP_NEXT_ARG(s); |
/* is errorlevel matching? */ |
if (i <= *rmod_exitcode) negflag ^= 1; |
goto EXEC_S_CMD_IF_NEGFLAG_SET; |
} |
/* IF EXIST fname (or wildcard) |
* TODO: checking for a file on an empty diskette drive should NOT lead bother |
* the user with the stupid 'retry, abort, fail' query! */ |
if (imatchlim(s, "EXIST ", 6)) { |
struct DTA *dta = (void *)(0x80); /* default dta location */ |
JMP_NEXT_ARG(s); |
/* copy filename to buffer */ |
for (i = 0; (s[i] != ' ') && (s[i] != 0); i++) p->BUFFER[i] = s[i]; |
p->BUFFER[i] = 0; |
/* move s to command */ |
JMP_NEXT_ARG(s); |
if (*s == 0) goto SYNTAX_ERR; /* check now to avoid moving the diskette drive if syntax bad anyway */ |
/* does file exist? */ |
if (findfirst(dta, p->BUFFER, 0) == 0) negflag ^= 1; |
goto EXEC_S_CMD_IF_NEGFLAG_SET; |
} |
/* IF str1==str2 ? (and if that's not it, then it's a syntax error) */ |
if (strstr(s, "==") != NULL) { |
/* copy first argument to BUFF, until first '=' or space */ |
for (i = 0; (s[i] != '=') && (s[i] != ' '); i++) p->BUFFER[i] = s[i]; |
/* 1st arg cannot be empty */ |
if (i == 0) goto SYNTAX_ERR; |
/* terminate buff string and move s forward to the equality char (or space) */ |
p->BUFFER[i++] = 0; |
s += i; |
while (*s == ' ') s++; |
/* if second char is not a '=' then syntax error (equality sign is not |
* allowed in first string) */ |
if (*s != '=') goto SYNTAX_ERR; |
/* skip all trailing equality chars (MSDOS accepts many of them, ie all |
* these are fine: "dupa==dupa", "dupa===dupa", "dupa====dupa", etc) */ |
while (*s == '=') s++; |
while (*s == ' ') s++; /* skip any leading spaces */ |
/* move along until space or NULL terminator, checking equality */ |
for (i = 0; (p->BUFFER[i] != 0) && (p->BUFFER[i] == s[i]); i++); |
if ((p->BUFFER[i] == 0) && (s[i] == ' ')) negflag ^= 1; |
JMP_NEXT_ARG(s); |
goto EXEC_S_CMD_IF_NEGFLAG_SET; |
} |
/* invalid syntax */ |
SYNTAX_ERR: |
nls_outputnl(0,1); /* "Invalid syntax" */ |
return(CMD_FAIL); |
/* let's exec command (write it to start of cmdline and parse again) */ |
EXEC_S_CMD_IF_NEGFLAG_SET: |
if (*s == 0) goto SYNTAX_ERR; |
if (negflag == 0) return(CMD_OK); |
memmove((void *)(p->cmdline), s, strlen(s) + 1); /* cmdline and s share the same memory! */ |
return(CMD_CHANGED); |
} |
/svarcom/tags/svarcom-2022.1/cmd/ln.c |
---|
0,0 → 1,257 |
/* 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. |
*/ |
/* |
* ln add linkname linkdir |
* ln del linkname |
* ln list [pattern] |
*/ |
static enum cmd_result cmd_lnadd(char *BUFFER, const char *linkname, const char *targetdir, unsigned short env_seg) { |
const char *ext; |
char *realdirname = BUFFER; |
unsigned short realdirnamelen; |
char *buff = BUFFER + 256; |
unsigned short doserr; |
/* convert dirname to realpath */ |
doserr = file_truename(targetdir, realdirname); |
if (doserr != 0) { |
nls_outputnl_doserr(doserr); |
return(CMD_FAIL); |
} |
/* does EXENAME in DIRECTORY exist? */ |
if (lookup_cmd(buff, linkname, realdirname, &ext) != 0) { |
nls_outputnl(29,4); /* "No matching executable found in given path." */ |
return(CMD_FAIL); |
} |
/* open DOSDIR\CFG\LINKS.DB and write realdirname to */ |
if (link_computefname(buff, linkname, env_seg) != 0) return(CMD_FAIL); |
realdirnamelen = strlen(realdirname); |
/* open file *only if it does not exist yet* and write realdirname to it */ |
_asm { |
push ax |
push bx |
push cx |
push dx |
mov ax, 0x6c00 /* extended OPEN */ |
mov bx, 1 /* open for WRITE */ |
xor cx, cx /* create the file with no attributes */ |
mov dx, 0x0010 /* create file if it does not exists, otherwise fail */ |
mov si, buff /* file name */ |
int 0x21 |
jnc WRITE |
mov doserr, ax |
jmp DONE |
WRITE: |
mov bx, ax /* file handle */ |
mov ah, 0x40 /* write to file */ |
mov cx, realdirnamelen |
mov dx, realdirname |
int 0x21 |
mov ah, 0x3e /* close file in BX */ |
int 0x21 |
DONE: |
pop dx |
pop cx |
pop bx |
pop ax |
} |
if (doserr != 0) { |
nls_outputnl_doserr(doserr); |
return(CMD_FAIL); |
} |
return(CMD_OK); |
} |
static enum cmd_result cmd_lndel(char *buff, const char *linkname, unsigned short env_seg) { |
unsigned short i; |
/* is the argument valid? (must not contain any dot nor backslash) */ |
for (i = 0; linkname[i] != 0; i++) { |
if ((linkname[i] == '.') || (linkname[i] == '/') || (linkname[i] == '\\')) { |
nls_outputnl(0,3); /* "Invalid parameter format" */ |
return(CMD_OK); |
} |
} |
/* prep link filename to look at */ |
if (link_computefname(buff, linkname, env_seg) != 0) return(CMD_FAIL); |
/* try removing it */ |
i = 0; |
_asm { |
push ax |
push bx |
push cx |
push dx |
mov ah, 0x41 |
mov dx, buff |
int 0x21 |
jnc SUCCESS |
mov i, ax |
SUCCESS: |
pop dx |
pop cx |
pop bx |
pop ax |
} |
if (i != 0) nls_outputnl_doserr(i); |
return(CMD_OK); |
} |
static enum cmd_result cmd_lnlist(char *buff, const char *linkname, unsigned short env_seg) { |
unsigned short i, pathlen; |
struct DTA *dta = (void *)0x80; |
char *buff128 = buff + 256; |
char *buff16 = buff128 + 128; |
if (linkname != NULL) { |
/* make sure link pattern is valid (must not contain '.' or '\\' or '/') */ |
for (i = 0; linkname[i] != 0; i++) { |
switch (linkname[i]) { |
case '.': |
case '/': |
case '\\': |
nls_outputnl(0,3); /* "Invalid parameter format" */ |
return(CMD_FAIL); |
} |
} |
} else { |
linkname = "*"; |
} |
/* fetch %DOSDIR% */ |
pathlen = env_lookup_valcopy(buff, 128, env_seg, "DOSDIR"); |
if (pathlen == 0) { |
nls_outputnl(29,5); /* "%DOSDIR% not defined" */ |
return(CMD_FAIL); |
} |
/* prep DOSDIR\LINKS\pattern */ |
if (buff[pathlen - 1] == '\\') pathlen--; |
pathlen += sprintf(buff + pathlen, "\\LINKS\\"); |
sprintf(buff + pathlen, "%s.LNK", linkname); |
if (findfirst(dta, buff, DOS_ATTR_RO | DOS_ATTR_ARC) != 0) return(CMD_OK); |
do { |
/* print link file name (but trim ".lnk") */ |
for (i = 0; (dta->fname[i] != 0) && (dta->fname[i] != '.'); i++) buff16[i] = dta->fname[i]; |
if (i < 8) buff16[i++] = '\t'; |
buff16[i] = 0; |
output(buff16); |
output(" @ "); |
/* prep full link filename */ |
strcpy(buff + pathlen, dta->fname); |
/* read up to 128 bytes from link file to buff and display it */ |
i = 0; |
_asm { |
push ax |
push bx |
push cx |
push dx |
/* open file */ |
mov ax, 0x3d00 |
mov dx, buff /* filename */ |
int 0x21 |
jc FAIL_FOPEN |
/* read from file */ |
mov bx, ax |
mov ah, 0x3f |
mov cx, 128 |
mov dx, buff128 |
int 0x21 |
jc FAIL_FREAD |
mov i, ax |
/* close file */ |
FAIL_FREAD: |
mov ah, 0x3e |
int 0x21 |
FAIL_FOPEN: |
pop dx |
pop cx |
pop bx |
pop ax |
} |
buff128[i] = 0; |
/* make sure no cr or lf is present */ |
for (i = 0; buff128[i] != 0; i++) { |
if ((buff128[i] == '\r') || (buff128[i] == '\n')) { |
buff128[i] = 0; |
break; |
} |
} |
outputnl(buff128); |
} while (findnext(dta) == 0); |
return(CMD_OK); |
} |
static enum cmd_result cmd_ln(struct cmd_funcparam *p) { |
if (cmd_ishlp(p)) { |
nls_outputnl(29,0); /* "Adds, deletes or displays executable links." */ |
outputnl(""); |
nls_outputnl(29,1); /* "LN ADD linkname targetdir" */ |
nls_outputnl(29,2); /* "LN DEL linkname" */ |
nls_outputnl(29,3); /* "LN LIST [pattern]" */ |
return(CMD_OK); |
} |
if (p->argc == 0) { |
nls_outputnl(0,7); /* "Required parameter missing */ |
return(CMD_OK); |
} |
/* detect what subfunction the user wants */ |
if ((imatch(p->argv[0], "add")) && (p->argc == 3)) return(cmd_lnadd(p->BUFFER, p->argv[1], p->argv[2], p->env_seg)); |
if ((imatch(p->argv[0], "del")) && (p->argc == 2)) return(cmd_lndel(p->BUFFER, p->argv[1], p->env_seg)); |
if (imatch(p->argv[0], "list")) { |
if (p->argc == 1) return(cmd_lnlist(p->BUFFER, NULL, p->env_seg)); |
if (p->argc == 2) return(cmd_lnlist(p->BUFFER, p->argv[1], p->env_seg)); |
} |
nls_outputnl(0,6); /* "Invalid parameter" */ |
return(CMD_FAIL); |
} |
/svarcom/tags/svarcom-2022.1/cmd/mkdir.c |
---|
0,0 → 1,77 |
/* 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. |
*/ |
/* |
* mkdir |
*/ |
static enum cmd_result cmd_mkdir(struct cmd_funcparam *p) { |
const char *dname = p->argv[0]; |
unsigned short err = 0; |
if (cmd_ishlp(p)) { |
nls_outputnl(28,0); /* "Creates a directory" */ |
outputnl(""); |
nls_outputnl(28,1); /* "MKDIR [drive:]path" */ |
nls_outputnl(28,2); /* "MD [drive:]path" */ |
return(CMD_OK); |
} |
if (p->argc == 0) { |
nls_outputnl(0,7); /* "Required parameter missing" */ |
return(CMD_FAIL); |
} |
if (p->argc > 1) { |
nls_outputnl(0,4); /* "Too many parameters" */ |
return(CMD_FAIL); |
} |
if (p->argv[0][0] == '/') { |
nls_outputnl(0,6); /* "Invalid parameter" */ |
return(CMD_FAIL); |
} |
_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) { |
nls_outputnl_doserr(err); |
return(CMD_FAIL); |
} |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/cmd/path.c |
---|
0,0 → 1,89 |
/* 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. |
*/ |
/* |
* path |
* |
* Displays or sets a search path for executable files. |
*/ |
static enum cmd_result cmd_path(struct cmd_funcparam *p) { |
char *buff = p->BUFFER; |
/* help screen (/?) */ |
if (cmd_ishlp(p)) { |
nls_outputnl(27,0); /* "Displays or sets a search path for executable files." */ |
outputnl(""); |
nls_outputnl(27,1); /* "PATH [[drive:]path[;...]]" */ |
outputnl("PATH ;"); |
outputnl(""); |
nls_outputnl(27,2); /* "Type PATH ; to clear all search-path settings and (...)" */ |
outputnl(""); |
nls_outputnl(27,3); /* "Type PATH without parameters to display the current path." */ |
return(CMD_OK); |
} |
/* no parameter - display current path */ |
if (p->argc == 0) { |
char far *curpath = env_lookup(p->env_seg, "PATH"); |
if (curpath == NULL) { |
nls_outputnl(27,4); /* "No Path" */ |
} else { |
unsigned short i; |
for (i = 0;; i++) { |
buff[i] = curpath[i]; |
if (buff[i] == 0) break; |
} |
outputnl(buff); |
} |
return(CMD_FAIL); |
} |
/* more than 1 parameter */ |
if (p->argc > 1) { |
nls_outputnl(0,4); /* "Too many parameters" */ |
return(CMD_FAIL); |
} |
/* 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(CMD_OK); |
} |
/* 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] == 0) break; |
} |
env_setvar(p->env_seg, buff); |
} |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/cmd/pause.c |
---|
0,0 → 1,38 |
/* This file is part of the SvarCOM project and is published under the terms |
* of the MIT license. |
* |
* Copyright (C) 2021 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. |
*/ |
/* |
* pause |
*/ |
static enum cmd_result cmd_pause(struct cmd_funcparam *p) { |
if (cmd_ishlp(p)) { |
nls_outputnl(15, 0); |
outputnl("\r\nPAUSE"); |
} else { |
press_any_key(); |
} |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/cmd/prompt.c |
---|
0,0 → 1,60 |
/* 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. |
*/ |
/* |
* prompt |
* |
* Changes the DOS command prompt. |
* |
*/ |
static enum cmd_result cmd_prompt(struct cmd_funcparam *p) { |
if (cmd_ishlp(p)) { |
nls_outputnl(33,0); /* "Changes the DOS command prompt." */ |
outputnl(""); |
nls_outputnl(33,1); /* "PROMPT [new command prompt specification]" */ |
return(CMD_OK); |
} |
/* no parameter - restore default prompt path */ |
if (p->argc == 0) { |
env_dropvar(p->env_seg, "PROMPT"); |
return(CMD_OK); |
} |
/* 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] == 0) break; |
} |
env_setvar(p->env_seg, buff); |
} |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/cmd/rem.c |
---|
0,0 → 1,38 |
/* 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. |
*/ |
/* |
* rem |
*/ |
static enum cmd_result cmd_rem(struct cmd_funcparam *p) { |
/* help screen ONLY if /? is the only argument - I do not want to output |
* help for ex. for "REM mouse.com /?" */ |
if ((p->argc == 1) && (imatch(p->argv[0], "/?"))) { |
nls_outputnl(26,0); /* "Records comments (remarks) in a batch file or CONFIG.SYS" */ |
outputnl(""); |
nls_outputnl(26,1); /* "REM [comment]" */ |
} |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/cmd/rename.c |
---|
0,0 → 1,162 |
/* 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. |
*/ |
/* |
* rename/ren |
*/ |
static enum cmd_result cmd_rename(struct cmd_funcparam *p) { |
char *src = p->BUFFER; |
char *dst = p->BUFFER + 256; |
char *buff1 = p->BUFFER + 512; |
char *buff2 = p->BUFFER + 1024; |
unsigned short i, fnameoffset; |
struct DTA *dta = (void *)0x80; /* use default DTA in PSP */ |
if (cmd_ishlp(p)) { |
nls_outputnl(25,0); /* "Renames a file" */ |
outputnl(""); |
nls_outputnl(25,1); /* "RENAME [drive:][path]filename1 filename2" */ |
nls_outputnl(25,2); /* "REN [drive:][path]filename1 filename2" */ |
outputnl(""); |
nls_outputnl(25,3); /* "Note that you cannot specify a new drive or (...)" */ |
return(CMD_OK); |
} |
/* I expect exactly two arguments */ |
if (p->argc != 2) { |
nls_outputnl(0,1); /* "Invalid syntax" */ |
return(CMD_FAIL); |
} |
/* convert src to truename format */ |
i = file_truename(p->argv[0], src); |
if (i != 0) { |
nls_outputnl_doserr(i); |
return(CMD_FAIL); |
} |
/* copy src path to buffers and remember where the filename starts */ |
fnameoffset = 0; |
for (i = 0;; i++) { |
buff1[i] = src[i]; |
buff2[i] = src[i]; |
if (buff1[i] == '\\') fnameoffset = i + 1; |
if (buff1[i] == 0) break; |
} |
/* now append dst filename to the buffer and validate it: cannot contain backslash, slash or ':' */ |
for (i = 0;; i++) { |
switch (p->argv[1][i]) { |
case ':': |
case '\\': |
case '/': |
nls_outputnl(0,8); /* "Invalid destination" */ |
return(CMD_FAIL); |
} |
buff1[fnameoffset + i] = p->argv[1][i]; |
if (buff1[fnameoffset + i] == 0) break; |
} |
/* apply truename to dest to normalize wildcards into ? chars */ |
i = file_truename(buff1, dst); |
if (i != 0) { |
nls_outputnl_doserr(i); |
return(CMD_FAIL); |
} |
/* we're good to go, src and dst should look somehow like that now: |
* src = C:\TEMP\PATH\FILE????.TXT |
* dst = C:\TEMP\PATH\FILE????.DOC |
* buff1 = C:\TEMP\PATH\ |
* buff2 = C:\TEMP\PATH\ |
* fnameoffset = 13 |
* |
* src is used for FindFirst/FindNext iterations, then buff1 is filled with |
* the source filename found by FindFirst/FindNext and buff2 is filled with |
* the destination file (with ?'s replaced by whatever is found at the same |
* location in buff1). |
*/ |
i = findfirst(dta, src, 0); |
if (i != 0) nls_outputnl_doserr(i); |
while (i == 0) { |
/* write found fname into buff1 and dst fname into buff2 - both in FCB |
* format (MYFILE EXT) so it is easy to compare them */ |
file_fname2fcb(buff1 + fnameoffset, dta->fname); |
file_fname2fcb(buff2 + fnameoffset, dst + fnameoffset); |
/* scan buff2 fname for '?' and replace them with whatever is in buff1 */ |
for (i = fnameoffset; buff2[i] != 0; i++) { |
if (buff2[i] == '?') buff2[i] = buff1[i]; |
} |
/* fill buff1 with the 8+3 found file and convert the one in buff2 to 8+3 as well */ |
file_fcb2fname(buff1 + fnameoffset, buff2 + fnameoffset); |
strcpy(buff2 + fnameoffset, buff1 + fnameoffset); |
strcpy(buff1 + fnameoffset, dta->fname); |
/* buff1 contains now a fully resolved source and buff2 a proper destination */ |
#if 0 /* DEBUG ("if 1" to enable) */ |
output(buff1); |
output(" -> "); |
outputnl(buff2); |
#endif |
/* call DOS to do the actual job */ |
i = 0; |
_asm { |
push ax |
push di |
push dx |
push es |
mov ah, 0x56 /* rename file: DS:DX=ASCIIZ of src ES:DI=ASCIIZ of dst */ |
push ds |
pop es |
mov dx, buff1 |
mov di, buff2 |
int 0x21 /* CF clear on success, otherwise err code in AX */ |
jnc DONE |
mov [i], ax /* copy error code to i */ |
DONE: |
pop es |
pop dx |
pop di |
pop ax |
} |
if (i != 0) { |
output(buff1 + fnameoffset); |
output(" -> "); |
output(buff2 + fnameoffset); |
output(" "); |
nls_outputnl_doserr(i); |
} |
/* next please */ |
i = findnext(dta); |
} |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/cmd/rmdir.c |
---|
0,0 → 1,77 |
/* 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. |
*/ |
/* |
* rmdir |
*/ |
static enum cmd_result cmd_rmdir(struct cmd_funcparam *p) { |
const char *dname = p->argv[0]; |
unsigned short err = 0; |
if (cmd_ishlp(p)) { |
nls_outputnl(24,0); /* "Removes (deletes) a directory" */ |
outputnl(""); |
nls_outputnl(24,1);/* "RMDIR [drive:]path" */ |
nls_outputnl(24,2);/* "RD [drive:]path" */ |
return(CMD_OK); |
} |
if (p->argc == 0) { |
nls_outputnl(0,7); /* "Required parameter missing" */ |
return(CMD_FAIL); |
} |
if (p->argc > 1) { |
nls_outputnl(0,4); /* "Too many parameters" */ |
return(CMD_FAIL); |
} |
if (p->argv[0][0] == '/') { |
nls_outputnl(0,6); /* "Invalid parameter"); */ |
return(CMD_FAIL); |
} |
_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) { |
nls_outputnl_doserr(err); |
return(CMD_FAIL); |
} |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/cmd/set.c |
---|
0,0 → 1,100 |
/* 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. |
*/ |
/* |
* set [varname[=value]] |
* |
* value cannot contain any '=' character, but it can contain spaces |
* varname can also contain spaces |
*/ |
static enum cmd_result cmd_set(struct cmd_funcparam *p) { |
char far *env = MK_FP(p->env_seg, 0); |
char *buff = p->BUFFER; |
if (cmd_ishlp(p)) { |
nls_outputnl(23,0); /* "Displays, sets, or removes DOS environment variables"); */ |
outputnl(""); |
nls_outputnl(23,1); /* "SET [variable=[string]]" */ |
outputnl(""); |
nls_outputnl(23,2); /* "variable Specifies the environment-variable name" */ |
nls_outputnl(23,3); /* "string Specifies a series of characters to assign to the variable" */ |
outputnl(""); |
nls_outputnl(23,4); /* "Type SET without parameters to display the current environment variables." */ |
return(CMD_OK); |
} |
/* 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 == 0) goto syntax_err; |
buff[i] = *ptr; |
if ((buff[i] >= 'a') && (buff[i] <= 'z')) buff[i] -= ('a' - 'A'); |
i++; |
} |
/* copy value now */ |
while (*ptr != 0) { |
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) { |
nls_outputnl(23,5); /* "Not enough available space within the environment block" */ |
return(CMD_FAIL); |
} |
} |
return(CMD_OK); |
syntax_err: |
nls_outputnl(0,1); /* "Invalid syntax" */ |
return(CMD_FAIL); |
} |
/svarcom/tags/svarcom-2022.1/cmd/shift.c |
---|
0,0 → 1,53 |
/* This file is part of the SvarCOM project and is published under the terms |
* of the MIT license. |
* |
* Copyright (C) 2021 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. |
*/ |
/* |
* shift |
*/ |
static enum cmd_result cmd_shift(struct cmd_funcparam *p) { |
char far *batargv; |
char far *nextarg; |
if (cmd_ishlp(p)) { |
nls_outputnl(16, 0); |
nls_outputnl(16, 1); |
outputnl(""); |
outputnl("SHIFT"); |
return(CMD_OK); |
} |
/* abort if batargv is empty */ |
if ((p->rmod->bat == NULL) || (p->rmod->bat->argv[0] == 0)) return(CMD_OK); |
batargv = p->rmod->bat->argv; |
/* find the next argument in batargv */ |
for (nextarg = batargv + 1; *nextarg != 0; nextarg++); |
nextarg++; /* move ptr past the zero terminator */ |
/* move down batargv so 2nd argument is at the head now */ |
_fmemmove(batargv, nextarg, sizeof(p->rmod->bat->argv) - (nextarg - batargv)); |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/cmd/time.c |
---|
0,0 → 1,253 |
/* 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. |
*/ |
/* |
* time [time] |
*/ |
/* read a one or two digit number and write it to buff */ |
static int cmd_time_get_item(char *buff, const char *s) { |
unsigned short i; |
for (i = 0; i < 3; i++) { |
if ((s[i] < '0') || (s[i] > '9')) { |
buff[i] = 0; |
return(0); |
} |
buff[i] = s[i]; |
} |
/* err */ |
*buff = 0; |
return(-1); |
} |
/* parse a NULL-terminated string int hour, minutes and seconds, returns 0 on success |
* valid inputs: 0, 7, 5:5, 23:23, 17:54:45, 9p, 9:05, ... |
*/ |
static int cmd_time_parse(const char *s, signed char *ho, signed char *mi, signed char *se, struct nls_patterns *nls) { |
unsigned short i; |
const char *ptrs[2] = {NULL, NULL}; /* minutes, seconds */ |
char buff[3]; |
char ampm = 0; |
*ho = -1; |
*mi = 0; |
*se = 0; |
/* validate input - must contain only chars 0-9, time separator and 'a' or 'p' */ |
for (i = 0; s[i] != 0; i++) { |
switch (s[i]) { |
case '0': |
case '1': |
case '2': |
case '3': |
case '4': |
case '5': |
case '6': |
case '7': |
case '8': |
case '9': |
break; |
case 'a': |
case 'A': |
case 'p': |
case 'P': |
/* these can be only at last position and never at the first */ |
if ((s[i + 1] != 0) || (i == 0)) return(-1); |
ampm = s[i]; |
if (ampm >= 'a') ampm -= ('a' - 'A'); |
break; |
default: |
if ((s[i] != nls->timesep[0]) || (i == 0)) return(-1); |
if (ptrs[0] == NULL) { |
ptrs[0] = s + i + 1; |
} else if (ptrs[1] == NULL) { |
ptrs[1] = s + i + 1; |
} else { /* too many separators */ |
return(-1); |
} |
break; |
} |
} |
/* read hour */ |
if (cmd_time_get_item(buff, s) != 0) goto FAIL; |
if (atous(&i, buff) != 0) goto FAIL; |
*ho = i; |
/* if minutes provided, read them */ |
if (ptrs[0] != NULL) { |
if (cmd_time_get_item(buff, ptrs[0]) != 0) goto FAIL; |
if (atous(&i, buff) != 0) goto FAIL; |
*mi = i; |
} |
/* if seconds provided, read them */ |
if (ptrs[1] != NULL) { |
if (cmd_time_get_item(buff, ptrs[1]) != 0) goto FAIL; |
if (atous(&i, buff) != 0) goto FAIL; |
*se = i; |
} |
/* validate ranges */ |
if ((*ho > 23) || (*mi > 59) || (*se > 59)) goto FAIL; |
/* am? */ |
if ((ampm == 'A') && (*ho > 12)) goto FAIL; |
if ((ampm == 'A') && (*ho == 12)) *ho = 0; /* 12:00am is 00:00 (midnight) */ |
/* pm? */ |
if (ampm == 'P') { |
if (*ho > 12) goto FAIL; |
if (*ho < 12) *ho += 12; |
} |
return(0); |
FAIL: |
*ho = -1; |
return(-1); |
} |
static enum cmd_result cmd_time(struct cmd_funcparam *p) { |
struct nls_patterns *nls = (void *)(p->BUFFER); |
char *buff = p->BUFFER + sizeof(*nls); |
unsigned short i; |
signed char ho = -1, mi = -1, se = -1; |
if (cmd_ishlp(p)) { |
nls_outputnl(22,0); /* "Displays or sets the system time." */ |
outputnl(""); |
nls_outputnl(22,1); /* "TIME [time]" */ |
outputnl(""); |
nls_outputnl(22,2); /* "Type TIME with no parameters to display the current time and (...)" */ |
return(CMD_OK); |
} |
i = nls_getpatterns(nls); |
if (i != 0) { |
nls_outputnl_doserr(i); |
return(CMD_FAIL); |
} |
/* display current time if no args */ |
if (p->argc == 0) { |
/* get cur time */ |
_asm { |
push ax |
push bx |
push cx |
push dx |
mov ah, 0x2c /* DOS 1+ -- Query DOS Time */ |
int 0x21 /* CH=hour CL=minutes DH=seconds DL=1/100sec */ |
mov [ho], ch |
mov [mi], cl |
mov [se], dh |
pop dx |
pop cx |
pop bx |
pop ax |
} |
buff[0] = ' '; |
nls_format_time(buff + 1, ho, mi, se, nls); |
nls_output(22,3); /* "Current time is" */ |
outputnl(buff); |
ho = -1; |
} else { /* parse time if provided */ |
if (cmd_time_parse(p->argv[0], &ho, &mi, &se, nls) != 0) { |
nls_outputnl(22,4); /* "Invalid time" */ |
ho = -1; |
} |
} |
/* ask for time if not provided or if input was malformed */ |
while (ho < 0) { |
nls_output(22,5); /* "Enter new time:" */ |
output(" "); |
/* collect user input into buff */ |
_asm { |
push ax |
push bx |
push dx |
mov ah, 0x0a /* DOS 1+ -- Buffered String Input */ |
mov bx, buff |
mov dx, bx |
mov al, 16 |
mov [bx], al /* max input length */ |
mov al, 1 |
mov [bx+1], al /* zero out the "previous entry" length */ |
int 0x21 |
/* terminate the string with a NULL terminator */ |
xor ax, ax |
inc bx |
mov al, [bx] /* read length of input string */ |
mov bx, ax |
add bx, dx |
mov [bx+2], ah |
/* output a \n */ |
mov ah, 2 |
mov dl, 0x0A |
int 0x21 |
pop dx |
pop bx |
pop ax |
} |
if (buff[1] == 0) break; /* empty string = do not change time */ |
if (cmd_time_parse(buff + 2, &ho, &mi, &se, nls) == 0) break; |
nls_outputnl(22,4); /* "Invalid time" */ |
return(CMD_FAIL); |
} |
if (ho >= 0) { |
/* set time */ |
_asm { |
push ax |
push bx |
push cx |
push dx |
mov ah, 0x2d /* DOS 1+ -- Set DOS Time */ |
mov ch, [ho] /* hour (0-23) */ |
mov cl, [mi] /* minutes (0-59) */ |
mov dh, [se] /* seconds (0-59) */ |
mov dl, 0 /* 1/100th seconds (0-99) */ |
int 0x21 |
pop dx |
pop cx |
pop bx |
pop ax |
} |
} |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/cmd/type.c |
---|
0,0 → 1,113 |
/* 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. |
*/ |
/* |
* type |
*/ |
static enum cmd_result cmd_type(struct cmd_funcparam *p) { |
char *buff = p->BUFFER; |
const char *fname = p->argv[0]; |
unsigned short err = 0; |
if (cmd_ishlp(p)) { |
nls_outputnl(21,0); /* "Displays the contents of a text file." */ |
outputnl(""); |
nls_outputnl(21,1); /* "TYPE [drive:][path]filename" */ |
return(CMD_OK); |
} |
if (p->argc == 0) { |
nls_outputnl(0,7); /* "Required parameter missing" */ |
return(CMD_FAIL); |
} |
if (p->argc > 1) { |
nls_outputnl(0,4); /* "Too many parameters" */ |
return(CMD_FAIL); |
} |
/* 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) { |
nls_outputnl_doserr(err); |
return(CMD_FAIL); |
} |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/cmd/ver.c |
---|
0,0 → 1,127 |
/* 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. |
*/ |
/* |
* ver |
*/ |
#define PVER "2022.1" |
#define COPYRDATE "2021-2022" |
static enum cmd_result cmd_ver(struct cmd_funcparam *p) { |
char *buff = p->BUFFER; |
unsigned char maj = 0, min = 0; |
/* help screen */ |
if (cmd_ishlp(p)) { |
nls_outputnl(20,0); /* "Displays the DOS version." */ |
outputnl(""); |
outputnl("ver [/about]"); |
#ifdef VERDBG |
outputnl("ver /dbg"); |
#endif |
return(CMD_OK); |
} |
#ifdef VERDBG |
if ((p->argc == 1) && (imatch(p->argv[0], "/dbg"))) { |
unsigned short far *rmod_envseg = MK_FP(p->rmod->rmodseg, RMOD_OFFSET_ENVSEG); |
unsigned char far *rmod_exitcode = MK_FP(p->rmod->rmodseg, RMOD_OFFSET_LEXITCODE); |
unsigned short far *rmod_comspecptr = MK_FP(p->rmod->rmodseg, RMOD_OFFSET_COMSPECPTR); |
char far *fptr; |
unsigned short i; |
printf("rmod->rmodseg = 0x%04X\r\n", p->rmod->rmodseg); |
printf("rmod->origparent = %04X:%04X\r\n", p->rmod->origparent >> 16, p->rmod->origparent & 0xffff); |
printf("rmod->origenvseg = 0x%04X\r\n", p->rmod->origenvseg); |
printf("rmod->flags = 0x%02X\r\n", p->rmod->flags); |
printf("[rmod:RMOD_OFFSET_ENVSEG] = 0x%04X\r\n", *rmod_envseg); |
printf("environment allocated size: %u bytes\r\n", env_allocsz(*rmod_envseg)); |
for (fptr = MK_FP(p->rmod->rmodseg, RMOD_OFFSET_BOOTDRIVE), i = 0; *fptr != 0; fptr++) buff[i++] = *fptr; |
buff[i] = 0; |
printf("[rmod:RMOD_OFFSET_BOOTCOMSPEC] = '%s'\r\n", buff); |
if (*rmod_comspecptr == 0) { |
sprintf(buff, "NULL"); |
} else { |
for (fptr = MK_FP(*rmod_envseg, *rmod_comspecptr), i = 0; *fptr != 0; fptr++) buff[i++] = *fptr; |
buff[i] = 0; |
} |
printf("[rmod:RMOD_OFFSET_COMSPECPTR] = '%s'\r\n", buff); |
printf("[rmod:RMOD_OFFSET_LEXITCODE] = %u\r\n", *rmod_exitcode); |
printf("rmod dump (first 64 bytes at [rmodseg:0100h]):\r\n"); |
fptr = MK_FP(p->rmod->rmodseg, 0x100); |
for (i = 0; i < 64; i += 16) { |
int ii; |
for (ii = i; ii < i + 16; ii++) printf(" %02X", fptr[ii]); |
printf(" "); |
for (ii = i; ii < i + 16; ii++) { |
if (fptr[ii] < ' ') { |
printf("."); |
} else { |
printf("%c", fptr[ii]); |
} |
} |
printf("\r\n"); |
} |
return(CMD_OK); |
} |
#endif |
if ((p->argc == 1) && (imatch(p->argv[0], "/about"))) { |
nls_outputnl(20,3); /* "SvarCOM is a shell interpreter for DOS kernels compatible with MS-DOS 5+." */ |
outputnl(""); |
nls_outputnl(20,4); /* "This software is distributed under the terms of the MIT license." */ |
outputnl("Copyright (C) " COPYRDATE " Mateusz Viste"); |
outputnl(""); |
outputnl("Program ten dedykuje Milenie i Mojmirowi. Zycze wam, byscie w swoim zyciu"); |
outputnl("potrafili docenic wartosci minionych pokolen, jednoczesnie czerpiac radosc"); |
outputnl("z prostych przyjemnosci dnia codziennego. Lair, jesien 2021."); |
return(CMD_OK); |
} |
if (p->argc != 0) { |
nls_outputnl(0,6); /* "Invalid parameter" */ |
return(CMD_FAIL); |
} |
_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, svarlang_str(20,1), maj, min); /* "DOS kernel version %u.%u" */ |
outputnl(buff); |
nls_output(20,2); /* "SvarCOM shell ver" */ |
outputnl(" " PVER); |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/cmd/verify.c |
---|
0,0 → 1,89 |
/* 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. |
*/ |
/* |
* verify |
*/ |
static enum cmd_result cmd_verify(struct cmd_funcparam *p) { |
if (cmd_ishlp(p)) { |
nls_outputnl(19,0); /* "Tells DOS whether to verify that files are written correctly to disk." */ |
outputnl(""); |
outputnl("VERIFY [ON | OFF]"); |
outputnl(""); |
nls_outputnl(19,1); /* "Type VERIFY without a parameter to display its current setting." */ |
return(CMD_OK); |
} |
if (p->argc > 1) { |
nls_outputnl(0,4); /* "Too many parameters" */ |
return(CMD_FAIL); |
} |
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) { |
nls_outputnl(19,2); /* "VERIFY is off" */ |
} else { |
nls_outputnl(19,3); /* "VERIFY is on" */ |
} |
return(CMD_OK); |
} |
/* 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 { |
nls_outputnl(19,4); /* "Must specify ON or OFF" */ |
return(CMD_FAIL); |
} |
return(CMD_OK); |
} |
/svarcom/tags/svarcom-2022.1/cmd/vol.c |
---|
0,0 → 1,150 |
/* 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. |
*/ |
/* |
* vol [drive:] |
*/ |
static void cmd_vol_internal(unsigned char drv, char *buff) { |
unsigned short *buff16 = (void *)(buff); |
unsigned short err = 0; |
struct DTA *dta = (void *)0x80; /* use the default DTA at location 80h in PSP */ |
outputnl(""); /* start with an empty line to mimic MS-DOS */ |
/* look for volume label in root dir via a FindFirst call */ |
sprintf(buff, "%c:\\????????.???", drv + 'A'); |
_asm { |
push ax |
push cx |
push dx |
mov [err], 0 /* preset errflag to zero */ |
mov ah, 0x4e /* FindFirst */ |
mov dx, buff |
mov cx, 0x08 /* match volume labels only */ |
int 0x21 /* dta filled or CF set on error */ |
jnc DONE |
mov [err], ax |
DONE: |
pop dx |
pop cx |
pop ax |
} |
if (err != 0) { |
sprintf(buff, svarlang_str(34,2)/*"Volume in drive %c has no label"*/, drv + 'A'); |
} else { |
/* if label > 8 chars then drop the dot (DRIVE_LA.BEL -> DRIVE_LABEL) */ |
if (strlen(dta->fname) > 8) memmove(dta->fname + 8, dta->fname + 9, 4); |
sprintf(buff, svarlang_str(34,3)/*"Volume in drive %c is %s"*/, drv + 'A', dta->fname); |
} |
outputnl(buff); |
/* try to fetch the disk's serial number (DOS 4+ internal call) */ |
err = 0; |
_asm { |
push ax |
push bx |
push dx |
mov ax, 0x6900 |
mov bl, drv /* A=1, B=2, etc */ |
inc bl /* adjust BL to +1 since drv is 0-based (A=0, B=1, etc) */ |
xor bh, bh /* "info level", must be 0 */ |
mov dx, buff /* pointer to a location where a DiskInfo struct will be written */ |
int 0x21 |
jnc DONE |
mov [err], ax /* err code */ |
DONE: |
pop dx |
pop bx |
pop ax |
} |
/* Format of DiskInfo struct (source: RBIL) |
Offset Size Description (Table 01766) |
00h WORD 0000h (info level) |
02h DWORD disk serial number (binary) |
06h 11 BYTEs volume label or "NO NAME " if none present |
11h 8 BYTEs filesystem type */ |
if ((err == 0) && (buff16[1] | buff16[2])) { |
sprintf(buff + 64, svarlang_str(34,4)/*"Volume Serial Number is %04X-%04X"*/, buff16[2], buff16[1]); |
outputnl(buff + 64); |
} |
} |
static enum cmd_result cmd_vol(struct cmd_funcparam *p) { |
char drv = 0; |
char curdrv = 0; |
unsigned short i; |
if (cmd_ishlp(p)) { |
nls_outputnl(34,0); /* "Displays the disk volume label and serial number, if they exist." */ |
outputnl(""); |
nls_outputnl(34,1); /* "VOL [drive:]" */ |
return(CMD_OK); |
} |
for (i = 0; i < p->argc; i++) { |
if (p->argv[i][0] == '/') { |
nls_outputnl(0,2); /* "Invalid switch" */ |
return(CMD_FAIL); |
} |
if (drv != 0) { |
nls_outputnl(0,4); /* "Too many parameters" */ |
return(CMD_FAIL); |
} |
if ((p->argv[i][0] == 0) || (p->argv[i][1] != ':') || (p->argv[i][2] != 0)) { |
nls_outputnl(0,3); /* "Invalid parameter format" */ |
return(CMD_FAIL); |
} |
drv = p->argv[i][0]; |
/* convert drive letter to a value 1..x (1=A, 2=B, etc) */ |
if ((drv >= 'a') && (drv <= 'z')) { |
drv -= 'a'; |
} else { |
drv -= 'A'; |
} |
} |
/* fetch current drive */ |
_asm { |
push ax |
mov ah, 0x19 /* query default (current) disk */ |
int 0x21 /* drive in AL (0=A, 1=B, etc) */ |
mov [curdrv], al |
pop ax |
} |
/* if no drive specified, use the default one */ |
if (drv == 0) { |
drv = curdrv; |
} else if (!isdrivevalid(drv)) { /* is specified drive valid? */ |
nls_outputnl(255,15); /* "Invalid drive" */ |
return(CMD_FAIL); |
} |
cmd_vol_internal(drv, p->BUFFER); |
return(CMD_OK); |
} |