From 34b50d2a29bc81aca1efbb733222c99dec0a3f46 Mon Sep 17 00:00:00 2001 From: Sepp J Morris Date: Wed, 4 Nov 2020 23:59:28 +0100 Subject: [PATCH] Upload --- COMMAND/BATCH.C | 2653 ++++++++++++++++++++++++++ COMMAND/BIN/BATCH.OBJ | Bin 0 -> 13105 bytes COMMAND/BIN/CMDLIST.OBJ | Bin 0 -> 2335 bytes COMMAND/BIN/COM.OBJ | Bin 0 -> 9945 bytes COMMAND/BIN/COMCPY.OBJ | Bin 0 -> 7149 bytes COMMAND/BIN/COMINT.OBJ | Bin 0 -> 11762 bytes COMMAND/BIN/COMMAND.COM | Bin 0 -> 55173 bytes COMMAND/BIN/COMMAND.EXE | Bin 0 -> 43440 bytes COMMAND/BIN/CONFIG.OBJ | Bin 0 -> 1565 bytes COMMAND/BIN/CRIT.OBJ | Bin 0 -> 1073 bytes COMMAND/BIN/CSTART.OBJ | Bin 0 -> 8300 bytes COMMAND/BIN/CSUP.OBJ | Bin 0 -> 3917 bytes COMMAND/BIN/DOSIF.OBJ | Bin 0 -> 2800 bytes COMMAND/BIN/GLOBAL.OBJ | Bin 0 -> 978 bytes COMMAND/BIN/HELPSTUB.OBJ | Bin 0 -> 141 bytes COMMAND/BIN/MESSAGE.OBJ | Bin 0 -> 7846 bytes COMMAND/BIN/PRINTF.OBJ | Bin 0 -> 2511 bytes COMMAND/BIN/RESIDENT.OBJ | Bin 0 -> 1344 bytes COMMAND/BIN/SUPPORT.OBJ | Bin 0 -> 6033 bytes COMMAND/BIN/TXHELP.BIN | Bin 0 -> 11733 bytes COMMAND/BIN/TXHELP.EXE | Bin 0 -> 12245 bytes COMMAND/BIN/TXHELP.OBJ | Bin 0 -> 13209 bytes COMMAND/CHAR.DEF | 74 + COMMAND/CMDLIST.C | 212 +++ COMMAND/COM.C | 1833 ++++++++++++++++++ COMMAND/COMCPY.C | 1490 +++++++++++++++ COMMAND/COMINT.C | 2173 +++++++++++++++++++++ COMMAND/COMMAND.H | 238 +++ COMMAND/COMMAND.MAP | 1258 +++++++++++++ COMMAND/CONFIG.C | 574 ++++++ COMMAND/CRIT.ASM | 589 ++++++ COMMAND/CSTART.ASM | 3837 ++++++++++++++++++++++++++++++++++++++ COMMAND/CSUP.ASM | 756 ++++++++ COMMAND/DEFINES.H | 38 + COMMAND/DOS.H | 116 ++ COMMAND/DOSIF.ASM | 2907 +++++++++++++++++++++++++++++ COMMAND/DOSIF.H | 181 ++ COMMAND/DRIVER.EQU | 59 + COMMAND/F52DATA.DEF | 88 + COMMAND/GLOBAL.C | 168 ++ COMMAND/GLOBAL.H | 155 ++ COMMAND/HELP.H | 198 ++ COMMAND/HELPSTUB.ASM | 62 + COMMAND/IDLE.H | 52 + COMMAND/LOGIN.H | 151 ++ COMMAND/MAKE.BAT | 122 ++ COMMAND/MESSAGE.ASM | 514 +++++ COMMAND/MESSAGE.DEF | 246 +++ COMMAND/MESSAGE.H | 123 ++ COMMAND/MSDOS.EQU | 131 ++ COMMAND/MSERROR.EQU | 121 ++ COMMAND/MSERROR.H | 102 + COMMAND/PORTAB.H | 209 +++ COMMAND/PRINTF.C | 560 ++++++ COMMAND/RESIDENT.ASM | 126 ++ COMMAND/RESIDENT.DEF | 54 + COMMAND/RESIDENT.H | 27 + COMMAND/RESP1 | 3 + COMMAND/RESP2 | 11 + COMMAND/RESP3 | 3 + COMMAND/SECURITY.H | 240 +++ COMMAND/STRUCT.H | 89 + COMMAND/SUPPORT.C | 1302 +++++++++++++ COMMAND/SUPPORT.H | 88 + COMMAND/TOUPPER.H | 348 ++++ COMMAND/TXHELP.ASM | 312 ++++ COMMAND/TXHELP.DEF | 57 + COMMAND/TXHELP.H | 111 ++ COMMAND/TXLOGIN.H | 127 ++ IBMBIO/BDOSLDR.A86 | 573 ++++++ IBMBIO/BDOSSTUB.A86 | 48 + IBMBIO/BIN/BDOSLDR.OBJ | Bin 0 -> 1871 bytes IBMBIO/BIN/BDOSSTUB.OBJ | Bin 0 -> 188 bytes IBMBIO/BIN/BIOS.MAP | 418 +++++ IBMBIO/BIN/BIOSGRPS.OBJ | Bin 0 -> 307 bytes IBMBIO/BIN/BIOSINIT.OBJ | Bin 0 -> 5833 bytes IBMBIO/BIN/BIOSMSGS.OBJ | Bin 0 -> 575 bytes IBMBIO/BIN/BIOSSTUB.LIB | Bin 0 -> 1024 bytes IBMBIO/BIN/CLOCK.OBJ | Bin 0 -> 1235 bytes IBMBIO/BIN/CONFIG.OBJ | Bin 0 -> 4810 bytes IBMBIO/BIN/CONFSTUB.OBJ | Bin 0 -> 188 bytes IBMBIO/BIN/CONSOLE.OBJ | Bin 0 -> 876 bytes IBMBIO/BIN/DISK.OBJ | Bin 0 -> 6634 bytes IBMBIO/BIN/GENERCFG.OBJ | Bin 0 -> 9616 bytes IBMBIO/BIN/IBMBIO.COM | Bin 0 -> 27880 bytes IBMBIO/BIN/INIT.OBJ | Bin 0 -> 5036 bytes IBMBIO/BIN/INITMSGS.OBJ | Bin 0 -> 1317 bytes IBMBIO/BIN/NLSFUNC.OBJ | Bin 0 -> 1045 bytes IBMBIO/BIN/SERPAR.OBJ | Bin 0 -> 969 bytes IBMBIO/BIN/STACKS.OBJ | Bin 0 -> 1230 bytes IBMBIO/BIOS.LNK | 4 + IBMBIO/BIOSGRPS.ASM | 39 + IBMBIO/BIOSGRPS.EQU | 75 + IBMBIO/BIOSINIT.A86 | 1805 ++++++++++++++++++ IBMBIO/BIOSMSGS.ASM | 36 + IBMBIO/BIOSMSGS.DEF | 8 + IBMBIO/BIOSMSGS.H | 4 + IBMBIO/BIOSSTUB.LIB | Bin 0 -> 1024 bytes IBMBIO/BPB.EQU | 50 + IBMBIO/CHAR.DEF | 74 + IBMBIO/CLOCK.ASM | 467 +++++ IBMBIO/CONFIG.A86 | 1404 ++++++++++++++ IBMBIO/CONFIG.EQU | 124 ++ IBMBIO/CONFSTUB.A86 | 45 + IBMBIO/CONSOLE.ASM | 307 +++ IBMBIO/COUNTRY.DEF | 73 + IBMBIO/DISK.ASM | 2618 ++++++++++++++++++++++++++ IBMBIO/DOSHNDL.DEF | 123 ++ IBMBIO/DRIVER.EQU | 59 + IBMBIO/DRMACROS.EQU | 85 + IBMBIO/F52DATA.DEF | 88 + IBMBIO/FDOS.EQU | 220 +++ IBMBIO/GENERCFG.A86 | 3607 +++++++++++++++++++++++++++++++++++ IBMBIO/IBMROS.EQU | 83 + IBMBIO/INIT.ASM | 1080 +++++++++++ IBMBIO/INITMSGS.ASM | 82 + IBMBIO/INITMSGS.DEF | 32 + IBMBIO/INITMSGS.H | 16 + IBMBIO/MAKE.BAT | 119 ++ IBMBIO/MODFUNC.DEF | 327 ++++ IBMBIO/MSDOS.EQU | 131 ++ IBMBIO/MSERROR.EQU | 121 ++ IBMBIO/NLSFUNC.A86 | 417 +++++ IBMBIO/PATCH.COD | 104 ++ IBMBIO/PSP.DEF | 108 ++ IBMBIO/REQHDR.EQU | 167 ++ IBMBIO/REQUEST.EQU | 193 ++ IBMBIO/SERPAR.ASM | 332 ++++ IBMBIO/STACKS.ASM | 365 ++++ IBMBIO/UDSC.EQU | 64 + IBMDOS/BDEVIO.A86 | 1474 +++++++++++++++ IBMDOS/BDOS.EQU | 80 + IBMDOS/BIN/BDEVIO.OBJ | Bin 0 -> 4352 bytes IBMDOS/BIN/BUFFERS.OBJ | Bin 0 -> 2688 bytes IBMDOS/BIN/CDEVIO.OBJ | Bin 0 -> 1408 bytes IBMDOS/BIN/CIO.LST | 2496 +++++++++++++++++++++++++ IBMDOS/BIN/CIO.OBJ | Bin 0 -> 2688 bytes IBMDOS/BIN/CIO.SYM | 219 +++ IBMDOS/BIN/CMDLINE.LST | 1921 +++++++++++++++++++ IBMDOS/BIN/CMDLINE.OBJ | Bin 0 -> 2944 bytes IBMDOS/BIN/CMDLINE.SYM | 133 ++ IBMDOS/BIN/DIRS.OBJ | Bin 0 -> 2176 bytes IBMDOS/BIN/DISK.OBJ | Bin 0 -> 3200 bytes IBMDOS/BIN/DOSMEM.LST | 1024 ++++++++++ IBMDOS/BIN/DOSMEM.OBJ | Bin 0 -> 1664 bytes IBMDOS/BIN/DOSMEM.SYM | 101 + IBMDOS/BIN/ERROR.LST | 1475 +++++++++++++++ IBMDOS/BIN/ERROR.OBJ | Bin 0 -> 1664 bytes IBMDOS/BIN/ERROR.SYM | 152 ++ IBMDOS/BIN/FCBS.LST | 1681 +++++++++++++++++ IBMDOS/BIN/FCBS.OBJ | Bin 0 -> 2176 bytes IBMDOS/BIN/FCBS.SYM | 142 ++ IBMDOS/BIN/FDOS.OBJ | Bin 0 -> 12032 bytes IBMDOS/BIN/FIOCTL.OBJ | Bin 0 -> 1408 bytes IBMDOS/BIN/HEADER.OBJ | Bin 0 -> 7040 bytes IBMDOS/BIN/HISTORY.LST | 1064 +++++++++++ IBMDOS/BIN/HISTORY.OBJ | Bin 0 -> 1664 bytes IBMDOS/BIN/HISTORY.SYM | 91 + IBMDOS/BIN/IBMDOS.COM | Bin 0 -> 30081 bytes IBMDOS/BIN/IBMDOS.INP | 5 + IBMDOS/BIN/IBMDOS.MAP | 154 ++ IBMDOS/BIN/IBMDOS.SYM | 179 ++ IBMDOS/BIN/IBMDOS.TMP | Bin 0 -> 48128 bytes IBMDOS/BIN/INT2F.OBJ | Bin 0 -> 3072 bytes IBMDOS/BIN/IOCTL.OBJ | Bin 0 -> 1536 bytes IBMDOS/BIN/MISC.OBJ | Bin 0 -> 4352 bytes IBMDOS/BIN/NETWORK.LST | 696 +++++++ IBMDOS/BIN/NETWORK.OBJ | Bin 0 -> 896 bytes IBMDOS/BIN/NETWORK.SYM | 83 + IBMDOS/BIN/PCMIF.OBJ | Bin 0 -> 4352 bytes IBMDOS/BIN/PROCESS.OBJ | Bin 0 -> 3968 bytes IBMDOS/BIN/REDIR.OBJ | Bin 0 -> 3200 bytes IBMDOS/BIN/SUPPORT.LST | 875 +++++++++ IBMDOS/BIN/SUPPORT.OBJ | Bin 0 -> 1152 bytes IBMDOS/BIN/SUPPORT.SYM | 93 + IBMDOS/BUFFERS.A86 | 1300 +++++++++++++ IBMDOS/CDEVIO.A86 | 523 ++++++ IBMDOS/CHAR.DEF | 74 + IBMDOS/CIO.A86 | 1068 +++++++++++ IBMDOS/CMDLINE.A86 | 1111 +++++++++++ IBMDOS/CMDLINE.EQU | 70 + IBMDOS/COUNTRY.A86 | 3662 ++++++++++++++++++++++++++++++++++++ IBMDOS/COUNTRY.DEF | 73 + IBMDOS/DIRS.A86 | 827 ++++++++ IBMDOS/DISK.A86 | 1153 ++++++++++++ IBMDOS/DOSHNDL.DEF | 122 ++ IBMDOS/DOSMEM.A86 | 521 ++++++ IBMDOS/DRIVER.EQU | 60 + IBMDOS/ERROR.A86 | 469 +++++ IBMDOS/EXE.DEF | 52 + IBMDOS/F52DATA.DEF | 90 + IBMDOS/FCBS.A86 | 960 ++++++++++ IBMDOS/FDOS.A86 | 425 +++++ IBMDOS/FDOS.DEF | 126 ++ IBMDOS/FDOS.EQU | 227 +++ IBMDOS/FIOCTL.A86 | 503 +++++ IBMDOS/FUNCS.FDO | 2394 ++++++++++++++++++++++++ IBMDOS/HEADER.A86 | 1574 ++++++++++++++++ IBMDOS/HISTORY.A86 | 541 ++++++ IBMDOS/IBMDOS.INP | 5 + IBMDOS/IBMDOS.MAP | 154 ++ IBMDOS/IBMDOS.SYM | 179 ++ IBMDOS/INT2F.A86 | 1245 +++++++++++++ IBMDOS/IOCTL.A86 | 468 +++++ IBMDOS/MAKE.BAT | 109 ++ IBMDOS/MISC.A86 | 1829 ++++++++++++++++++ IBMDOS/MODFUNC.DEF | 328 ++++ IBMDOS/MSDOS.EQU | 130 ++ IBMDOS/MSERROR.EQU | 122 ++ IBMDOS/NETWORK.A86 | 151 ++ IBMDOS/PATCH.COD | 104 ++ IBMDOS/PCMIF.A86 | 1028 ++++++++++ IBMDOS/PCMODE.EQU | 179 ++ IBMDOS/PROCESS.A86 | 1493 +++++++++++++++ IBMDOS/PSP.DEF | 108 ++ IBMDOS/REDIR.A86 | 1722 +++++++++++++++++ IBMDOS/REDIR.EQU | 67 + IBMDOS/REQHDR.EQU | 166 ++ IBMDOS/RH.EQU | 134 ++ IBMDOS/SUPPORT.A86 | 258 +++ IBMDOS/UTILS.FDO | 2528 +++++++++++++++++++++++++ IBMDOS/VECTORS.DEF | 213 +++ LICENSE.TXT | 282 +++ LTOOLS/BIN2ASC.EXE | Bin 0 -> 22067 bytes LTOOLS/COMPBDOS.EXE | Bin 0 -> 6379 bytes LTOOLS/COMPBIOS.EXE | Bin 0 -> 6610 bytes LTOOLS/EXE2BIN.EXE | Bin 0 -> 9700 bytes LTOOLS/FIXUPP.EXE | Bin 0 -> 10680 bytes LTOOLS/LINKCMD.EXE | Bin 0 -> 46592 bytes LTOOLS/RASM86.EXE | Bin 0 -> 49152 bytes LTOOLS/RASM_SH.EXE | Bin 0 -> 12845 bytes README.TXT | 113 ++ 232 files changed, 86161 insertions(+) create mode 100644 COMMAND/BATCH.C create mode 100644 COMMAND/BIN/BATCH.OBJ create mode 100644 COMMAND/BIN/CMDLIST.OBJ create mode 100644 COMMAND/BIN/COM.OBJ create mode 100644 COMMAND/BIN/COMCPY.OBJ create mode 100644 COMMAND/BIN/COMINT.OBJ create mode 100644 COMMAND/BIN/COMMAND.COM create mode 100644 COMMAND/BIN/COMMAND.EXE create mode 100644 COMMAND/BIN/CONFIG.OBJ create mode 100644 COMMAND/BIN/CRIT.OBJ create mode 100644 COMMAND/BIN/CSTART.OBJ create mode 100644 COMMAND/BIN/CSUP.OBJ create mode 100644 COMMAND/BIN/DOSIF.OBJ create mode 100644 COMMAND/BIN/GLOBAL.OBJ create mode 100644 COMMAND/BIN/HELPSTUB.OBJ create mode 100644 COMMAND/BIN/MESSAGE.OBJ create mode 100644 COMMAND/BIN/PRINTF.OBJ create mode 100644 COMMAND/BIN/RESIDENT.OBJ create mode 100644 COMMAND/BIN/SUPPORT.OBJ create mode 100644 COMMAND/BIN/TXHELP.BIN create mode 100644 COMMAND/BIN/TXHELP.EXE create mode 100644 COMMAND/BIN/TXHELP.OBJ create mode 100644 COMMAND/CHAR.DEF create mode 100644 COMMAND/CMDLIST.C create mode 100644 COMMAND/COM.C create mode 100644 COMMAND/COMCPY.C create mode 100644 COMMAND/COMINT.C create mode 100644 COMMAND/COMMAND.H create mode 100644 COMMAND/COMMAND.MAP create mode 100644 COMMAND/CONFIG.C create mode 100644 COMMAND/CRIT.ASM create mode 100644 COMMAND/CSTART.ASM create mode 100644 COMMAND/CSUP.ASM create mode 100644 COMMAND/DEFINES.H create mode 100644 COMMAND/DOS.H create mode 100644 COMMAND/DOSIF.ASM create mode 100644 COMMAND/DOSIF.H create mode 100644 COMMAND/DRIVER.EQU create mode 100644 COMMAND/F52DATA.DEF create mode 100644 COMMAND/GLOBAL.C create mode 100644 COMMAND/GLOBAL.H create mode 100644 COMMAND/HELP.H create mode 100644 COMMAND/HELPSTUB.ASM create mode 100644 COMMAND/IDLE.H create mode 100644 COMMAND/LOGIN.H create mode 100644 COMMAND/MAKE.BAT create mode 100644 COMMAND/MESSAGE.ASM create mode 100644 COMMAND/MESSAGE.DEF create mode 100644 COMMAND/MESSAGE.H create mode 100644 COMMAND/MSDOS.EQU create mode 100644 COMMAND/MSERROR.EQU create mode 100644 COMMAND/MSERROR.H create mode 100644 COMMAND/PORTAB.H create mode 100644 COMMAND/PRINTF.C create mode 100644 COMMAND/RESIDENT.ASM create mode 100644 COMMAND/RESIDENT.DEF create mode 100644 COMMAND/RESIDENT.H create mode 100644 COMMAND/RESP1 create mode 100644 COMMAND/RESP2 create mode 100644 COMMAND/RESP3 create mode 100644 COMMAND/SECURITY.H create mode 100644 COMMAND/STRUCT.H create mode 100644 COMMAND/SUPPORT.C create mode 100644 COMMAND/SUPPORT.H create mode 100644 COMMAND/TOUPPER.H create mode 100644 COMMAND/TXHELP.ASM create mode 100644 COMMAND/TXHELP.DEF create mode 100644 COMMAND/TXHELP.H create mode 100644 COMMAND/TXLOGIN.H create mode 100644 IBMBIO/BDOSLDR.A86 create mode 100644 IBMBIO/BDOSSTUB.A86 create mode 100644 IBMBIO/BIN/BDOSLDR.OBJ create mode 100644 IBMBIO/BIN/BDOSSTUB.OBJ create mode 100644 IBMBIO/BIN/BIOS.MAP create mode 100644 IBMBIO/BIN/BIOSGRPS.OBJ create mode 100644 IBMBIO/BIN/BIOSINIT.OBJ create mode 100644 IBMBIO/BIN/BIOSMSGS.OBJ create mode 100644 IBMBIO/BIN/BIOSSTUB.LIB create mode 100644 IBMBIO/BIN/CLOCK.OBJ create mode 100644 IBMBIO/BIN/CONFIG.OBJ create mode 100644 IBMBIO/BIN/CONFSTUB.OBJ create mode 100644 IBMBIO/BIN/CONSOLE.OBJ create mode 100644 IBMBIO/BIN/DISK.OBJ create mode 100644 IBMBIO/BIN/GENERCFG.OBJ create mode 100644 IBMBIO/BIN/IBMBIO.COM create mode 100644 IBMBIO/BIN/INIT.OBJ create mode 100644 IBMBIO/BIN/INITMSGS.OBJ create mode 100644 IBMBIO/BIN/NLSFUNC.OBJ create mode 100644 IBMBIO/BIN/SERPAR.OBJ create mode 100644 IBMBIO/BIN/STACKS.OBJ create mode 100644 IBMBIO/BIOS.LNK create mode 100644 IBMBIO/BIOSGRPS.ASM create mode 100644 IBMBIO/BIOSGRPS.EQU create mode 100644 IBMBIO/BIOSINIT.A86 create mode 100644 IBMBIO/BIOSMSGS.ASM create mode 100644 IBMBIO/BIOSMSGS.DEF create mode 100644 IBMBIO/BIOSMSGS.H create mode 100644 IBMBIO/BIOSSTUB.LIB create mode 100644 IBMBIO/BPB.EQU create mode 100644 IBMBIO/CHAR.DEF create mode 100644 IBMBIO/CLOCK.ASM create mode 100644 IBMBIO/CONFIG.A86 create mode 100644 IBMBIO/CONFIG.EQU create mode 100644 IBMBIO/CONFSTUB.A86 create mode 100644 IBMBIO/CONSOLE.ASM create mode 100644 IBMBIO/COUNTRY.DEF create mode 100644 IBMBIO/DISK.ASM create mode 100644 IBMBIO/DOSHNDL.DEF create mode 100644 IBMBIO/DRIVER.EQU create mode 100644 IBMBIO/DRMACROS.EQU create mode 100644 IBMBIO/F52DATA.DEF create mode 100644 IBMBIO/FDOS.EQU create mode 100644 IBMBIO/GENERCFG.A86 create mode 100644 IBMBIO/IBMROS.EQU create mode 100644 IBMBIO/INIT.ASM create mode 100644 IBMBIO/INITMSGS.ASM create mode 100644 IBMBIO/INITMSGS.DEF create mode 100644 IBMBIO/INITMSGS.H create mode 100644 IBMBIO/MAKE.BAT create mode 100644 IBMBIO/MODFUNC.DEF create mode 100644 IBMBIO/MSDOS.EQU create mode 100644 IBMBIO/MSERROR.EQU create mode 100644 IBMBIO/NLSFUNC.A86 create mode 100644 IBMBIO/PATCH.COD create mode 100644 IBMBIO/PSP.DEF create mode 100644 IBMBIO/REQHDR.EQU create mode 100644 IBMBIO/REQUEST.EQU create mode 100644 IBMBIO/SERPAR.ASM create mode 100644 IBMBIO/STACKS.ASM create mode 100644 IBMBIO/UDSC.EQU create mode 100644 IBMDOS/BDEVIO.A86 create mode 100644 IBMDOS/BDOS.EQU create mode 100644 IBMDOS/BIN/BDEVIO.OBJ create mode 100644 IBMDOS/BIN/BUFFERS.OBJ create mode 100644 IBMDOS/BIN/CDEVIO.OBJ create mode 100644 IBMDOS/BIN/CIO.LST create mode 100644 IBMDOS/BIN/CIO.OBJ create mode 100644 IBMDOS/BIN/CIO.SYM create mode 100644 IBMDOS/BIN/CMDLINE.LST create mode 100644 IBMDOS/BIN/CMDLINE.OBJ create mode 100644 IBMDOS/BIN/CMDLINE.SYM create mode 100644 IBMDOS/BIN/DIRS.OBJ create mode 100644 IBMDOS/BIN/DISK.OBJ create mode 100644 IBMDOS/BIN/DOSMEM.LST create mode 100644 IBMDOS/BIN/DOSMEM.OBJ create mode 100644 IBMDOS/BIN/DOSMEM.SYM create mode 100644 IBMDOS/BIN/ERROR.LST create mode 100644 IBMDOS/BIN/ERROR.OBJ create mode 100644 IBMDOS/BIN/ERROR.SYM create mode 100644 IBMDOS/BIN/FCBS.LST create mode 100644 IBMDOS/BIN/FCBS.OBJ create mode 100644 IBMDOS/BIN/FCBS.SYM create mode 100644 IBMDOS/BIN/FDOS.OBJ create mode 100644 IBMDOS/BIN/FIOCTL.OBJ create mode 100644 IBMDOS/BIN/HEADER.OBJ create mode 100644 IBMDOS/BIN/HISTORY.LST create mode 100644 IBMDOS/BIN/HISTORY.OBJ create mode 100644 IBMDOS/BIN/HISTORY.SYM create mode 100644 IBMDOS/BIN/IBMDOS.COM create mode 100644 IBMDOS/BIN/IBMDOS.INP create mode 100644 IBMDOS/BIN/IBMDOS.MAP create mode 100644 IBMDOS/BIN/IBMDOS.SYM create mode 100644 IBMDOS/BIN/IBMDOS.TMP create mode 100644 IBMDOS/BIN/INT2F.OBJ create mode 100644 IBMDOS/BIN/IOCTL.OBJ create mode 100644 IBMDOS/BIN/MISC.OBJ create mode 100644 IBMDOS/BIN/NETWORK.LST create mode 100644 IBMDOS/BIN/NETWORK.OBJ create mode 100644 IBMDOS/BIN/NETWORK.SYM create mode 100644 IBMDOS/BIN/PCMIF.OBJ create mode 100644 IBMDOS/BIN/PROCESS.OBJ create mode 100644 IBMDOS/BIN/REDIR.OBJ create mode 100644 IBMDOS/BIN/SUPPORT.LST create mode 100644 IBMDOS/BIN/SUPPORT.OBJ create mode 100644 IBMDOS/BIN/SUPPORT.SYM create mode 100644 IBMDOS/BUFFERS.A86 create mode 100644 IBMDOS/CDEVIO.A86 create mode 100644 IBMDOS/CHAR.DEF create mode 100644 IBMDOS/CIO.A86 create mode 100644 IBMDOS/CMDLINE.A86 create mode 100644 IBMDOS/CMDLINE.EQU create mode 100644 IBMDOS/COUNTRY.A86 create mode 100644 IBMDOS/COUNTRY.DEF create mode 100644 IBMDOS/DIRS.A86 create mode 100644 IBMDOS/DISK.A86 create mode 100644 IBMDOS/DOSHNDL.DEF create mode 100644 IBMDOS/DOSMEM.A86 create mode 100644 IBMDOS/DRIVER.EQU create mode 100644 IBMDOS/ERROR.A86 create mode 100644 IBMDOS/EXE.DEF create mode 100644 IBMDOS/F52DATA.DEF create mode 100644 IBMDOS/FCBS.A86 create mode 100644 IBMDOS/FDOS.A86 create mode 100644 IBMDOS/FDOS.DEF create mode 100644 IBMDOS/FDOS.EQU create mode 100644 IBMDOS/FIOCTL.A86 create mode 100644 IBMDOS/FUNCS.FDO create mode 100644 IBMDOS/HEADER.A86 create mode 100644 IBMDOS/HISTORY.A86 create mode 100644 IBMDOS/IBMDOS.INP create mode 100644 IBMDOS/IBMDOS.MAP create mode 100644 IBMDOS/IBMDOS.SYM create mode 100644 IBMDOS/INT2F.A86 create mode 100644 IBMDOS/IOCTL.A86 create mode 100644 IBMDOS/MAKE.BAT create mode 100644 IBMDOS/MISC.A86 create mode 100644 IBMDOS/MODFUNC.DEF create mode 100644 IBMDOS/MSDOS.EQU create mode 100644 IBMDOS/MSERROR.EQU create mode 100644 IBMDOS/NETWORK.A86 create mode 100644 IBMDOS/PATCH.COD create mode 100644 IBMDOS/PCMIF.A86 create mode 100644 IBMDOS/PCMODE.EQU create mode 100644 IBMDOS/PROCESS.A86 create mode 100644 IBMDOS/PSP.DEF create mode 100644 IBMDOS/REDIR.A86 create mode 100644 IBMDOS/REDIR.EQU create mode 100644 IBMDOS/REQHDR.EQU create mode 100644 IBMDOS/RH.EQU create mode 100644 IBMDOS/SUPPORT.A86 create mode 100644 IBMDOS/UTILS.FDO create mode 100644 IBMDOS/VECTORS.DEF create mode 100644 LICENSE.TXT create mode 100644 LTOOLS/BIN2ASC.EXE create mode 100644 LTOOLS/COMPBDOS.EXE create mode 100644 LTOOLS/COMPBIOS.EXE create mode 100644 LTOOLS/EXE2BIN.EXE create mode 100644 LTOOLS/FIXUPP.EXE create mode 100644 LTOOLS/LINKCMD.EXE create mode 100644 LTOOLS/RASM86.EXE create mode 100644 LTOOLS/RASM_SH.EXE create mode 100644 README.TXT diff --git a/COMMAND/BATCH.C b/COMMAND/BATCH.C new file mode 100644 index 0000000..56f9e73 --- /dev/null +++ b/COMMAND/BATCH.C @@ -0,0 +1,2653 @@ +/* +; File : $Workfile: BATCH.C$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; ENDLOG +*/ + +/* + * 27 Oct 87 Improve GOTO command to ignore trailing white space, only + * match on the first 8 characters and only allow valid + * filename characters. + * 28 Oct 87 Correct duplicate prompt display when a batch file label + * is read and the echo flag is ON. + * 9 Nov 87 Change Batch file termination so that Output Redirection is + * correctly handled. + * 13 Jan 88 If prompt display is aborted because of a critical error + * the following prompt will be forced to "$n$g". + * 25 Jan 88 Support redirection on the FOR command correctly + * 24 Feb 88 Generate batch file parameter %0 correctly as WS200 install + * requires that the drive specifier be present. Garry Silvey + * 5 May 88 Batch paramater %0 is now a copied from the invoking command + * line. + * 18 May 88 Support the ESC_CHAR in the command line. + * 20 May 88 Disable MULTI_CHAR support in DOSPLUS when the user enters the + * first command. + * 26 May 88 Added STACK switch and support $q in prompt. + * 27 May 88 Added string undefs. + * 6 Jun 88 Call resident portion to do readline (SideKick+ problem) + * 23 Jun 88 Support CR only delimited batch files and if errorlevel == + * syntax used in installation files. + * 6 Jul 88 Support the FOR ... CALL syntax correctly. (IMS) + * 17 Aug 88 Jump to labels followed by comments (Ashton Tate By-Line) + * 21 Sep 88 Use KEYIN_FLG to allow the default ECHO state to be ON. + * 16 Nov 88 Disable BACK_CHAR in Concurrent DOS. + * 21 Dec 88 Allow leading whitespace before labels + * 5 Jan 89 Support Quoted strings in Batch files. + * 18 Apr 89 Support Quoted strings in IF command + * 19 Apr 89 Quotes in IF command: "x == "x" parses, "x=x" == "x.. doesn't + * 24 Apr 89 Increase MAX_LINE to 128 for pctools ver 5 + * 19 May 89 Take out support for quoted strings in IF command + * 05 Jun 89 Do not echo command or display the prompt during FOR command. + * Restore support for batch files with long lines. + * 02 Nov 89 batch_line bodge which substitutes 0xFF for 0x00 changed - we + * now substitute '\r\n', then throw away rest of the line. + * 01 Dec 89 batch_line - trailing % at end of line is discarded + * 15 Dec 89 "if errorlevel -1" allowed + * 30 Jan 90 Added int2e_start and int2e_finish to save and restore + * important batch file variables to allow novell menu program + * to use int 2e to invoke batch files. + * 30 Jan 90 Forced batch data structures to appear on segment boundaries; + * Added dummy memory descriptor before batch structure; + * Put segment address of batch structure in batch_seg_ptr; + * All so novell can find and patch the drive letter of + * autoexec.bat during a remote boot. + * 6-Mar-90 Watcom C v 7.0 + * 7-Mar-90 allow ESC_CHAR through unless followed by MULTI/BACK_CHAR + * 14-Mar-90 Reduce batch_buf to 32 bytes like wot dos is + * 20-Mar-90 Batch structures allocated by mem_alloc (ie. MS_M_ALLOC) + * rather than on heap. Batch file nesting no longer heap limited. + * 27-Mar-90 Allow "=", "==", "===" etc in "if errorlevel==n" + * 10-Apr-90 Make errorlevel 999 same as errorlevel 231 (mod 256) + * 8-May-90 Don't echo getcmd unless batch file (eg. "dir|more" shouldn't + * echo "C:>more") + * 23-May-90 batch_read no longer repeatedly deblanks line (which leads + * to the buffer happily wandering up memory). + * 30-May-90 "if ab de==ef" form doesn't generate syntax error + * 13-Jun-90 batch_line rejects unmatched "|" as syntax error + * 20-Sep-90 is_filechar() and is_pathchar() now take pointer instead of byte + * Changed batch_char() to return pointer instead of byte, + * renamed to batch_ptr(). + * Amended make_label(), batch_start() and cmd_for() to check for + * DBCS lead bytes. + * 24-Sep-90 Add $m and $u option to PROMPT to display status of mail + and user name respectively + * 27-Sep-90 Add IF USERID COMMAND + IF LOGINNAME COMMAND + IF GROUPNAME COMMAND + IF ASK ["string"] COMMAND + .. AND .. OR .. to IF processing + INPUT ["string"] + INPUTC ["string"] + * 10-Oct-90 inherit batch files from TMP when TSR auto-loads CDOS.COM + (a bodge for Stellar) + * 25-Oct-90 inherit echoflg from TMP when TSR auto-loads CDOS.COM + * 31-Oct-90 change IF ASK command to IF KEY command + +DRDOS BUXTON +------------ + * 25-Apr-91 '!' is now ignored during COMMAND /C processing. + * 28-May-91 leading white space is now ignored before labels. + * 09-Jun-91 Added GOSUB, RETURN and SWITCH commands. + * 24-Jul-91 if batch_seg_ptr is poked to zero all batch processing is + terminated. + * 26-Jul-91 batch files are now read into a far buffer. This avoids + reading directly to seg FFFF if we happen to be there and so + solves some NOVELL problems. + + * 18-Jun-92 Support ? in batch files as in config.sys. + * 23-Jun-92 $u in prompt causes LOGINNAME in environment to be displayed. + * 07-Jul-92 IF EXIST now finds hidden files. +*/ + +#include "defines.h" + +#include +#if defined(MWC) && defined(strlen) +#undef strcmp /* These are defined as macros in string.h */ +#undef strcpy /* which are expanded in line under */ +#undef strlen /* Metaware C. These undefs avoid this. */ +#endif + +#include + +#if !defined(DOSPLUS) +#include +#endif + +#include "command.h" +#include "toupper.h" +#include "support.h" +#include "dosif.h" +#include "global.h" +#include "dos.h" + +#include + +/*RG-01*/ +#if defined(CDOSTMP) || defined(CDOS) +#include +#define PATH_LEN 65 /* max path length (null terminated) */ +EXTERN PD FAR * CDECL pd; /* Far pointer to Current PD */ +EXTERN VOID CDECL cmd_set(BYTE *); /* COMINT.C */ +#if !defined (NOSECURITY) +#include "security.h" +#include "login.h" +#endif +#endif +/*RG-01-end*/ + +EXTERN VOID CDECL cmd_pause(); + +EXTERN BOOLEAN parse(BYTE *); + +EXTERN UWORD boot_key_scan_code; /* in COM.C */ + +/*RG-03*/ +BOOLEAN if_context=FALSE; +BOOLEAN ifcond=FALSE; +/*RG-03-end*/ + +EXTERN jmp_buf break_env; + +#define MAX_LINE 128 /* Maximum No of Chars in input line */ + +#if defined(CPM) +EXTERN UWORD user; /* USER Number variable for CPM.EXE */ +#endif +EXTERN BYTE msg_prmeq[]; /* Static Environ String "PROMPT=" */ + +#if 0 +#define FCONTROL struct fcc +MLOCAL FCONTROL { + BOOLEAN sflg; /* FOR File Search Flag */ + DTA search; /* FOR Search structure */ + BYTE *files; /* FOR File list */ + BYTE *cmd; /* FOR Command Line */ + BYTE forvar; /* FOR variable char */ +}; +#endif + +MLOCAL FCONTROL *forptr; + +#if 0 +#define BCONTROL struct bcc +GLOBAL BCONTROL { + BCONTROL FAR *bcontrol; /* Previous Batch Control Structure */ + BOOLEAN eof; /* End of File Flag */ + LONG offset; /* Offset in BATCH file */ + LONG ret_offset[4]; /* return offset from gosub */ + BYTE *batcmd; /* Batch File Input parameters */ + UWORD batshift; /* Shift Offset */ + BYTE batfile[MAX_PATHLEN]; /* Batch File Name */ + UWORD stream; /* Stream for this Batch File */ + FCONTROL *fcontrol; /* Pointer to previous FOR command */ + BYTE *heap_start; /* Heap pointer before extra bytes */ + WORD heap_size; /* are added to shift to segment */ + BYTE save_area[1]; /* boundary. - EJH */ + } FAR *batch, FAR *batch_save; /* Master Batch Control Stucture */ +#endif + +/* Handle 255 is closed */ +#define CLOSED 0xff + +/* Keyboard Variables */ +GLOBAL BYTE kbdbuf[MAX_LINE+2]= {0};/* Keyboard Input Buffer */ +GLOBAL BYTE *kbdptr = kbdbuf+2; /* Keyboard Buffer Pointer */ +MLOCAL BOOLEAN keyin_flg = FALSE; /* This flag is set to TRUE when the */ + /* initial command line buffer setup */ + /* by INIT() has been exhausted. */ +MLOCAL WORD batchflg_save; /* Used during INT 2E handling. */ +MLOCAL WORD echoflg_save; /* ditto above */ +GLOBAL WORD echoflg_save2; /* saves echo state when batch file */ + /* execed. */ +/* + * Batch file buffering control structures. + */ +MLOCAL LONG batch_off; /* Offset of buffered data in File */ +MLOCAL WORD batch_cnt = 0; /* Number of bytes in buffer */ +MLOCAL BYTE batch_buf[32]; +MLOCAL BYTE batch_eof[] = "\x1a"; /* End of file string */ + +MLOCAL BYTE batch_sep[] = "\t ;,="; /* Batch Command line option delimiters */ + +EXTERN VOID CDECL cmd_ver(BYTE *); /* COMINT.C Display Version */ +EXTERN VOID docmd(BYTE *, BOOLEAN); /* COM.C */ +EXTERN VOID CDECL int_break(VOID); /* COM.C */ + +GLOBAL BOOLEAN getcmd(BYTE *); +GLOBAL VOID for_end(); +GLOBAL VOID batch_start(BYTE *, BYTE *, BYTE *); +GLOBAL VOID batch_end(VOID); +GLOBAL VOID batch_close(VOID); +MLOCAL VOID for_in(BYTE *); +MLOCAL WORD batch_open(VOID); +MLOCAL VOID batch_read(BYTE *, BOOLEAN); +MLOCAL VOID batch_line(BYTE *, BOOLEAN); +MLOCAL BYTE *batch_ptr(VOID); +MLOCAL VOID prompt(VOID); +MLOCAL BOOLEAN novell_extension(BYTE *, BYTE *); + +#if !defined(CDOSTMP) +EXTERN UWORD FAR *batch_seg_ptr; /* For novell remote boot. see CSTART.ASM */ +#endif + +#if defined(CDOS) || defined(CDOSTMP) +#define TmpPspEchoFlgPtr 0x58 /* Magic location to keep echo flag */ +#define TmpPspDataSeg 0x5a /* Magic location to keep Data Seg */ +#define TmpPspBatchSeg 0x5c /* Magic location to keep Batch Ptr */ +#define TmpPspMpad 0x5e /* Magic location to keep unlinked MPAD */ +#endif +#if defined(CDOS) +typedef struct _mpad +{ + UWORD link; /* address of next MPAD */ + UWORD start; /* seg of allocation unit */ + UWORD length; /* length in paras */ + UWORD res0x06; /* reserved */ + UWORD xios; /* Process id */ +} MPAD; +GLOBAL VOID inherit_TMP_state(VOID); +#endif + +/*.pa*/ +GLOBAL BOOLEAN getcmd(line) /* read command line */ +BYTE *line; +{ + BYTE *s; + BOOLEAN quote = FALSE; + BOOLEAN cancel_prompt = FALSE; +#if defined(DOSPLUS) + WORD i; + BYTE cmd_name[16]; +#endif + + back_flag = FALSE; /* Disable BackGround Processing*/ + + *line = '\0'; + + FOREVER { + if(for_flag) { /* If Processing a FOR command */ + for_in(line); /* then call then use the FOR_IN*/ + return NO; /* routine to fill the keyboard */ + } /* buffer and then return */ + + if(!batchflg) /* If no batch processing then */ + break; /* skip further tests */ +batch_restart: + +#if defined(DOSPLUS) + if (!*batch_seg_ptr) { /* if batch_seg_ptr has been set to */ + batch_endall(); /* zero terminate all batch files */ + return NO; + } +#endif + + if(batchflg && batch->eof) { /* Close the batch file if at */ + batch_end(); /* the end of the file. */ + if(batchflg == 0) /* BREAK if batch processing */ + return NO; /* is complete. */ + continue; + } + + if(!batch_open()) /* Open the file and read a line*/ + return YES; /* from the file */ + + batch_read(line, NO); /* Read Line */ + + if(batch->eof) /* If the end of the batch file */ + batch_close(); /* has been detected then close */ + /* the file. */ + + if (*line == '?' || boot_key_scan_code == 0x4200) { + optional_line(line); + } + + if(*line == '@') { /* If first character in the */ + strcpy(line, line+1); /* command line is '@' donot */ + return NO; /* echo the command and move the*/ + } /* string down 1 character. */ + + if (!cancel_prompt) { + if(crlfflg && echoflg) + crlf(); + prompt(); + } + return echoflg; + } + + if(!*kbdptr) { /* Set the Keyboard Input flag */ + keyin_flg = TRUE; /* after a initial command line */ + /* buffer has been exhausted */ +#if 1 + if (c_option) { /* insert an EXIT command if we */ + kbdptr = &kbdbuf[2]; /* are processing a /C command */ + strcpy(&kbdbuf[2],"exit"); + } +#endif + } + + if (!*kbdptr) { /* Check for existing line */ + + +/* NEIL */ + if(crlfflg && echoflg) + crlf(); +/* NEIL end */ + prompt(); /* issue command line prompt */ + allow_pexec = FALSE; + + /* $x in prompt string may cause batchflg to be set. */ + /* If so we must jump to batch processing code. */ + if (batchflg) { + cancel_prompt = TRUE; + goto batch_restart; + } + + kbdptr = ""; /* Force KBDPTR to point to '\0'*/ + /* in case we get ABORTED and */ + /* drop through here again. */ + kbdbuf[0] = MAX_LINE; /* set max. input length */ + kbdbuf[kbdbuf[1]+2] = '\r'; /* Terminate current line. */ +#if defined(CDOSTMP) + system(C_READSTR, kbdbuf); /* read a line */ +#else + + readline(kbdbuf); +#endif + + crlf(); + + kbdbuf[kbdbuf[1] + 2]='\0'; /* terminate input */ + kbdptr = kbdbuf + 2; + } + + s = kbdptr; + + while(*s) { + if(*s == '"') /* Check for a " character and */ + quote = !quote; /* update the flag correctly */ + +#if !defined(DOSPLUS) + if(*s == ESC_CHAR && /* If the Escape character has */ + !quote && /* been specified then do not */ + ((*(s+1) == MULTI_CHAR) || (*(s+1) == BACK_CHAR))) { + *line++ = *++s; /* process the following char. */ + s++; + continue; + } +#endif + +#if defined(DOSPLUS) /* Disable MULTI_CHAR support */ + if(!(keyin_flg||c_option||k_option)) + /* after the init command line */ +#endif /* has been exhausted. */ + if(*s == MULTI_CHAR && /* If a Multiple command char */ + !quote) { /* and the QUOTE flag is FALSE */ + s++; /* then break the command here */ + break; /* and save the rest of the line*/ + } /* for next time. */ + +#if FALSE /* defined(CDOSTMP) */ + if(*s == BACK_CHAR && /* If a Back Ground processing */ + !quote) { /* and the QUOTE flag is FALSE */ + s++; /* then treat as for MULTI_CHAR */ + back_flag = TRUE; /* except that the current */ + break; /* command is executed in the */ + } /* background. */ +#endif + if(*s == PIPE_CHAR && /* If a Pipe enable character */ + !quote) { /* and the QUOTE flag is FALSE */ + s++; /* then break the command here */ + pipe_out = YES; /* and save the rest of the line*/ + break; /* for next time. */ + } + + copy_char(&line, &s); /* Just save the character */ + } + + *line = '\0'; /* Terminate the Buffer */ + kbdptr = deblank(s); /* Copy the possibly null length*/ + return NO; /* string to KBDBUF for next */ + /* next invocation and save CCP */ +} + +MLOCAL VOID for_in(line) /* A FOR command is currently */ +BYTE *line; /* executing so build the line */ +{ /* from the internal FOR data */ + BYTE *s,*t; /* initialized by CMD_FOR */ + BYTE *bp1, *fp; + WORD i; + + FOREVER { + fp = forptr->files; /* Get the next string and stop */ + if(strlen(fp) == 0) { /* if its the zero length string */ + *line = '\0'; /* which marks the end of the FOR */ + crlfflg = YES; /* search list. */ + for_end(); + return; + } + + if(!iswild(fp)) { /* If not an ambiguous file */ + forptr->sflg = NO; /* then update the FOR */ + forptr->files += strlen(fp)+1; /* pointer to the next file */ + break; /* in the search list. */ + } + + if(forptr->sflg) /* Search for the next file */ + i = ms_x_next(&forptr->search); /* file on the disk if */ + else /* FOR_SFLG otherwise get first */ + i = ms_x_first(fp, ATTR_RO, &forptr->search); + + if(i < 0) { /* If the search failed */ + forptr->sflg = NO; /* then update the FOR */ + forptr->files += strlen(fp)+1; /* pointer to the next file */ + continue; /* in the search list. */ + } /* and get the next entry */ + + fp = (BYTE *) heap(); + strip_path(forptr->files, fp); /* Extract the Path */ + strcat(fp, forptr->search.fname); /* and then add the matching */ + forptr->sflg = YES; /* filename and update the */ + strupr(fp); /* variables. */ + break; /* Force name to uppercase */ + } + + s = forptr->cmd; + t = line; + while (*s && (t - line) < MAX_LINE) { /* Copy the command */ + if(*s == '%' && *(s+1) == forptr->forvar) { /* line looking for */ + s += 2; /* the imbedded %c and insert*/ + bp1 = fp; /* the current substition */ + while(*bp1 && (t - line) < MAX_LINE) /* string pointed at by FP */ + copy_char(&t, &bp1); + continue; + } + + copy_char(&t, &s); + } + + *t = '\0'; /* and terminate the string */ +} + +/*.pa*/ +/* + * BATCH FILE CONTROL ROUTINES + * =========================== + * + * The following routines provide the interface from COMMAND.COM to + * a batch file. BATCH_START sets up all the local variables to enable + * batch processing while BATCH_END terminates batch processing. BATCH_READ + * reads a line of data from the batch file and expands it to contain the + * command line variables and variables from the environment. + */ +GLOBAL VOID batch_start(argv0, path, tail) +BYTE *argv0; /* Invoking Command */ +BYTE *path; /* Complete filename */ +BYTE *tail; /* Command Line Options */ +{ +BYTE *s2; +BYTE dirbuf[MAX_PATHLEN]; +WORD i; + + if(batchflg) /* If a batch file is currently */ + batch_close(); /* close it. So minimum number */ + /* of handles are used. */ + + s2 = path; /* Save the original Path */ + if((path = d_check(path)) == NULL) /* Check that the file */ + return; /* exists. */ + + batch_new(); /* new incarnation of batch */ + + forptr = (FCONTROL *) NULL; /* Disable current FOR control */ + for_flag = NO; /* and Global FOR flag */ + + /* + * Generate the full path specification for the batch file + * and store in the batch control information. If the user + * has specified the full path use it otherwise determine the + * full path using ms_x_curdir. + */ + if (ddrive != -1 && *path != *pathchar) { + ms_x_curdir(ddrive+1, dirbuf); + sprintf(heap(), "%c:%s%s%s%s", ddrive + 'A', + pathchar, + dirbuf, + (*dirbuf ? pathchar : ""), + path); + } + else if (ddrive != -1) + sprintf(heap(), "%c:%s", ddrive + 'A', path); + else + ms_x_expand(heap(), path); + + for (i=0; ibatfile[i] = heap()[i]; + batch->batfile[MAX_PATHLEN-1] = 0; + + /* + * Copy the invoking command and the individual elements + * of the command line into a buffer ready for processing + */ + batch->batcmd = (BYTE *)heap(); /* Initialize Parameter Buffer */ + strcpy(heap(), argv0); /* Copy the invoking command */ + heap_get(strlen(heap())+1); /* and protect the buffer */ + + while(*tail) { /* While there are command line */ + s2 = (BYTE *)heap(); /* parameters copy them */ + while(*tail && strchr(batch_sep, *tail)) + tail = skip_char(tail); + + while(*tail && !strchr(batch_sep, *tail)) + copy_char(&s2, &tail); + + *s2++ = '\0'; + heap_get(strlen(heap()) + 1); + } + + *(WORD *)heap_get(2) = 0; /* Double NULL is a terminator */ + /* for command line params */ + + if(in_flag & REDIR_ACTIVE) /* If Input redirection has been */ + in_flag |= REDIR_BATCH; /* enabled for this command force*/ + /* it on for the complete command*/ + + if(out_flag & REDIR_ACTIVE) /* If Output redirection has been*/ + out_flag |= REDIR_BATCH; /* enabled for this command force*/ + /* it on for the complete command*/ + + + batchflg++; /* increment batch flag */ + + crlfflg = YES; /* print CR/LF after this */ +} + +GLOBAL VOID batch_endall() /* This terminates BATCH */ +{ /* processing by closing ALL */ + while(batchflg) { /* active batch files */ + batch_end(); + } +} + +GLOBAL VOID batch_end() /* This function is called for */ +{ /* both NORMAL and ABNORMAL */ + if(batchflg == 0) /* termination of batch file */ + return; /* processing */ + + boot_key_scan_code = 0; + + batch_close(); /* Close the Batch file */ + for_end(); /* Terminate Any FOR command */ + batch_old(); /* Restore the previous batch */ + /* control structures to heap */ + if(--batchflg == 0) { + *batch_seg_ptr = 0; + echoflg = echoflg_save2; /* Restore the original ECHO */ + crlfflg = YES; /* flag and set CR/LF flag when */ + } /* returning to the keyboard. */ +} + + +MLOCAL BOOLEAN batch_open() +{ +WORD h, i; +BYTE *name; + + if(batch->eof) { /* If the End of the batch file */ + batch_end(); /* was discovered last time then*/ + return FALSE; /* End Batch file input and exit*/ + } + + if(batch->stream != CLOSED) + return batch->stream; + + name = heap(); + + for (i=0; ibatfile[i]; + while ((h = ms_x_open(name, OPEN_READ)) < 0) { + err_flag = TRUE; + eprintf(MSG_BATMISS, name); /* prompt for batch file */ + heap_get(strlen(name)+1); + cmd_pause(""); + heap_set(name); + } + err_flag = FALSE; + batch->stream = h; + return TRUE; +} + +GLOBAL VOID batch_close() +{ + if(batchflg != 0 && + batch->stream != CLOSED) { /* Check if the batch file */ + batch_cnt = 0; /* currently open if YES */ + ms_x_close(batch->stream); /* then flush the internal */ + batch->stream = CLOSED; /* buffer and close file. */ + } +} + +#if defined(DOSPLUS) + +GLOBAL VOID inherit_batch_file(bc) +BCONTROL FAR *bc; +{ + WORD i; + BYTE FAR *p_heap; + BYTE *l_heap; + + /* inherit any parent batch file first */ + if (bc->bcontrol) inherit_batch_file(bc->bcontrol); + + /* create a new batch structure */ + batch_new(); + + batch->offset = bc->offset; /* continue at same offset */ + for (i=0;i<4;i++) batch->ret_offset[i] = bc->ret_offset[i]; + batch->batshift = bc->batshift; + + for (i=0; ibatfile[i] = bc->batfile[i]; + batch->batfile[MAX_PATHLEN-1] = 0; + + /* get command line */ + + p_heap = MK_FP(*parent_psp+16,bc->batcmd); + l_heap = heap(); + + while (1) { + while(*p_heap) *l_heap++ = *p_heap++; + *l_heap++ = *p_heap++; + if (*p_heap == 0) { + *l_heap = 0; + break; + } + } + heap_get(l_heap-heap()); + + batchflg++; +} + + +GLOBAL VOID inherit_parent_state() +{ + UWORD FAR *p; + BCONTROL FAR *bc; + UWORD root_psp; + + root_psp = *parent_psp; + while(1) { + p = MK_FP(root_psp-1,8); + if (p[0] == 0x4F43 && p[1] == 0x4D4D && + p[2] == 0x4E41 && p[3] == 0x0044) break; + + p = MK_FP(root_psp,0x16); + root_psp = *p; + } + + + p = MK_FP(root_psp+16,batch_seg_ptr); +#if 0 + printf("batch_seg_ptr = %04X:%04X\n",p); + printf("parent batch_seg_ptr = %04X\n",*p); +#endif + if (*p == 0 || *p == 0xFFFF) return; + + bc = MK_FP(*p,0); + + inherit_batch_file(bc); + + *p = 0; + + p = MK_FP(root_psp+16,&echoflg); + echoflg = *p; +} +#endif + +GLOBAL VOID batch_new() +/* save current batch file heap contexts to high memory */ +{ +BYTE *hp_start; +WORD hp_size; +UWORD i; +BCONTROL FAR *bc; +#if defined(CDOSTMP) +UWORD FAR *ptr; +#endif + + if (batchflg != 0) + hp_start = batch->heap_start; + else + hp_start = heap(); + + hp_size = heap() - hp_start; + + i = (sizeof(BCONTROL) + hp_size + 15)/16; + mem_alloc(&bc, &i, i, i); /* allocate new batch structure */ + + if (i == 0) { /* if we can't allocate one */ + longjmp(break_env, IA_HEAP);/* then pretend heap has run out*/ + } /* to force termination. */ + + bc->bcontrol = batch; /* Link to Previous Structure */ + batch = bc; /* make this current batch struc*/ + batch->eof = NO; /* Have not found the EOF yet */ + batch->offset = 0L; /* start at beginning of File */ + for (i=0;i<4;i++) batch->ret_offset[i] = 0L; + batch->batshift = 0; /* No Shift Factor */ + batch->stream = CLOSED; /* Batch file is not open */ + batch->fcontrol = forptr; /* Save current FOR control */ + batch->heap_start = hp_start; /* Save original heap */ + batch->heap_size = hp_size; + + for (i=0; i < hp_size; i++) { + batch->save_area[i] = hp_start[i]; + } + + heap_set(hp_start); /* free up heap used by old batch */ + +#if defined(CDOSTMP) + ptr = MK_FP(pd->P_PSP, TmpPspEchoFlgPtr); + *ptr = (UWORD)&echoflg; + ptr = (UWORD FAR *) &ptr; /* coerce a FAR * to local data */ + i = FP_SEG(ptr); /* so we can get local data segment */ + ptr = MK_FP(pd->P_PSP, TmpPspDataSeg); + *ptr = i; /* save local data segment */ + ptr = MK_FP(pd->P_PSP, TmpPspBatchSeg); + *ptr = (UWORD)(((ULONG)batch) >> 16); +#else + /* Get segment address of batch and put it where novell */ + /* can find it. */ + + *batch_seg_ptr = (UWORD)(((ULONG)batch) >> 16); +#endif +} + + +MLOCAL VOID batch_old() +/* restore current batch file heap contents from high memory */ +{ +BCONTROL FAR *bc; +UWORD i; +#if defined(CDOSTMP) +UWORD FAR *ptr; +#endif + + heap_set(batch->heap_start+batch->heap_size); + for (i=0; iheap_size; i++) { + batch->heap_start[i] = batch->save_area[i]; + } + bc = batch; + forptr = batch->fcontrol; /* Restore the previous for */ + for_flag = (BOOLEAN) forptr; /* control structures */ + batch = batch->bcontrol; /* restore ptr to previous batch */ + mem_free(&bc); /* free up batch memory */ +#if defined(CDOSTMP) + ptr = MK_FP(pd->P_PSP, TmpPspBatchSeg); + *ptr = (UWORD)(((ULONG)batch) >> 16); +#endif +} + +/* + * Read lines repeatedly from the batch file until a line in + * the correct format is read from the batch file or the EOF + * has been reached. + */ +MLOCAL VOID batch_read(line, goto_flg) +BYTE *line; /* Command Line Buffer */ +BOOLEAN goto_flg; /* Goto Command Flag */ +{ +BYTE *l; /* we need to deblank line */ + do { + batch_line(line, goto_flg); /* Read the next line from */ + l = deblank(line); /* the batch file and return*/ + if(*l != ';') { + if(goto_flg && *l == ':') /* a line in the correct */ + return; /* format. */ + + if(!goto_flg && *l != ':') + return; + } + } while(!batch->eof); +} + +/* + * Read one line from the batch file and place the expanded data into + * the buffer LINE. + */ +MLOCAL VOID batch_line(line, goto_flg) +BYTE *line; /* Command Line Buffer */ +BOOLEAN goto_flg; /* Goto Command Flag */ +{ +REG WORD i; +REG BYTE *s; +WORD n, env_start; +BYTE c, *bp; +BYTE env_str[128]; +BOOLEAN quote = FALSE; +LONG old_offset; +int j; + + env_start = NULL; /* Copy the environment into a */ + +#if 0 +/* 'eject any line starting with 'rem' */ + old_offset = batch->offset; + i=0; + do{ + switch(c=*batch_ptr()){ + case 0x1a: + batch->eof = YES; /* We have come to the end */ + c = '\r'; /* of the batch file so set */ + break; /* flag and mark end of line*/ + default: + if (i < MAX_LINE) + line[i++] = c; + if (dbcs_lead(c)) { + if ((c = *batch_ptr()) >= ' ' && i < MAX_LINE) + line[i++] = c; + } + }/*switch*/ + }while(c!='\r'); + + if (*batch_ptr() != '\n') batch->offset--; + line[i]=0; + j=0; + while(line[j]){ + if (line[j] != ' ') + break; + j++; + } + if (( strlwr(line[j]) == 'r') && + ( strlwr(line[j+1]) == 'e') && + ( strlwr(line[j+2]) == 'm') && + ( strlwr(line[j+3]) == ' ')){ + if (echoflg) + printf("%s\n",line); + line[0]='\0'; + return; + } + + batch->offset = old_offset; + batch->eof = NO; + +#endif +/*rbf-end*/ + +/* process line */ + i = 0; + do { + switch(c = *batch_ptr()) { + case '\0': /* In OS/2 install.bat file */ +#if 0 + if (i < MAX_LINE) /* "ECHO \0" displays blank */ + line[i++] = '\r'; /* line - so we insert a CR */ + while (c != '\r') { /* then swallow rest of line */ + c = *batch_ptr(); /* read next character - if */ + if (c == 0x1a) /* it's an EOF mark then use */ + goto end_of_file; /* end-of-file code else end */ + } /* up falling into '\r' code */ +#else + c = *batch_ptr(); + if ((c == '\r') && (i < MAX_LINE)) + line[i++] = '\r'; +#endif + + case '\r': /* carriage return */ + if(*batch_ptr() != '\n') /* skip line feed */ + batch->offset--; /* if present */ + break; + + case '"': /* Support Quoted strings */ + quote = !quote; /* in batch files. */ + goto save_it; + + case PIPE_CHAR: /* Handle Piped Output */ + if(goto_flg || quote) /* Ignore this character if */ + goto save_it; /* we are searching for a */ + /* Label or Quote. */ + line[i] = '\0'; + c = *deblank(line); /* normal case we just */ + if ((c !='\0') && (c != ':') && following_command()) { + c = '\r'; /* simulate a CR and set */ + pipe_out = YES; /* Pipe Output flag. */ + } else if (c == ':') { /* if it's a label */ + for(;(c != '\r') && (c != 0x1A); c = *batch_ptr()) + if (c == 0x1A) /* eat rest of the line */ + batch->eof = YES; + if(*batch_ptr() != '\n')/* skip line feed */ + batch->offset--; /* if present */ + c = '\r'; + } else { /* if it's a syntax error */ + swallow_line(line); /* discard the rest of line */ + i = 0; /* start again with new line */ + } + break; + + case '%': /* The following code checks to see if the */ + /* string starting at line[env_start-1] is */ + /* define in the environment if it is then */ + /* its definition replaces it in the input */ + /* line. Otherwise no change is made. */ + if(env_start) { + env_start--; + line[i] = '\0'; /* Terminate Input */ + strcpy(env_str, line+env_start);/* Copy the String */ + strupr(env_str); /* and force string */ + bp = (BYTE *)heap(); /* into Uppercase */ + i = env_start; + env_start = NULL; + + strcat(env_str,"="); + if (env_scan(env_str,bp)) { + if (novell_extension(env_str,bp)) break; + } + + while(*bp && i < MAX_LINE-1) + line[i++] = *bp++; + break; + } + + c = *batch_ptr(); + if (c == '\r') { + batch->offset--; /* rewind to point to '\r' */ + break; /* then break to normal code */ + } + if (c < '0' || c > '9') { /* if not a parameter */ + if(c != '%') /* or a '%' character */ + env_start = i+1; /* save its start address in */ + goto save_it; /* the string and wait for */ + } /* the terminating '%' */ + + n = c - '0' + batch->batshift; /* get parameter # 0-9 and */ + /* add in SHIFT offset */ + s = batch->batcmd; + while(n-- && strlen(s)) /* skip all other parameters */ + s += strlen(s)+1; /* before the one we want */ + + if((strlen(s) + i) >= MAX_LINE) /* Break if Greater than MAX_LINE*/ + break; + strcpy (line + i, s); /* get the substitution */ + i += strlen (s); /* add in its size */ + break; + + case 0x1a: + end_of_file: + batch->eof = YES; /* We have come to the end */ + c = '\r'; /* of the batch file so set */ + break; /* flag and mark end of line*/ + + default: + save_it: + if (i < MAX_LINE) + line[i++] = c; + if (dbcs_lead(c)) { + if ((c = *batch_ptr()) >= ' ' && i < MAX_LINE) + line[i++] = c; + } + } + } while (c != '\r'); /* repeat until CR */ + + line[i] = '\0'; /* Terminate the line and */ + + if(batch->eof) + return; + +#if 0 /* not DOS compatible */ + if(*batch_ptr() == 0x1A) /* Check if the next this */ + batch->eof = YES; /* the end of the file if */ + else /* YES then set the flag */ + batch->offset--; /* force the character to */ +#endif /* be re-read next time */ + return; /* return to the caller */ +} + +MLOCAL BOOLEAN following_command() +/* return true if we have a possible command on the rest of the line */ +{ +LONG old_offset; +BOOLEAN res = FALSE; +BYTE *s; + + old_offset = batch->offset; /* save batch offset */ + while (TRUE) { + s = batch_ptr(); /* look ahead at batch file */ + if (*s == '\r' || *s == 0x1a || (!dbcs_lead(*s) && *s == PIPE_CHAR)) + break; + if (!is_blank(s)) { + res = TRUE; /* possible command if we */ + break; /* hit non whitespace char */ + } + if (dbcs_lead(*s)) { + s = batch_ptr(); + if (*s == '\r' || *s == 0x1a) + break; + } + } + batch->offset = old_offset; /* restore batch offset */ + return res; +} + +MLOCAL VOID swallow_line(s) +BYTE *s; +/* there is a syntax error on this line - swallow it and say so */ +{ +BYTE c; + + prompt(); /* possibly echo the prompt */ + if (echoflg) /* echo to screen if wanted */ + printf("%s%c",s,PIPE_CHAR); + + do { + c = *batch_ptr(); + if (c == 0x1a) { + c = '\r'; /* pretend to be end of line*/ + batch->eof = YES; /* We have come to the end */ + break; /* flag and mark end of line*/ + } + if (echoflg) /* echo to screen if wanted */ + putc(c); + } while (c != '\r'); + if (echoflg) + putc('\n'); + + if (*batch_ptr() != '\n') /* skip line feed */ + batch->offset--; /* if present */ + + eprintf(MSG_SYNTAX); /* report syntax error */ +} + +/* + * In order to improve performance of the batch file processing + * the Batch file is read in blocks of BATCH_BUF characters. + * and the routine BATCH_CHAR then returns a pointer to a character + * from the buffer (filling the buffer if required). + */ +MLOCAL BYTE *batch_ptr() +{ + BYTE FAR *buf; + UWORD bufsize; + UWORD i; + + if(batch->eof) + return(batch_eof); + + if (batch->offset < batch_off || + batch->offset >= (batch_off + (LONG) (batch_cnt - 1))) { + + batch_off = batch->offset; + ms_x_lseek (batch->stream, batch->offset, 0); + batch_cnt = far_read(batch->stream, gp_far_buff, sizeof(batch_buf)); + if(batch_cnt <= 0) { + batch->eof = YES; + return(batch_eof); + } + for (i=0; ioffset++ - batch_off)]); +} + + +/*.pa*/ +/* + * BATCH FILE COMMANDS + * =================== + * + * The following commands are used almost entirely in BATCH files and + * have little or no meaning outside that environment. + */ +GLOBAL VOID CDECL cmd_shift () +{ + batch->batshift++; /* Increment the Shift Offset */ +} + + +MLOCAL WORD label_ignore_char(s) +BYTE *s; +{ + if (*s == '=') return(1); + if (*s == ';') return(1); + if (*s == ',') return(1); + if (*s == ' ') return(1); + return(0); +} + +/* + * Extract the first a valid characters from the label and then + * zero terminate the resulting string. + */ +MLOCAL BYTE * make_label(label) +BYTE *label; +{ +REG BYTE *bp; +UWORD i; + + label = deblank(label); /* remove leading white space */ + while (label_ignore_char(label)) + label = skip_char(label); + + bp = label; + + while (is_filechar(bp)) /* skip over valid chars */ + bp = skip_char(bp); + + *bp = '\0'; /* make label zero terminated */ + return label; +} + +GLOBAL VOID CDECL cmd_goto (label) /* goto label in batch file */ +REG BYTE *label; +{ +UWORD i; +BYTE *bp, s[MAX_LINE+2]; /* Allocate buffer for Batch Input */ + + if (!batchflg) /* if not in batch mode */ + return; /* this command is ignored */ + + if(*label == ':') /* Ignore any leading ':' */ + label++; + + label = make_label(label); /* Convert to Label Format */ + + batch->offset = 0L; /* rewind the batch file */ + batch->eof = NO; /* So it cannot be EOF */ + + if(!batch_open()) /* Check the Batch file is open */ + return; /* and stop if the function fails. */ + + while(!batch->eof) { /* while not end of file read next */ + batch_read(s, YES); /* line and return the next command */ + bp = deblank(s); + if((*bp == ':') && !strnicmp(make_label(bp+1),label, 8)) + return; + } + + batch_end(); /* Stop any further batch file */ + crlfflg = YES; /* processing and print the error */ + eprintf(MSG_LABEL, label); +} + + +GLOBAL VOID CDECL cmd_gosub (label) /* gosub label in batch file */ +REG BYTE *label; +{ +UWORD i; +BYTE *bp, s[MAX_LINE+2]; /* Allocate buffer for Batch Input */ + + if (!batchflg) /* if not in batch mode */ + return; /* this command is ignored */ + + if (batch->ret_offset[3] != 0L) { + batch_end(); + crlfflg = YES; + eprintf(MSG_GOSUB); + return; + } + + if(*label == ':') /* Ignore any leading ':' */ + label++; + + label = make_label(label); /* Convert to Label Format */ + + i = 0; + while (batch->ret_offset[i] != 0L) i++; + batch->ret_offset[i] = batch->offset; + + batch->offset = 0L; /* rewind the batch file */ + batch->eof = NO; /* So it cannot be EOF */ + + if(!batch_open()) /* Check the Batch file is open */ + return; /* and stop if the function fails. */ + + while(!batch->eof) { /* while not end of file read next */ + batch_read(s, YES); /* line and return the next command */ + bp = deblank(s); + if((*bp == ':') && !strnicmp(make_label(bp+1),label, 8)) + return; + } + + batch_end(); /* Stop any further batch file */ + crlfflg = YES; /* processing and print the error */ + eprintf(MSG_LABEL, label); +} + +GLOBAL VOID CDECL cmd_return() +{ + UWORD i; + + if (!batchflg) return; + if (batch->ret_offset[0] == 0L) { + batch_end(); + crlfflg = YES; + eprintf(MSG_RETURN); + return; + } + i = 0; + while ((batch->ret_offset[i] != 0L)&&(i<4)) i++; + batch->offset = batch->ret_offset[i-1]; + batch->ret_offset[i-1] = 0L; +} + +#if SWITCH_ENABLED +GLOBAL VOID CDECL cmd_switch(list) +REG BYTE *list; +{ + BYTE *list_start; + BYTE *label; + WORD i,j; + BYTE c; + + if (!batchflg) return; + list_start = list; + +switch_retry: + list = list_start; + i = psp_poke(STDIN,1); + +#if defined(CDOSTMP) + c =(BYTE) bdos(C_RAWIO, 0xFD); /* Get a character from console */ + + if ((c==0) ||(dbcs_lead(c))) + bdos(C_RAWIO, 0xFD); /* skip second byte in DBCS pair */ +#else + c = (BYTE) msdos(MS_C_RAWIN, 0);/* Get a character from console */ + if ((c==0) || (dbcs_lead(c))) + msdos(MS_C_RAWIN, 0); /* skip second byte in DBCS pair */ +#endif + psp_poke(STDIN,i); + + if (c==0x03) int_break(); /* check for CTRL-C */ + if (c==0x0d) c = '1'; /* return gives default of 1 */ + + i = (WORD) (c - '1'); + if (i<0 || i>8) goto switch_retry; /* ignore invalid keys */ + + j = 0; + while (j') return(OP_NE); + if (op[1] == '=') return(OP_LE); + return(OP_LT); + } + if (op[0] == '>') { + if (op[1] == '=') return(OP_GE); + return(OP_GT); + } + return(-1); +} + +MLOCAL LONG get_decimal(s) +BYTE *s; +{ + LONG total = 0; + + if (*s == '#') s++; + + while (*s>='0' && *s<='9') { + total *= 10; + total += (LONG) (*s-'0'); + s++; + } + + return(total); +} + +MLOCAL BOOLEAN CDECL test_cond(cptr) +BYTE **cptr; +{ + BYTE *cmd,*str1, *str2, *ptr; + DTA search; + BOOLEAN not, cond, neg,is_user; + BYTE level; + BYTE c[]=" \n"; + WORD attr; + UWORD userid; + LONG val1,val2; + + cmd=*cptr; + not = cond = NO; /* Initialise the Flags */ + + if(!strnicmp(cmd = deblank(cmd), "not", 3)) { + not = YES; + cmd = deblank(cmd+3); + } + + switch(if_index(&cmd)) { + + /* + * EXIST Option extract the possibly ambiguous filename + * and check if it exists. + */ + case 0: + cmd = deblank(get_filename(heap(), cmd, YES)); + cond = !ms_x_first(heap(), ATTR_STD|ATTR_HID, &search); + break; + + /* + * DIREXIST Option checks if the given directory exists + */ + case 1: + cmd = deblank(get_filename(heap(), cmd, YES)); + attr = ms_x_chmod(heap(), ATTR_ALL, 0); + if (attr < 0) cond = FALSE; + else cond = (attr & 0x10); + break; + + /* + * ERRORLEVEL Option extract the decimal number from the + * command line. + */ + case 2: + level = 0; + neg = FALSE; + + if(*cmd =='-') { + neg = TRUE; + cmd++; + } + + if(!isdigit(*cmd)) { /* SYNTAX error if the */ + syntax(); /* first character is not a */ + return FALSE; /* digit. */ + } + + while(isdigit(*cmd)) + level = level * 10 + (*cmd++ - '0'); + + level = level & 0x00FF; + + if (neg) level = -level; + + cond = (level<=(err_ret & 0x00FF)); + break; + + +/*RG-02*/ +#if !defined(NOXBATCH) +#if (defined(CDOSTMP) || defined(CDOS)) + /* + * KEY ["string"] [==] [""] Search for the string "string" and + * display it if it exists, then read a key and echo it. + * However, if the string to match is null "" then do a keyboard + * status check and return TRUE if there is no key there + */ + case 3: + cmd = deblank(cmd); + ptr=cmd; + if (display_string(&ptr)!=0) + return FALSE; + + cmd = deblank(ptr); + while(*cmd == '=') /* Remove any "=" string */ + cmd++; + + cmd = deblank(cmd); + if ((*cmd==0)||(*(cmd+1)!=' ')) { /* check for condition */ + syntax(); + return FALSE; + } + + /* read a character from the keyboard */ + c[0]=bdos(C_RAWIO, 0xFD); /* Get a character from console */ + + /* echo the char typed */ + if (echoflg) /* echo to screen if wanted */ + putc(c[0]); + crlf(); /* print cr/lf */ + + /* check if it matches */ + if((tolower(c[0])==*cmd)||(toupper(c[0])==*cmd)) + cond=TRUE; + else + cond=FALSE; + + /* skip the condition */ + while (*cmd!=' ') + cmd++; /* skip the char */ + + break; + +#endif +#if !defined (NOSECURITY) && (defined(CDOSTMP) || defined(CDOS)) + /* + * USERID Option extract the 4 digit hex user id + * and check if it is us. + */ + case 4: + if (!login_enabled()) + return FALSE; + cmd = deblank(cmd); + if(aschextobin(cmd)==get_user_on_station()) + cond=TRUE; + else + cond=FALSE; + + do { /* skip past the user id */ + if ((*cmd>='0' && *cmd<='9') + ||(tolower(*cmd)>='a' && tolower(*cmd)<='f')) + cmd++; /* skip the hex digit */ + else { + syntax(); + return FALSE; + } + } while (*cmd!=' '); + break; + + /* + * LOGINNAME Option extract the loginname and check if it is us. + */ + case 5: + if (!login_enabled()) + return FALSE; + is_user=TRUE; + + /* + * GROUPNAME Option extract the loginname and check if it is us. + */ + case 6: + if (!login_enabled()) + return FALSE; + cmd = deblank(cmd); + if(aschextobin(user_info.userid)!=get_user_on_station()) { + if(get_user_info(get_user_on_station())!=0) { + syntax(); + is_user=cond=FALSE; + return FALSE; + } + } + if((is_user==TRUE)&&(strncmp(strlwr(cmd),strlwr(user_info.loginname),strlen(user_info.loginname))==0)) { + cond=TRUE; + cmd+=strlen(user_info.loginname); + } + else if((is_user!=TRUE)&&(strncmp(strlwr(cmd),strlwr(user_info.groupname),strlen(user_info.groupname))==0)) { + cond=TRUE; + cmd+=strlen(user_info.groupname); + } + else { + cond=FALSE; + while (*cmd!=' ') + cmd++; /* skip the name */ + } + if (*cmd!=' ') { + is_user=cond=FALSE; + } + is_user=FALSE; + break; + +#endif +#endif /*NOXBATCH*/ +/*RG-02-end*/ + /* + * String comparison option. + */ + default: + str1 = cmd; /* Extract String 1 */ + + while ((!is_blank(cmd)) && (*cmd != '=') && + ((*cmd != '!') || (cmd[1]!= '=')) && + (*cmd != '<') && (*cmd != '>')) { + + cmd = skip_char(cmd); + } + + str2 = cmd; + cmd = deblank(cmd); + + attr = get_operator(cmd++); + + if (attr == -1) { + syntax(); + return(FALSE); + } + + *str2 = 0; + + if (*cmd == '=' || *cmd == '>') cmd++; + + cmd = deblank(cmd); + str2 = cmd; + while (!is_blank(cmd)) cmd = skip_char(cmd); + *cmd++ = 0; + + if (*str1 == '#') { + val1 = get_decimal(str1); + val2 = get_decimal(str2); + switch(attr) { + case OP_EQ: cond = (val1==val2); break; + case OP_NE: cond = (val1!=val2); break; + case OP_LT: cond = (val1val2); break; + case OP_GE: cond = (val1>=val2); break; + } + } + else switch(attr) { + case OP_EQ: + cond = (strcmp(str1,str2) == 0); + break; + case OP_NE: + cond = (strcmp(str1,str2) != 0); + break; + case OP_LT: + cond = (strcmp(str1,str2) < 0); + break; + case OP_LE: + cond = (strcmp(str1,str2) <= 0); + break; + case OP_GT: + cond = (strcmp(str1,str2) > 0); + break; + case OP_GE: + cond = (strcmp(str1,str2) >= 0); + break; + } + break; + } + + if(not) /* if negated condition */ + cond = !cond; + + *cptr=cmd; + return cond; /* write result back */ +} + +#if !defined(NOXBATCH) +BOOLEAN is_it_or(BYTE *cmd) +{ + cmd--; + if ((*cmd != 0) && (*cmd != '\t') && (*cmd != ' ')) + return FALSE; + cmd++; + if (strnicmp(cmd, "or", 2) != 0) + return FALSE; + cmd+=2; + if ((*cmd != '\t') && (*cmd != ' ')) + return FALSE; + return TRUE; +} +#endif +GLOBAL VOID CDECL cmd_if(cmd) +BYTE *cmd; +{ + BOOLEAN cond; + + ifcond=cond=test_cond(&cmd); + + if(!*deblank(cmd)) { /* and return a SYNTAX error*/ + syntax(); /* if it is empty. */ + return; + } + if(!cond) { +#if !defined(NOXBATCH) + while (!is_it_or(cmd) && + (*cmd != 0)) { + if (strnicmp(cmd,"ECHO",4)==0) return; + cmd++; + } + if (*cmd==0) return; /* no OR's so quit now */ + + if_context = TRUE; + + docmd(deblank(cmd), YES); /* New command starts at "or" */ + +#endif + } + else { + cmd = deblank(cmd); + + if (strnicmp(cmd,"AND",3)) { + if (parse(cmd)) return; /* IF won't have been 'parsed' for */ + /* > or < redirectors so do it now */ + } + + if_context = TRUE; + /* Execute command if the */ + docmd(cmd, YES); /* condition flag is TRUE */ + } + if_context=FALSE; +} + +/*RG-03*/ +#if !defined(NOXBATCH) +GLOBAL VOID CDECL cmd_or(cmd) +BYTE *cmd; +{ + BOOLEAN cond; + BYTE *org_cmd; + + cond=test_cond(&cmd); + if(!*deblank(cmd)) { /* and return a SYNTAX error*/ + syntax(); /* if it is empty. */ + return; + } + if(!cond) { + org_cmd = cmd; /* now look for "OR" */ + while (!is_it_or(cmd) && + (*cmd != 0)) { + if (strnicmp(cmd,"ECHO",4)==0) while(*cmd) cmd++; + else cmd++; + } + if (*cmd==0) { /* oh dear, no ORs */ + if (ifcond) /* but so far so good, so do command anyway */ + docmd(deblank(org_cmd), YES); + return; + } + docmd(deblank(cmd), YES); /* New command starts at "or" */ + return; + } + else { + cmd = deblank(cmd); + + if (strnicmp(cmd,"AND",3)) { + if (parse(cmd)) return; /* IF won't have been 'parsed' for */ + /* > or < redirectors so do it now */ + } + + ifcond=cond; /* Execute command if the */ + docmd(cmd, YES); /* condition flag is TRUE */ + } +} +#endif /*NOXBATCH*/ +/*RG-03-end*/ + + +GLOBAL VOID CDECL cmd_for(s) +BYTE *s; +{ +FCONTROL *fc; +BYTE *bp1; + + fc = (FCONTROL *) heap_get(sizeof(FCONTROL)); + + /* Allocate Control Struct */ + if(forptr) /* and prevent nesting of */ + goto for_error; /* FOR Command. */ + + s = deblank(s); /* Remove leading blanks */ + if ((*s++ != '%') || /* Get the FOR variable */ + (fc->forvar = *s++) < ' ') /* character and save */ + goto for_error; + + if(strnicmp(s = deblank(s), "in", 2)) /* Check for the correct */ + goto for_error; /* command syntax. */ + + s = deblank(s+2); + if (*s++ != '(') + goto for_error; + + fc->files = (BYTE *)heap(); /* Allocate FOR parameter */ + while(*s && *s != ')') { /* buffer and scan the */ + bp1 = (BYTE *)heap(); /* command line generating */ + /* zero terminated strings */ + while(strchr(batch_sep, *s)) /* Skip any separators */ + s = skip_char(s); + + while( *s != ')' && /* then copy all valid */ + !strchr(batch_sep, *s)) /* characters into buffer */ + /* then zero terminate */ + copy_char(&bp1, &s); + + *bp1++ = '\0'; + heap_get(strlen(heap()) + 1); /* Preserve String */ + } + + *(BYTE *)heap_get(1) = '\0'; /* Final String is zero */ + /* bytes in length */ + + s = deblank(s); + if(*s++ != ')') + goto for_error; + + if(strnicmp(s = deblank(s), "do", 2)) + goto for_error; + + if(in_flag & REDIR_ACTIVE) /* If Input redirection has been */ + in_flag |= REDIR_FOR; /* enabled for this command force*/ + /* it on for the complete command*/ + + if(out_flag & REDIR_ACTIVE) /* If Output redirection has been*/ + out_flag |= REDIR_FOR; /* enabled for this command force*/ + /* it on for the complete command*/ + + fc->cmd = (BYTE *)heap_get(strlen(s = deblank(s+2)) +1); + strcpy(fc->cmd, s); + + fc->sflg = NO; /* File matching inactive */ + for_flag = YES; /* Turn FOR processing ON */ + forptr = fc; /* Save control Structure */ + return; + +for_error: /* When a Syntax error occurs */ + heap_set((BYTE *) fc); /* restore the heap and print */ + syntax(); /* an error message. */ + return; +} + +GLOBAL VOID for_end() +{ + if(for_flag) { + heap_set((BYTE *) forptr); /* Terminate FOR processing */ + forptr = (FCONTROL *) NULL; /* restore the HEAP and reset */ + for_flag = NO; /* control flags. */ + } +} + +/*.pa*/ +/* + * This command generates the displayed prompt based on the contents + * of the string PROMPT= in the environment. Otherwise the default + * prompt string DEFAULT_PROMPT is used. + */ + +MLOCAL BOOLEAN prompt_flg = FALSE; /* Prompt Flag */ + +MLOCAL VOID prompt() /* display command line prompt */ +{ + REG BYTE *cp; + BYTE buf[MAX_PATHLEN]; + BYTE c; +#if !STACK + BYTE cpbuf[MAX_ENVLEN]; +#endif +/*rbf*/ +#if 1 +BYTE prmptcpbuf[MAX_ENVLEN]; +REG BYTE *prmptcp = prmptcpbuf; +#endif + + if(!echoflg) /* Return if No Echo */ + return; + + + +#if defined(CPM) + cp = heap(); + strcpy(cp, "[CPM] $u$p$g"); +#else + if(env_scan(msg_prmeq, cp = (BYTE *)heap())) + strcpy(cp, DEFAULT_PROMPT); +#endif + + if(prompt_flg) /* If the previous Prompt display */ + strcpy(cp, "$n$g"); /* terminated due to a Critical */ + /* then just display the default */ + prompt_flg = TRUE; /* drive. */ + +#if STACK + cp = stack(strlen(cp) + 1); +#else + cp = &cpbuf[0]; +#endif + strcpy(cp, heap()); + + while((c = *cp++) != 0) { /* get next character */ + if (c != '$') /* if not '$', print as is */ + putc (c); + else { + c = *cp++; + switch(tolower(c)) { /* else get next character */ + case '\0': /* Treat "$\0" as an invalid */ + cp--; /* prompt command sequence */ + break; + case 't': /* print current time */ + disp_systime(); + break; + case 'd': /* print current date */ + disp_sysdate(); + break; + case 'p': /* print current path */ + if (ms_x_curdir(drive+1, buf) < 0) + printf(MSG_DRV_INVALID); + else + printf("%c:%s%s", drive+'A', pathchar, buf); + break; + case 'v': /* print version number */ + cmd_ver(""); + break; + case 'n': /* print default drive */ + putc((BYTE) drive+'A'); + break; + case 'g': /* print ">" */ + putc ('>'); + break; + case 'l': /* print "<" */ + putc ('<'); + break; + case 'b': /* print "|" */ + putc ('|'); + break; + case 'q': /* print "=" */ + putc ('='); + break; + case '_': /* print CR,LF */ + crlf(); + break; + case 'h': /* print backspace, space, backspace */ + printf("\b \b"); + break; + case 'e': /* print ESC character */ + putc ('\33'); + break; +/*RG-01 */ + +#if !defined(NOXBATCH) +#if !defined (NOSECURITY) +#if defined(CDOSTMP) || defined(CDOS) + case 'm': /* print mail status */ + if (login_enabled()) { + if(chk_mail()) { /* we have mail */ + if(env_scan("MAIL=", heap())) + printf(MSG_UHAVEMAIL); + else + printf("%s",heap()); + } + } + break; + + case 'u': /* Display the User Name */ + if (login_enabled()) { + if((aschextobin(user_info.userid)!=get_user_on_station())||(strlen(user_info.userid)==0)) { + if(get_user_info(get_user_on_station())!=0) + printf("#%04X",get_user_on_station()); + else + printf("%s",user_info.loginname); + } + else + printf("%s",user_info.loginname); + } + break; +#endif +#endif +#endif /*NOXBATCH*/ +/*RG-01-end*/ +#if defined(CPM) + case 'u': /* Display the User Number */ + printf("%d", user); + break; +#endif +#if defined(DOSPLUS) + case 'u': + if (!env_scan("LOGINNAME=",heap())) + printf("%s",heap()); + break; +#endif + case '$': + putc ('$'); /* print single '$' */ + break; + case 'x': + if ((allow_pexec)&&(!batchflg)) prompt_exec(); + break; + default: /* Otherwise the character */ + break; + } + } + } + + prompt_flg = FALSE; /* Prompt display completed OK */ +} + + +#if !defined(CDOSTMP) +/* The following functions are called by the int2e_handler function in + * COM.C. If a program is run from a batch file and calls INT 2E to + * execute a new batch file the original batch file must NOT be terminated. + * Therefore batch and batchflg must be saved, set to zero, and then + * restored when INT 2E returns. - EJH + */ + +GLOBAL VOID int2e_start() +{ + batchflg_save = batchflg; + batchflg = 0; + batch_save = batch; + echoflg_save = echoflg; + echoflg = ECHO_ON; +} + +GLOBAL VOID int2e_finish() +{ + batchflg = batchflg_save; + batch = batch_save; + echoflg = echoflg_save; +} + +#endif + +#if defined(CDOS) +MLOCAL VOID map_user_page(UWORD window_page, UWORD physical_page) +{ +UWORD pblk[3]; + pblk[0] = window_page; + pblk[1] = physical_page; + pblk[2] = 0; + bdos(181, pblk); +} + + +MLOCAL BYTE FAR * map_pd_mem(UWORD ppd, UWORD wp, UWORD seg, UWORD offset) +{ +/* Map memory for another process into our memory space so we examine it */ +UWORD base_seg; +UWORD page; +PD FAR * pdptr; +UWORD sysdat; +UWORD mptbl; +UWORD FAR * ptr; +UWORD mp_off; +UWORD i; +MPAD FAR * mp; + + + sysdat = FP_SEG(pd); + ptr = MK_FP(sysdat, 0xc8); +/* DEBUG */ + if (*ptr == 0) /* for DEBUG under XM assume non-banked system */ + return(MK_FP(seg, offset)); +/* DEBUG */ + ptr = MK_FP(sysdat, *ptr + 8); + mptbl = *ptr; + + /* get segment of 4k page to map */ + base_seg = (seg + (offset+15)/16) & 0xff00; + + + /* now find physical page to map */ + + pdptr = (PD FAR *) MK_FP(sysdat, ppd); + + for (mp_off = pdptr->P_MPAR; mp_off !=0;) { + mp = MK_FP(sysdat, mp_off); + mp_off = mp->link; + if ((base_seg >= mp->start) && + (base_seg < (mp->start + mp->length))) { + page = mp->xios; + for (i = 0; i < ((base_seg - mp->start)/1024); i++){ + ptr = MK_FP(mptbl, page*2); + page = *ptr; + } + page = 4*page + (((base_seg - mp->start)/0x0100) & 3); + map_user_page(wp, page); + return(MK_FP(wp*0x0100,(seg*16+offset) & 0x0fff)); + } + } + + /* not found in mpad's - must be non-banked address */ + return(MK_FP(seg, offset)); +} + +MLOCAL VOID ip_poke(UWORD ppd, UWORD wp, UWORD seg, UWORD offset, UBYTE val) +{ +UBYTE FAR *ptr; + + ptr = map_pd_mem(ppd, wp, seg, offset); + *ptr = val; +} + +MLOCAL UBYTE ip_peek(UWORD ppd, UWORD wp, UWORD seg, UWORD offset) +{ +UBYTE FAR *ptr; + + ptr = map_pd_mem(ppd, wp, seg, offset); + return(*ptr); +} + +MLOCAL UWORD ip_peek_word(UWORD ppd, UWORD wp, UWORD seg, UWORD offset) +{ + return (ip_peek(ppd, wp, seg, offset) + + 256*ip_peek(ppd, wp, seg, offset+1)); +} + +GLOBAL VOID inherit_TMP_state(VOID) +/* inherit batch files */ +/* NB. This is bodged - we don't inherit FOR state, or redirection */ +{ +PD FAR *parent; +UWORD batch_seg; +UWORD tmp_mpad; +UWORD mp_off; +MPAD FAR * mp; +VOID FAR *window; +UWORD win_page; +UWORD i; + + parent = (PD FAR *) MK_FP(FP_SEG(pd), pd->P_PARENT); + + /* verify our parent is a Tmp, forget if it isn't */ + if ((parent->P_NAME[0] != 'T') || + (parent->P_NAME[1] != 'm') || + (parent->P_NAME[2] != 'p')) + return; + + /* allocate a 4k aligned window to bank data into */ + i = 2*4096/16; + mem_alloc(&window, &i, i, i); + if (i==0) + return; + win_page = (FP_SEG(window) + 0x0100) / 0x100; + + batch_seg = ip_peek_word(pd->P_PARENT, win_page, + parent->P_PSP, TmpPspBatchSeg); + + /* do we have any batch files to inherit */ + if (batch_seg) { + + echoflg = (BOOLEAN)ip_peek_word(pd->P_PARENT, win_page, + ip_peek_word(pd->P_PARENT, win_page, + parent->P_PSP, TmpPspDataSeg), + ip_peek_word(pd->P_PARENT, win_page, + parent->P_PSP, TmpPspEchoFlgPtr)); + + /* recover Tmp's hidden mpads */ + + tmp_mpad = ip_peek_word(pd->P_PARENT, win_page, + parent->P_PSP, TmpPspMpad); + + for (mp_off = parent->P_MPAR; mp_off != 0;) { + mp = MK_FP(FP_SEG(parent), parent->P_MPAR); + mp_off = mp->link; + } + + mp->link = tmp_mpad; + inherit_batch_file(pd->P_PARENT, win_page, batch_seg); + mp->link = 0; /* unlink again */ + } + map_user_page(0, 0); /* force user page to be unmapped */ + bdos(141,0); /* dispatch to re-map TPA memory */ + mem_free(&window); /* free the window */ +} + +MLOCAL VOID inherit_batch_file(UWORD ppd, UWORD win_page, UWORD batch_seg) +{ +UBYTE FAR * dst; +BCONTROL FAR *save0; +FCONTROL *save1; +BYTE *save2; +WORD save3; +UWORD i; +UWORD data_seg; +PD FAR *parent; + + + + /* if we are in a nested batch file, inherit older batch file first */ + i = ip_peek_word(ppd, win_page, batch_seg, 2); + + if (i != 0) + inherit_batch_file( ppd, win_page, i); + + batch_new(); /* new incarnation of batch */ + + save0 = batch->bcontrol; save1 = batch->fcontrol; + save2 = batch->heap_start; save3 = batch->heap_size; + + dst = (BYTE FAR *) batch; /* copy batch structure */ + for (i=0; ieof - (UWORD) &batch->bcontrol, + (UBYTE) TRUE); + + /* + * Copy the invoking command and the individual elements + * of the command line into a buffer ready for processing + */ + + parent = (PD FAR *) MK_FP(FP_SEG(pd), pd->P_PARENT); + data_seg = ip_peek_word(pd->P_PARENT, win_page, + parent->P_PSP, TmpPspDataSeg); + + i = (UWORD) batch->batcmd; + batch->batcmd = (BYTE *)heap(); /* Initialize Parameter Buffer */ + + while (ip_peek_word(ppd, win_page, data_seg, i) != 0) + *(BYTE *)heap_get(1) = ip_peek(ppd, win_page, data_seg, i++); + + *(WORD *)heap_get(2) = 0; /* Double NULL is a terminator */ + /* for command line params */ + + batch->bcontrol = save0; batch->fcontrol = save1; + batch->heap_start = save2; batch->heap_size = save3; + + batchflg++; /* increment batch flag */ + + crlfflg = YES; /* print CR/LF after this */ +} +#endif + + +EXTERN N_CMD novell_ext_list[]; + +EXTERN BYTE FAR * CDECL farptr(BYTE *); +EXTERN BYTE FAR * CDECL cgroupptr(BYTE *); + +EXTERN BOOLEAN CDECL call_novell(BYTE *, BYTE *, WORD); +EXTERN BOOLEAN CDECL nov_station(WORD *); +EXTERN WORD CDECL nov_connection(); + + +MLOCAL BOOLEAN novell_extension(src,dst) +BYTE *src; +BYTE *dst; +/* + * Check if src string is a novell string to be expanded. eg login_name. + * if so, put expansion in dst. + */ +{ + N_CMD FAR *n_cmd_p; + BYTE FAR *cpf; + WORD i; + + for (i=0;src[i] && src[i]!='=';i++); + src[i] = 0; + + n_cmd_p = (N_CMD FAR *)farptr((BYTE *)&novell_ext_list[0]); + + while(n_cmd_p->string) { + + cpf = cgroupptr(n_cmd_p->string); + + for(i=0; (cpf[i]==src[i]) && src[i]; i++); + + if(cpf[i]==src[i]) { + (*n_cmd_p->func)(dst); + return(0); + } + + n_cmd_p++; + } + return(1); +} + + + +GLOBAL VOID CDECL get_login_name(dst) +BYTE *dst; +{ + struct s_nov_e346_in { + WORD len; + BYTE code; + } nov_e346_in; + struct s_nov_e346_out { + WORD len; + BYTE level; + LONG id; + } nov_e346_out; + struct s_nov_e336_in { + WORD len; + BYTE code; + LONG id; + } nov_e336_in; + struct s_nov_e336_out { + WORD len; + LONG id; + WORD type; + BYTE name[48]; + } nov_e336_out; + + nov_e346_in.len = 1; + nov_e346_in.code = 0x46; + nov_e346_out.len = 5; + nov_e346_out.id = -1L; + call_novell((BYTE *)&nov_e346_in, (BYTE *)&nov_e346_out, 0xE3); + + if (nov_e346_out.id == -1L) { + *dst = 0; + return; + } + + nov_e336_in.len = 5; + nov_e336_in.code = 0x36; + nov_e336_in.id = nov_e346_out.id; + nov_e336_out.len = 54; + call_novell((BYTE *)&nov_e336_in, (BYTE *)&nov_e336_out, 0xE3); + + strcpy(dst,nov_e336_out.name); + +} + +GLOBAL VOID CDECL get_pstation(dst) +BYTE *dst; +{ + WORD sn[3]; + + if (nov_station(sn)) { + *dst = 0; + return; + } + + sprintf(dst,"%04X%04X%04X",sn[0],sn[1],sn[2]); +} + + +GLOBAL VOID CDECL get_full_name(dst) +BYTE *dst; +{ +/* scan bindery */ +struct s_nov_e337_in { + WORD len; + BYTE code; + LONG last_object_id; + WORD object_type; + BYTE object_name_len; + BYTE object_name[48]; + } nov_e337_in; + +struct s_nov_e337_out { + WORD len; + LONG object_id; + WORD object_type; + BYTE object_name[48]; + BYTE object_flag; + BYTE object_security; + BYTE object_has_properties; + } nov_e337_out; + + +/* scan property */ +struct s_nov_e33c_in { + WORD len; + BYTE code; + WORD object_type; + BYTE object_name_len; + BYTE object_name[48]; + LONG sequence_num; + BYTE property_name_len; + BYTE property_name[16]; + } nov_e33c_in; + +struct s_nov_e33c_out { + WORD len; + BYTE property_name[16]; + BYTE property_flags; + BYTE property_security; + LONG sequence_num; + BYTE property_has_value; + BYTE more_properties; + } nov_e33c_out; + + +/* read property */ +struct s_nov_e33d_in { + WORD len; + BYTE code; + WORD object_type; + BYTE object_name_len; + BYTE object_name[48]; + BYTE segment_num; + BYTE property_name_len; + BYTE property_name[16]; + } nov_e33d_in; + +struct s_nov_e33d_out { + WORD len; + BYTE property_value[128]; + BYTE more_segments; + BYTE property_flags; + } nov_e33d_out; + +int res; + + + +get_login_name(nov_e337_in.object_name); +nov_e337_in.object_name_len = strlen(nov_e337_in.object_name); +if (!nov_e337_in.object_name_len){ + *dst = 0; + return; + } + +nov_e337_in.code = 0x37; +nov_e337_in.len = sizeof(struct s_nov_e337_in) - 2; +nov_e337_out.len = sizeof(struct s_nov_e337_out) -2 ; +nov_e337_in.last_object_id = -1L; +nov_e337_in.object_type = 0x0100; /*user*/ + + +for(;;){ + res = call_novell((BYTE *)&nov_e337_in, (BYTE *)&nov_e337_out, 0xe3 ); + if ( res == 0xfc ) + break; + else if ( res ){ + *dst= 0; + return; + } + + if ( nov_e337_out.object_has_properties ){ + nov_e33c_in.code = 0x3c; + nov_e33c_in.len = sizeof(struct s_nov_e33c_in) - 2; + nov_e33c_out.len = sizeof(struct s_nov_e33c_out) - 2; + nov_e33c_in.object_type = nov_e337_out.object_type; + nov_e33c_in.object_name_len = sizeof( nov_e33c_in.object_name ); + strcpy( nov_e33c_in.object_name, nov_e337_out.object_name ); + nov_e33c_in.sequence_num = -1L; + nov_e33c_in.property_name_len = 1; + nov_e33c_in.property_name[0] = '*'; + + for(;;){ + res = call_novell( (BYTE *)&nov_e33c_in, (BYTE *)&nov_e33c_out, 0xe3 ); + if ( res == 0xfb ) + break; + else if ( res ){ + *dst = 0; + return; + } + + if ( nov_e33c_out.property_has_value ){ + nov_e33d_in.code = 0x3d; + nov_e33d_in.len = sizeof (struct s_nov_e33d_in) - 2; + nov_e33d_out.len = sizeof (struct s_nov_e33d_out) - 2; + nov_e33d_in.object_type = nov_e337_out.object_type; + nov_e33d_in.object_name_len = sizeof( nov_e33d_in.object_name ); + strcpy( nov_e33d_in.object_name, nov_e337_out.object_name ); + nov_e33d_in.segment_num = 1; + nov_e33d_in.property_name_len = strlen( nov_e33c_out.property_name ); + strcpy(nov_e33d_in.property_name, nov_e33c_out.property_name ); + for(;;){ + res = call_novell( (BYTE *)&nov_e33d_in, (BYTE *)&nov_e33d_out, 0xe3); + if ( res == 0xec ) + break; + else if ( res ){ + *dst = 0; + return; + } + + if (!strcmp(nov_e33c_out.property_name,"IDENTIFICATION")){ + strcpy(dst,nov_e33d_out.property_value); + return; + } + nov_e33d_in.segment_num++; + }/*for*/ + }/*if*/ + nov_e33c_in.sequence_num = nov_e33c_out.sequence_num; + }/*for*/ + nov_e337_in.last_object_id = nov_e337_out.object_id; + }/*if*/ + }/*for*/ +} + + + +GLOBAL VOID CDECL get_hour(dst) +BYTE *dst; +{ + SYSTIME time; + + ms_gettime(&time); + + if (time.hour > 12) time.hour -= 12; + if (time.hour == 0) time.hour = 12; + + sprintf(dst,"%d",time.hour); +} + +GLOBAL VOID CDECL get_hour24(dst) +BYTE *dst; +{ + SYSTIME time; + + ms_gettime(&time); + + sprintf(dst,"%02d",time.hour); +} + +GLOBAL VOID CDECL get_minute(dst) +BYTE *dst; +{ + SYSTIME time; + + ms_gettime(&time); + + sprintf(dst,"%02d",time.min); +} + +GLOBAL VOID CDECL get_second(dst) +BYTE *dst; +{ + SYSTIME time; + + ms_gettime(&time); + + sprintf(dst,"%02d",time.sec); +} + +GLOBAL VOID CDECL get_am_pm(dst) +BYTE *dst; +{ + SYSTIME time; + BYTE FAR *p; + + ms_gettime(&time); + + if (time.hour >= 12) p = cgroupptr(PM_TIME); + else p = cgroupptr(AM_TIME); + + while (*p) *dst++ = *p++; + *dst = 0; +} + +GLOBAL VOID CDECL get_greeting(dst) +BYTE *dst; +{ + SYSTIME time; + BYTE FAR *p; + + ms_gettime(&time); + + if (time.hour < 12) + p = cgroupptr(GREETING_MORNING); + else if (time.hour < 17) + p = cgroupptr(GREETING_AFTERNOON); + else + p = cgroupptr(GREETING_EVENING); + + while (*p) *dst++ = *p++; + *dst = 0; +} + +GLOBAL VOID CDECL get_year(dst) +BYTE *dst; +{ + SYSDATE date; + + ms_getdate(&date); + + sprintf(dst,"%d",date.year); +} + +GLOBAL VOID CDECL get_short_year(dst) +BYTE *dst; +{ + SYSDATE date; + + ms_getdate(&date); + + sprintf(dst,"%d",date.year%100); +} + +GLOBAL VOID CDECL get_month(dst) +BYTE *dst; +{ + SYSDATE date; + + ms_getdate(&date); + + sprintf(dst,"%d",date.month); +} + +GLOBAL VOID CDECL get_month_name(dst) +BYTE *dst; +{ + SYSDATE date; + BYTE *m; + + ms_getdate(&date); + + switch(date.month) { + case 1: m = JAN_M; break; + case 2: m = FEB_M; break; + case 3: m = MAR_M; break; + case 4: m = APR_M; break; + case 5: m = MAY_M; break; + case 6: m = JUN_M; break; + case 7: m = JUL_M; break; + case 8: m = AUG_M; break; + case 9: m = SEP_M; break; + case 10: m = OCT_M; break; + case 11: m = NOV_M; break; + case 12: m = DEC_M; break; + } + + sprintf(dst,"%s",m); +} + + + + +GLOBAL VOID CDECL get_day(dst) +BYTE *dst; +{ + SYSDATE date; + + ms_getdate(&date); + + sprintf(dst,"%d",date.day); +} + +GLOBAL VOID CDECL get_nday_of_week(dst) +BYTE *dst; +{ + SYSDATE date; + + ms_getdate(&date); + + sprintf(dst,"%d",date.dow+1); +} + +GLOBAL VOID CDECL get_day_of_week(dst) +BYTE *dst; +{ + SYSDATE date; + + ms_getdate(&date); + + sprintf(dst,"%s",day_names(date.dow)); +} + +GLOBAL VOID CDECL get_os_version(dst) +BYTE *dst; +{ + env_scan("VER=",dst); +} + +GLOBAL VOID CDECL get_connection(dst) +BYTE *dst; +{ + int i; + + i = nov_connection(); + if (i==-1) { + *dst = 0; + return; + } + + sprintf(dst,"%d",i); +} diff --git a/COMMAND/BIN/BATCH.OBJ b/COMMAND/BIN/BATCH.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..24cbc5f81e1bb9f56fecbc3ae0b3ab0583df87b6 GIT binary patch literal 13105 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 literal 0 HcmV?d00001 diff --git a/COMMAND/BIN/CMDLIST.OBJ b/COMMAND/BIN/CMDLIST.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..d8665a42095a2ef35816aba3368836ad76d2a0a4 GIT binary patch literal 2335 zcmZ9Oe~4676vxl}*x&9tuB)!AuH*V^)7;k8%p}PDG48CoGuzDU@dw6p_RZUwr!(`$ zH*eI9qQxQ>k=QI`5fPIRkqDCtkqDD_BcwkhBKiR#MPxz|78DWKId|@eHE`zpIp>~x z-kba0Im~1uG<5CLbE&LZbh`9sr`iFaEz!SuQ?Spnv&noam?+s}Rwn@ zaMx4!;;AlxDlHM(o$&WZ2SR>rI6kPTFCO=iRre3ZqN5|#15!F?YM>Lq>+@_N3h(gw zt2`ew0aVv`8czG6_P%!yN!@+lt`ldy4O-f8w49kQIR-RnbcdR4I3+u;oPurT3Jy7( zRy1@gpMrXsmbQweF=Dyj$~zeqFCZk|~wsOcWmETZIXAFU5>G?o=|&TqPrAWDlvR znaWn8dNP|;QRArTs1jqgkvv!l>lq7btqT#42wvnq;HYyuzBd<2(QfiTY0}&TaB`4IPIj%rYsVBzg+_Mqp$izHl zYSy@R#4rxRY#E~GnKyLDwDKxo6*YQLMGgci)&I9A#}8Y}C+RrLMY2}f%$EaAa?f}v zn|(N;n6Yei0F5%CP;`>=qGdO28-`=%)6gi7%&|*`EdTp-06gCETfmJ&J#%4t0fhou z-a2g1MU114#w(K^XgC-3c>zB2(3=h(xJ62R0AG@Nzz5$-zY4yS>W3ec|FhI;_=VI1 zHE@sA2et60jMu?GGG5Q6XuSb`l<`?mMLs|y)XVs6Xp-6lbCthPt_Pr<)DLr@Luxa0 zN}UVq$Qp-t2JqBtZ z^8DBt9UO{ik>24DjA-#hZ(=AKfo-EZca~$}=x7Z1i&}YjC^DJ|K|ItSjSN8Vur@Lb zgRxL3F%%ip5<^sBPpCHr@o+Sj&?F8=BZ)A`?{c|;-aSC3MYn0YLZKZHdDw}@H4Me# zd;@)FwtK}V*d^Q+k5}Bl$HaApk8qv%kl`A3i>nMD;3MKahAX&UTxNI&tHs+4mvE!F z$Z!FJ;w^^rxJjI2IE%I748v*kiy4Mf=n-!)oWw`PG{dV{FHSHV#|>hN;T3#byv%S6 zd&DGzjf+Kr;Q-c&48s_%6#E(W;vBJ?A%;(g5r*y9BEk%PI9qIG*n)G#W`-VIF1i`k z;8M}a(1BhNWN5=xqLrbUAiz+MD?}}Wmy&_N{TqGmUkvxK#{G@qF3xiAFno_4?rnx| zaJBmt!{-FI7;a*~{gmMb!F7gfxW>K8a0TbPml-b6(nW^z*x;UHIE_{A48uuW+K3}d*=-OsR>a&|MsC})IWJ2tvuhCXa^w=!(O zW_L3~4=!=L8P?!hx09g*+ua~T8%0_fnsI>}V5rB1ZY_hCehv`4Fx3KZ=Rf~~*1z;x K$Nl5f>(0OA7lI!E literal 0 HcmV?d00001 diff --git a/COMMAND/BIN/COM.OBJ b/COMMAND/BIN/COM.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..62c58dd4cb6dc8f9ded89dd2795b76bcc1edf41f GIT binary patch literal 9945 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 literal 0 HcmV?d00001 diff --git a/COMMAND/BIN/COMCPY.OBJ b/COMMAND/BIN/COMCPY.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..b4f2d44c5d097089b81c214db17bf4331a01f84a GIT binary patch literal 7149 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 VFa=3wO>1j!`+%rnmyF}`e*lAoG{gV^ literal 0 HcmV?d00001 diff --git a/COMMAND/BIN/CSUP.OBJ b/COMMAND/BIN/CSUP.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..329b9d8e176c6dbef089eac18017f3a5ed8c8441 GIT binary patch literal 3917 zcmY+HZ)_Y#6~N!_-R<4^PwXVnqI_^vkSrin#J#pM4JnH9hti6sD)|Fdonh~G?!5Ny z>}LO*<9-MZPKneDsrgcsDj!lIiWE>3BtE!7stjjCgj9)sqoNY2B2__7B@{r0P;|VR zH@kNv(!Muu-h1=j?99)5O9e0v?0anzz&iN#=Z_wLu6Xe1p~J;P2aX-E4k<&4$w7%7 zJN)fqwb#q=`Q2u@V2nzw2v*Vf;u}RUd&YNBlzQfi7yn%-+dfNNpF_zGBj%$>TPP}x zG-8gOaMH-b;SK4*qiF9VBx)ocCGi-EX(gs;H1!oVdStH>(-biMI8-nTYq}nXDo>+; z)+#l5U9QlKT;{-zR>XPYiWak*36De&2pG?8yv+s94OsjjQkKdr_d?bPe5fidjDi+a zT+yaQ%2E?4_9zwVY|a+4={Y;ph0LX%EMzWKb}taEIX`4j_JRc#^A?nRTkV!_FG@c@ z5Lob#AGcWDb{f6|)l3g_a}XxEIf!AHJQClH`vbw_B%i^iu?OYmiYUt&aeE#r(%J|` z6Gli|jNI0&4sC>sG54AjiZ8MelIrk!+M?_ZZ#Qk%gR+cv+=$XRZfw^*u2*ur0E-z@ z9#Na&ZrPse(9*my8&G3hwDDC^R@9rRr?c|N)*g{`KjUVtHXA|cW~<6G z5tDNh-@n#mR<#qYAWrLKbR9fBs(n}3jl^whXIBJaW|!y2_F!B#p&QVrPFg&>&ULk3 z-J=*Uu$|COW~n3n=4owzUhb6YLr6`%LBY9$yGg-vpboVvOO8~kQMs7li5DP91>DDX9wqq*S8dGF%MF_PAO!O= z(vnH>BJH{eMU^lR(nGa^2h?)~2UTv6CWD*W-x8@gQJc0Tw9}Z=LJ=2Ke#DbB5;PzA z`QeIr#3HAoJ7CH{TV*+Ehe)M! zDsP&85lWS?ttw5oO}MSHoVOMu;7TcpYcb-hloGHg6=8>&JiZ#SL-`R^dpT7}qaTr3nQJ_9h#5`ig5Ay})D!Q?>@ zCbOb2^^#*)&qxkuGaAI(RcHT4VoFIUrUoRZC@zOF)tS+lLI}sSmLdi@Wk9A3Ig$HA zg|cm`kUo>MX$|Ep6;YXXQ)79IBKusXY6#4_8cAl#n4>u#;_}F5>Qtha!immhm0NO6 zE7E~#$>2NYfNinqoAjsr>;?)2s${ zK9HoQdNNeglxB4m{~T&qld8!;xV9MadK;6?^nqPr8L=%!$VRD{jZ#6|Vnl6}3fmQy zaob`9?lRNlE-@CyA^h#i=S&0OqyKh4Io`QDal$%z2jEh-bMqUuUTtl1x|BS%eAa@b zdhgopCwtFYn|C`~6V~o>=WOv8SBKWp`{ zr*_W_u9kc#!#=$9=gwB)er@gTUhm$u3tLYVlZp=i$Imx!4lI)V@?jG?H*0H`x;1pY z{jV+lS@wm zd^4#i`9eA}`DOv$yG8%Y!)x6M+2VCj)oi`L{8zK{9<6w?^9Nkx?{B3gHrnfTzoR^4 z2_JQF2j2uJ94ST*p8I$S_T7obegbgL0$73z_?+q9D8Tcp0MB8^UJ$GWW_Hk!@ zri;NcN9Ra!KR{eSM-0z1%yjpy$HRNpxBj#bbG41`4RbJ=b@G$-v&GJ{mFv6iT}zDv zog%c?{NJ2gWYJx+$YSy)p)-i9dw!2Tc-$=vP=7M@u!vkGgs0y8;8>SQ!Pw zkRKuPX92)JS9aleCv$=r?_GpnV)8G6uzmi40YAlzhEb7UGZ^5V2DrMi9WD52ffg>3 zXt4nB;DDDaVtkz(*EJ0M7D2DLVT-Q<_}Z!I3Wo>HH3ME;*@;dgtm&okENj?}S^h5r zzP~bp))IbM*x?Thcwc8yO|^J(#DHkf6!YX213s&(QeLt95|0hIsS~kp9ed_21FTnY HKa&3e=JYd6 literal 0 HcmV?d00001 diff --git a/COMMAND/BIN/DOSIF.OBJ b/COMMAND/BIN/DOSIF.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..7243514e6363556f787495a1953abc6fbadcc483 GIT binary patch literal 2800 zcmZWreQXnD7=P})+qI03ZJ?kShK;%?C>Un^fT2vrh6@5g=n$nZUHf)B*R}QTIyR#V ziDTLxLQ!MzBZB@xO#GVh{%8bEp~5ug)Wj&$5d6YKGDU^xj8W_J-d)#Q{O8`@?|Giz z^Z7p4T_On0E1qcpkXN^D+OTD#w0c9!8mXmubF*=Ys#78~BLzX`;Ulx>w8hJDM<`nDHQm<>wiEGw|RXkKmw4sgUk zUp>oJeu(qS;x%h_XA zKqC`lww)1@%-gxrw(&DuW4(m*W-CYT;AX23tVg92LD^Ve?HDdZ7n4Gi8C>QslbX$F zj8^8IlcH=Zw-hJFo;ALj^x854WfSh$rdjld*)k${U~@HQ#ba*e{8bZUe~0&EM}Xtq@{*YWBhb+7|fj6vyS71aC89acakjfIIZikjx# zR=_E(-<*%dvwfNC$LHpFNLX(K%?;x|_tgzS#1L%e4&)0OgRFP?~+yVautZp6^E!ml z%Av;m=aik}IOa(snr4qX!x*YI*J3@UtqA$G-x~|YnDG$?J?aC z-7%Yx*)V!+E)hn@@NwqQ8$kXRi(BOUjdkeYoy)+gHIA?1RW@s^+GT~|Z|th!So~UN z^hr3dM$nJ9`A=)9I(_A@b-IiJj!U^b0B;3Pl{d#fQo_-&^{qe?r2VRl8hk0Bn%l#C z>AV$K3FmcAoSBiipJZAju7zx+5|YWmJe(^N#%A%C1YEr!@!sWSI6ilPBu!{b|(U$4sh!pMTCQHTuL&c$7vr^YecMplPhXE5gaA3$4!Z2Jl?YeKFQ5Q zYMJ(G(WLe-fzNZZ@qIeJ)2Q0VJzfX!;#5#$`T`C*9dR|aR5-$x0({`s1K}8rvN+S( zK?0}Tlx-AAF-9deFi0R*p^jl0RE-T0Sm)(%R8<1sRaB87iq)(lU`+varI#%w@MOha zi8`OxZ3KjhDrUg#uORU16p-7u5UlrPYN+XaiC-hIu|liuRP;!9SnVcIo=i+lD}Tb* z0X$qG?x&INsG>5!ah_a>fH;5p0|1?s0MI7mkrHts)ZlIRQ$1-* N+eLUji+?lq{{Tvw;w}IH literal 0 HcmV?d00001 diff --git a/COMMAND/BIN/GLOBAL.OBJ b/COMMAND/BIN/GLOBAL.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..7f8cc04465369998668af3eaf92af2fc0728d0fc GIT binary patch literal 978 zcmah|PiqrV5TDI%(j<+gN-3fE0i?*bN)f4|^dEY%rHLXXbbQ%;o2-4^UEaPlZ51i# zL3+xmhTNMhdQ&H3ijeVyf?r3w=?sbJ*q*~ZFN-K7RvR0p11(c z%KGY>v%1t=vX>i;((0ql^`{#}Y_2_T7FX7vG@3UXX@|lA0LDww7WC10_21?B)A9+>^Hf zDk!zi^b7o{Q92byJ9n}$VZ3fuz+KMBzFM05qwIpxJOH>g+yM|u1ZYkb4C1`YDtm=d z)^UvuanEF60-(xHOcp0h z*Xs(s1@L?5g1rSTxCe9Ky0E|4nstdbsKW-`4p6QCoX?*o;dFY+DxB8&nxX5};9E9~ zr0;Xq7Jnk`ht#Xk+Zng9@niD>U;$5H^AkN@qSOuF*+4(-GQ@2+y7Ly4IRV@7X0KW#;>DL)2h40GJz{MB3R==q|OX>h72YK7G}oxvsf6I{xc@@xH0g>r{omJ zr>B<0mn0_Tq%v@V`I&i{B@Db^W=>*WdTC;MDgzgo3sJ=zU!0kjo|6jI#IS&kfsp|S UBImF%9AOY+WUcFBVqho%0H!M^0RR91 literal 0 HcmV?d00001 diff --git a/COMMAND/BIN/MESSAGE.OBJ b/COMMAND/BIN/MESSAGE.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..9d4ca7c0abdb040e19ce1ebdc06a29777b5bcb0f GIT binary patch literal 7846 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 literal 0 HcmV?d00001 diff --git a/COMMAND/BIN/PRINTF.OBJ b/COMMAND/BIN/PRINTF.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..a77fd532b9e42e54b68efbb50697b22a97fd0f18 GIT binary patch literal 2511 zcmaJ@YitzP6+ZLWryVa~aGHuoq?Ann+g&#Va6tiVbBjuAy8#c6hFQ6ejU1VR)-wjR z)NHe++PmX*@}sJf$cl(iUq6ycRYOhb1Jqdd}<; zyMOv)zI*20d(J)IH}{@9;d1cSzI-y&{avlAw&V9dsRfW5TblOBO}h{5mKyf&cQ$?P zrIxl|dU=go*^wZ@sZ)#`I+TtX!2-z*}6*2iH8N<|nf#Bx|1Mj2L2a5Q|H~g5eD_H!Xn1nmnS+rHMyNdQ@ zfYXCsaFN(2wGil}^dA6qM(vicFNuKq##uSa?9F`BW}mjFq0Bj+(pD%WGzmc8p(yV| zA(!1}VLVdQU@`_8c|;nzF^V(evZG8NEvg@xK9pt?i|!&%apk_DdgIL>WqPF{cHbW> zXW@C!UJcK$*H5I_MM$$*0aC2+beiR?vphGL=ooHL)N@hKx+d;}{7VrWRv3Mg zW0S^_kGSgPDK?bw$K)L~x)T!vU^@c3jM)YJ;T;?GDx_kpal#8?6VyI_P0gSW4 zV7dPdl6xHFHTt?Qh>v6S=ngyxrdW4{C(d2bWSSPeR()vOEv>1#92aP8M6;rLIpXux z5@LH7Tu8G#ZU|yrW_xos zje5~)+TQ9it)p;FTUPDUzFxS7*2-#0TWfY0Y{5|SarI*6gk-KMz0DGbSrI!=OQ!Gh zDVGjHrc&Z8V{TvU+Y08C)i;e>k&i`^B2Uy^G0|z)&{ck281;vDf_~4eiZxHi)epFu ziTdK~;wF|E{D+}rwzFKngi=QOXF>a-q0U&%GxekW%aVB1Ej-mRwcwAgF(=b(3Ps<_ zuVXl`UY=ZA9QLPNPZ(%(b>9hGHj~I4fmCkCr6zw0RdR zrcnjZ5T5ty-IUkR6^`$e<&ufsNPqbwUCM5@y>SpvYdb1|Mh|gt6LM^QTm;NJ=4QL^^zac#ZYDD=!wGQbGcoK+C8qmU3*eBl#r~M19#`&ewg2M-Vg*;(ASD=D+RNXPNz;qY@NX3z>@$=`VPD zml=J9_>tMn1|a|4X0mS1tmOB`?nr8$?~FCf1}4VN4DW*^5F-bH2Vua61ievoQU;(HxbwCE~78cWqyJ_jr3x RPq5>}E1f}z#zg!Z`7f-Es4f5i literal 0 HcmV?d00001 diff --git a/COMMAND/BIN/RESIDENT.OBJ b/COMMAND/BIN/RESIDENT.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..029f9e62697b2d7d3c99ba53da94f9c9c1a82516 GIT binary patch literal 1344 zcmZXSJ7^R^7{|X&F2>|?@rk7jvW10cUdAVe&Aqaay9;}#!D`vu&LzuTcF)ON^g6*# z1h-HTwNQj$p~Ob8v=h-n`11H@8V zN!yXi8in&SJ*E)f?)Jjegc9pg*6zii`>$d?OezY%EOR&|b>?we=7cilF;zcS2&25m z38R+X40X!lRu~p3t%l*GWs^l}I~L*1I#r7}$z#OD-ip_7ZFPn@E~kum4NklYsati* z)QnT3q_|*VZk{APw^DP;T+JjW3Ag4jMXxMajU`TPHPNpIOJJc&F5|vIU^8c#5|!9= z*(qb7soI>!xN4|Jh(S4Psyascyz4QlW-!cHPE92f1m`6!S8P}FaB;psNk!}eiGJN( zqKuQW$C!8x+gYj-%e6_7Gp9;1Y?3N%0?B(MM;ATTgs=V{P?UacvS5_Vl0OooyH!{=&xF5-38(=k( zBR2uAwOU8F;3V6h4?E~l9tSjXhF(8NOIT9vKAaC8vtsGM)Mk=+Oz+tD_{vNpC) z{e6gK!0d$kDO{z4Zd@`FFCy@MkEG!H+E3u19U>b5KHa7T;e4AGhz~{Wg7N!E3dk=a zDJVaQq`>?jl7jP%@LG8Ef6$xZ1v*Hthwm1lE`+!5Wc_HHD_~#R<_g-+!hSY5N_ z0l!(?diVCN=Bh25Yqy$3K4}s$>wVHnw?V`llSvuXLnp%02ke(%u7bLmI{xzBgs zOteWdZ<6e4VU7QOKU19yO^s@<@uM>^IZxNAdNi^R$RGLrN3iL6dAQd%rf+Ik*uRXF z=}b`8pm>V~L#m1ylsG>2qx^HRU`%}v1J5uaHNcEh`_>Q%g~8@{RBUW+32_)iBDy{j z3`iky6Ol_>6W<@#mK-JW^!Ugk#uH&Nh<0y8Z>2;?`)&&bwN~1l(AvgWv)0A~650vW zIdOW7qyAg!^5xv;{awDSpLO}hc{Sz-&^lX%@`VSj^*g??b0|k9!7daEQ-zsAZKavo zZjpz6|6ytFr{@XCt8;iYgI7~{<>Hl%S4LDjhcw`}0lAI~j$YrDJZ9akSLD`gmv016 z`o_9^U&yB*5qY@dP9lRexyv`2emv(Nn3q3{>4!x3NalMam%1|7nq|4xv1I>FQl@dV zX93(>whGD;lw~L@P;NshLs^ef#Z1aQ%&gqUEJ_WtD%+S%sbh8}z#OSoR-pVnr1S*J zQBLgNKf*VjQ3nS};uI4r?F zP)^5}P}(pCN`sE z)F@dy(*X5AuFHxhk;9_$W5zQd@lScUGu`|3)57mMUy)DWTPeW1bf(q9q_-|%J#HlT zC#qHZmp50H^itwShtDL88E-Z@PH0zWHNp#WnH5=2Z^HP?<{{69n8~xF)#yGyF6FFlq^Y4$s7GnhM=6JBVsaX<+}lw+&?NnM{Q`4xxR~P=gc-($gG^&kZrbCtu9` zd0Z1U#C)!M4(H_hp7XosBo7KDvBf!4_q3e3%PODkw06(A-dCOYGGk_jJk&V@t4x{q zv$`)G#(5=k(qm6pz*y$MI5+_tlaro931{+vupZ+E$^^&D1~cM#jeJr*omO&KVG>TN zm*vwt@;*R5rT=lcoK@#_nXVmgyniymh>KDYHVOJM30@Mo+|KQ`=^<&cYUlf= zKh1WU_(0+vbt(?y&<5Y082n5g5i?iEbjLMuXgAg^y5Z2*Xr57BHw@?Lo>O1M`ogbH ze4-wmutvW;EdNoiAM5sw-DcaMzM|Nt#a@JLSuAucY2Gv8#SMqfafykt~GG zJQWFB??z$Ci0oU|KZ{ZXG;ReFcc6sWl+^cGk@75?`mMfsK&9Z}KvaxJ0}XK8CrnfT zWMD@e1o2Z7)o~1#nX{S(`~mRGqd04K>zJ`MJ8YuN2V=Et8-#QA6maVHa^BO?ad1%3 z?M+tVEIF&1*1OB|)AwUq`kMYBpXxRpchJ?pcKppPoRU3Q{Wk1IHIxmC^*e`{=8FA( zP4@EZ>DR}5ec4_%nwDWQNOS=HtnSuPuAP_HwPz20+U?7(^Nk(+Shnh5*ALaoLv7rD zxY(3N&41XDPU%j=XC_C(?oh)XF`U>d9yOD-Io{UX5)?l&)6+f0x=!qli7=9ATToMp z;v<73q~SnGawWY>C0o+#l_0E7`G`4xa)=D_<>E7y4XQKKD>)wj-8I8~1wmdj>%?EM zl#5m#N}u7Z%!M^vwI$DyH4^(B{&C5(AD5#`bGZt`MTs24oE%y zG#{DN(LP2}b<(qxdn0e6GUv-4YR`61{I&imq^#uu$-{~j#-<{kPy5flRZs;doCZ&` zG$(4a5dWUA2GMOH7ogJ?@Gvj#v{0gF2BOWbSSYZE$8oZ?M8ZwqgjG@I$jc=B*fP7z z)X6Qg8f@!&YKP%;nsJ(H`LZwRtw=o8(VjK59z|q*kRSZJTZYY~oit_#T*skfQ1^?O zSK+Ubta4pDr7rl2?oUc`)bcPGdk+Yj!oHO`&h=AEs0xvW)?b3V{W%Owx(oX~lY{rq zaxGnj;UDDSjQ`l{yOg)ZD7PF3EXB*Fr|xDmQuXM^+0@kYY|65}nSjgO7?on;MGM(t zp{S-fw^-@<9y`xBJl0!gnoVd^re2L3m`R`69- zXWDasljlSOTD;RTn{#FF)~T2V8r*$G9>KyWv#JK&Q_#*8Rk{`a`S)V<8WdS#y zqip8ueFb3Iv>#sLV=E2yti>gTe}p6GGzMaT0-e3_CNUC*!Nl_y7%kj{!rX?mxyDBN z&5@T#m}8R`!3KEHm507_61uUN2jQ;ztUI@MNH?YV?m_it=)nKC=v_B=s2Sx8T{F@} zU&5;nC%u*Me$_&nzLbagzX$HqDCqIsf(`keJiJ2Q7v(S0PkzY_P#+gAre7V^ZC8um zC13s@6pH(+NininDJ%P$ax2>9XdBsV<(oWt3nO`pu{o)IXurj7N+r?up*+rRQl4Tr zE5G22eu;r!vpJXhTmaP)3G?i&$wsX`724&aNsR9gOM!hrEtCfmDPXLnv9YCzr_8aK z*w_+i(l09e#I{&7E-IZzo*?0z?JN8-&fkn{{5_WE&x{P@{ZY8k%-f>?(2@rlk~oDR zg4|`hQ5*K>^}~><)&@A9nIDYQ-fyY#^BV~Fdj_sZx->f!ixv6s+?#KjGkfOr$%QTw z`d9N1{$1|Y+ckM2YwjSYrr_a_)E0^DA(!@r>rN;Z z4z$ouxhH6{e`tTt{MoX@AZBiha=jBEDXkfj&ZAbo|XKpuLvq(3n9_vf%~AH{=H`k z98WM9YiS}&q!Hxv6&T(#azi-6EH;U~`qY*n#{$4@W)vjrslw2W{?|1#f|zM$(cO z{;bg??g|7WQHf043xD9?XS~>ZASbtvmE~R#h;x!YeifOlCx8pv!>u;l)7Ighwz~7A z`%1TO1e)2qRRA2*mib0HPXN%ff3ov?F_HUKbr2-vH#^!#NwUc2)MM((!?}c|yM1if zTypqT>DzoJk;E$sa)Kk=H&47qS#)JTj*QMwc1Av}XUanp7`Zt{WAgj*=4|?R$eQ8N zHuc{`iojN-%2{#hUN%KJz*Z?qc6%xXb?IjFUePrLt`!+gTuc^Fd(R3g7K38EB@o{& z#-%_k7?F6RXL@-0nQ*9$&9S&dm0XFwS71=Z^cI8`p3oJ@r*ZiOubC!7&ah$>2dVG% zo%RnDlb>N6?yvIGT*5ezg~~j#9Nf>X%;qF><#;YJ4Vex}TY%M1kkROL)b;5{$GH=3 z&0X<*G)Zz{_OWZThjUU1r_NtPbmAad2%@j)M6uH#+;~Nfduqh?Ll;trYQ5h+kSlvP zZ5bUXp}PKgq)cLWq^7dfsby@9vK{@MY_-ygc0a~C*_u?}6ev>x#|a*@IWCD_JRbJk zhSUzPkNd<(G!&jdrlBPg4^4bDM;fFSvIHaib%NSBT-%*~zJ1<*93E_U>Rki3JY@Bd zt2NW`IX`cH;;Ez_?bFDW&ueC%5Jrv*n*0(RGdzA`9~Vfxft1XVFka|iObF|1 z@qAMOxYnf@D}qm&ib%d%>Ek|#zsvlXd7kN856mohe+adTk2uK{z$H37p<7Ql$r+7B z_C_TD8fp;Va#A6Tt~r8OAhtAzL!#iKdwYuVK?75KkiKz5Bw?B>GmOJ<*YOfsZ^8n5 z1OG|S{KUN8I)QsDxUBh-gC|T?>E6%P3%%O}%>vZ|cFm%2_b5A)?tq5EMM;enEN?+vuH;4M6ex8BY!98LNkP;VfJ literal 0 HcmV?d00001 diff --git a/COMMAND/BIN/TXHELP.BIN b/COMMAND/BIN/TXHELP.BIN new file mode 100644 index 0000000000000000000000000000000000000000..d220bcd3759cc79320d589e054262ed82bccfe04 GIT binary patch literal 11733 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 NFNzhc--LXI{{v3c<>CMU literal 0 HcmV?d00001 diff --git a/COMMAND/CHAR.DEF b/COMMAND/CHAR.DEF new file mode 100644 index 0000000..82723db --- /dev/null +++ b/COMMAND/CHAR.DEF @@ -0,0 +1,74 @@ +; File : $CHAR.DEF$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +;************************************************; +;* *; +;* Character Definitions *; +;* *; +;************************************************; + +CTLA equ 'A' - '@' +CTLB equ 'B' - '@' +CTLC equ 'C' - '@' +CTLD equ 'D' - '@' +CTLE equ 'E' - '@' +CTLF equ 'F' - '@' +CTLG equ 'G' - '@' +BELL equ 'G' - '@' +CTLH equ 'H' - '@' +CTLI equ 'I' - '@' +TAB equ 'I' - '@' +CTLJ equ 'J' - '@' +LF equ 'J' - '@' +CTLK equ 'K' - '@' +CTLM equ 'M' - '@' +CR equ 'M' - '@' +CTLP equ 'P' - '@' +CTLQ equ 'Q' - '@' +CTLR equ 'R' - '@' +CTLS equ 'S' - '@' +CTLT equ 'T' - '@' +CTLU equ 'U' - '@' +CTLV equ 'V' - '@' +CTLW equ 'W' - '@' +CTLX equ 'X' - '@' +CTLY equ 'Y' - '@' +CTLZ equ 'Z' - '@' +ESC equ '[' - '@' +CTLBS equ '\' - '@' +CTLUB equ '_' - '@' +CTLUP equ '^' - '@' +DEL equ 07Fh +RUBOUT equ DEL + +CTL equ '^' diff --git a/COMMAND/CMDLIST.C b/COMMAND/CMDLIST.C new file mode 100644 index 0000000..4677adf --- /dev/null +++ b/COMMAND/CMDLIST.C @@ -0,0 +1,212 @@ +/* +; File : $Workfile: CMDLIST.C$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; CMDLIST.C 1.18 94/08/09 15:47:05 +; Fixed TRUENAME help. +; CMDLIST.C 1.16 94/06/28 15:42:23 +; Add TRUENAME support +; CMDLIST.C 1.15 93/12/01 00:17:11 +; Tidy up, commands alphabetical for benefit of help screen +; CMDLIST.C 1.14 93/10/28 17:08:05 +; ifdef'd out 'more' , since it now external +; see cmd_list[]. +; CMDLIST.C 1.12 93/04/22 14:50:45 +; GOSUB, RETURN and SWITCH now have help. +; CMDLIST.C 1.11 93/01/21 16:15:03 +; CMDLIST.C 1.7 92/08/06 09:52:44 +; Added novell_ext_list which is used to expand novell system information +; statements. See BATCH.C for more info. +; ENDLOG +*/ + +/* +* 3 Oct 90 remove 8087 command +* 5 Oct 90 remove logout and lock command +* 23 Oct 90 support AND, OR, INPUT, INPUTC, +BATCH +* 23 Nov 90 add ECHOERR command +*/ + +#include "defines.h" +#include +#include "command.h" /* Command Definitions */ +#include "txhelp.h" + +/*.pa + * CMD_LIST maps command names to routines as well as specifying + * the top level of syntax checking. If a command requires parameters + * then the message field must point to the error message to be + * displayed if no parmeters are given. + */ +EXTERN VOID CDECL cmd_break(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_call(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_cd(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_copy(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_ctty(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_chcp(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_idle(BYTE *, BYTE *); /*#NOIDLE#*/ +EXTERN VOID CDECL cmd_hiload(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_date(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_del(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_dir(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_delq(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_md(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_more(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_path(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_prompt(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_ren(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_rd(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_time(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_truename(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_type(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_ver(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_verify(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_vol(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_cls(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_echo(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_echoerr(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_exit(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_for(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_goto(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_gosub(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_return(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_switch(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_if(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_pause(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_pauseerr(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_rem(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_set(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_shift(BYTE *, BYTE *); +EXTERN VOID CDECL cmd_or(BYTE *, BYTE *); + +GLOBAL S_CMD cmd_list[] = +{ +/* +TO DO: MAKE DUAL LANG AWARE +*/ +#if !defined(NOXBATCH) + { "and", cmd_if, PARAM_IFCONTEXT,DLS_help_and }, +#endif /*NOXBATCH*/ + { "break", cmd_break, PARAM_NONE, DLS_help_break }, + { "call", cmd_call, PARAM_NEEDFILE, DLS_help_call }, + { "cd", cmd_cd, PARAM_NONE, DLS_help_chdir }, + { "chcp", cmd_chcp, PARAM_NONE, DLS_help_chcp }, + { "chdir", cmd_cd, PARAM_NONE, DLS_help_chdir }, + { "cls", cmd_cls, PARAM_NONE, DLS_help_cls }, + { "copy", cmd_copy, PARAM_NEEDFILE, DLS_help_copy }, + { "ctty", cmd_ctty, PARAM_NEEDDEV, DLS_help_ctty }, + { "date", cmd_date, PARAM_NONE, DLS_help_date }, + { "del", cmd_del, PARAM_NEEDFILE, DLS_help_del }, + { "delq", cmd_delq, PARAM_NEEDFILE, DLS_help_delq }, + { "dir", cmd_dir, PARAM_NONE, DLS_help_dir }, + { "echo", cmd_echo, PARAM_NONE, DLS_help_echo }, + { "era", cmd_del, PARAM_NEEDFILE, DLS_help_erase }, + { "eraq", cmd_delq, PARAM_NEEDFILE, DLS_help_eraq }, + { "erase", cmd_del, PARAM_NEEDFILE, DLS_help_erase }, + { "exit", cmd_exit, PARAM_NONE, DLS_help_exit }, + { "for", cmd_for, PARAM_SYNTAX, DLS_help_for }, + { "gosub", cmd_gosub, PARAM_SYNTAX, DLS_help_gosubreturn}, + { "goto", cmd_goto, PARAM_SYNTAX, DLS_help_goto }, + { "hiload", cmd_hiload, PARAM_NONE, DLS_help_hiload }, + { "idle", cmd_idle, PARAM_NONE, DLS_help_idle }, + { "if", cmd_if, PARAM_SYNTAX, DLS_help_if }, + { "lh", cmd_hiload, PARAM_NONE, DLS_help_hiload }, + { "loadhigh", cmd_hiload, PARAM_NONE, DLS_help_hiload }, + { "md", cmd_md, PARAM_NEEDPATH, DLS_help_mkdir }, + { "mkdir", cmd_md, PARAM_NEEDPATH, DLS_help_mkdir }, +#if !defined(NOXBATCH) + { "or", cmd_or, PARAM_IFCONTEXT,DLS_help_or }, +#endif /*NOXBATCH*/ + { "path", cmd_path, PARAM_NONE, DLS_help_path }, + { "pause", cmd_pause, PARAM_NONE, DLS_help_pause }, + { "prompt", cmd_prompt, PARAM_NONE, DLS_help_prompt }, + { "rd", cmd_rd, PARAM_NEEDPATH, DLS_help_rmdir }, + { "rem", cmd_rem, PARAM_NONE, DLS_help_rem }, + { "ren", cmd_ren, PARAM_NEEDFILE, DLS_help_rename }, + { "rename", cmd_ren, PARAM_NEEDFILE, DLS_help_rename }, + { "return", cmd_return, PARAM_NONE, DLS_help_gosubreturn}, + { "rmdir", cmd_rd, PARAM_NEEDPATH, DLS_help_rmdir }, + { "set", cmd_set, PARAM_NONE, DLS_help_set }, + { "shift", cmd_shift, PARAM_NONE, DLS_help_shift }, +#if SWITCH_ENABLED + { "switch", cmd_switch, PARAM_SYNTAX, DLS_help_switch }, +#endif + { "time", cmd_time, PARAM_NONE, DLS_help_time }, + { "truename", cmd_truename, PARAM_NONE, DLS_help_truename}, + { "type", cmd_type, PARAM_NEEDFILE, DLS_help_type }, + { "ver", cmd_ver, PARAM_NONE, DLS_help_ver }, + { "verify", cmd_verify, PARAM_NONE, DLS_help_verify }, + { "vol", cmd_vol, PARAM_NONE, DLS_help_vol }, + + { NULL, NULL, PARAM_NONE } +}; + + +EXTERN VOID CDECL get_login_name(BYTE *); +EXTERN VOID CDECL get_pstation(BYTE *); +EXTERN VOID CDECL get_full_name(BYTE *); +EXTERN VOID CDECL get_hour(BYTE *); +EXTERN VOID CDECL get_hour24(BYTE *); +EXTERN VOID CDECL get_minute(BYTE *); +EXTERN VOID CDECL get_second(BYTE *); +EXTERN VOID CDECL get_am_pm(BYTE *); +EXTERN VOID CDECL get_greeting(BYTE *); +EXTERN VOID CDECL get_year(BYTE *); +EXTERN VOID CDECL get_short_year(BYTE *); +EXTERN VOID CDECL get_month(BYTE *); +EXTERN VOID CDECL get_month_name(BYTE *); +EXTERN VOID CDECL get_day(BYTE *); +EXTERN VOID CDECL get_day_of_week(BYTE *); +EXTERN VOID CDECL get_nday_of_week(BYTE *); +EXTERN VOID CDECL get_os_version(BYTE *); +EXTERN VOID CDECL get_connection(BYTE *); + +GLOBAL N_CMD novell_ext_list[] = { + { "LOGIN_NAME", get_login_name }, + { "P_STATION", get_pstation }, + { "FULL_NAME", get_full_name }, + { "HOUR", get_hour }, + { "HOUR24", get_hour24 }, + { "MINUTE", get_minute }, + { "SECOND", get_second }, + { "AM_PM", get_am_pm }, + { "GREETING_TIME", get_greeting }, + { "YEAR", get_year }, + { "SHORT_YEAR", get_short_year }, + { "MONTH", get_month }, + { "MONTH_NAME", get_month_name }, + { "DAY", get_day }, + { "DAY_OF_WEEK",get_day_of_week }, + { "NDAY_OF_WEEK",get_nday_of_week}, + { "OS_VERSION", get_os_version }, + { "STATION", get_connection }, + { NULL, NULL } +}; diff --git a/COMMAND/COM.C b/COMMAND/COM.C new file mode 100644 index 0000000..07af700 --- /dev/null +++ b/COMMAND/COM.C @@ -0,0 +1,1833 @@ +/* File : $Workfile: COM.C$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ + * COM.C 1.2 97/03/21 14:41:21 + * Added /n option to disable critical error handler + * COM.C 1.59 94/12/01 10:05:21 + * Removed closing handles 5 and 6 in error_code() in order to be able + * to continue with a batch file if the user wants to. JBEULICH + * Enabled UNC filenames + * COM.C 1.58 94/08/10 14:49:22 + * After first run through looking for a file to execute, now strips the D: + * off the path, if only a drive and not a directory is specified. So, if you + * type D:TEST, it will look for TEST on the current directory of drive D:, then + * continue to search the path. It will only skip searching the path if a + * specific directory is specified. + * COM.C 1.57 94/03/29 16:12:11 + * docmd_int2f in CSTART.ASM returns 1 if it has been accepted. + * In this case, we don't want it, so docmd_offer returns TRUE. + * All cases of docmd_offer return if TRUE, so we don't process + * the line ourselves. + * COM.C 1.56 94/02/08 11:50:17 + * Fixed a problem where typing COMMAND DIR A: after giving the correct error + * message for DIR being an incorrect loadpath, tries to access A: and crashes + * under /MULTI. + * Break added after error message to fix crashing problem. + * Variable lferror added so that after an incorrect loadpath, it does not use + * the next bit (ie. A:) as keyboard input. + * COM.C 1.54 93/12/09 18:07:04 + * Fixed a bug which screwed the upper memory link if you entered c:lh dir + * COM.C 1.53 93/12/01 23:14:02 + * Fix parsing bug "outfile command" would fail + * COM.C 1.49 93/12/01 11:32:08 + * Now do a flush cache call before displaying prompt. + * COM.C 1.48 93/12/01 00:17:17 + * docmd_offer() will do an int 2F/AE (2 if external) within batch files + * SPR: 811218, shouldn't access drive whatever the prompt + * COM.C 1.45 93/11/19 21:08:14 + * Put code to report "Syntax Error" for "| command" and "command |" back to + * it's original state. + * COM.C 1.43 93/11/08 23:59:19 + * F8 key now only affects autoexec, not 1st batch file + * COM.C 1.42 93/11/05 13:03:00 + * Fix problem with /P /MH (missing break;....) + * COM.C 1.41 93/11/05 00:44:07 + * /MU option only valid with /P option. The problem is if you "exit" with upper + * memory unlinked the resident portion isn't freed, and you eat upper memory. + * COM.C 1.40 93/10/29 17:05:51 + * Add PROMPT=$P$G and PATH=d:\NWDOS to default env + * COM.C 1.39 93/10/22 11:51:30 + * Changed Beta string from 3 to 4 + * COM.C 1.36 93/09/15 18:56:39 + * FOR command now allows any char in brackets. eg for %%v in (+ -) do... + * COM.C 1.34 93/08/26 09:39:05 + * Now use PSP for stack during func 4b exec. There's some debug + * code in case things screw up. + * COM.C 1.30 93/07/05 08:32:57 + * Memory allocation strategy now restored if ctrl-c pressed during a hiload. + * COM.C 1.25 93/05/24 11:34:43 + * psp now points to itself when /P isn't specified. + * COM.C 1.24 93/05/17 11:22:28 + * Added support for F5 and F8 being pressed during boot-up. + * COM.C 1.23 93/04/22 14:51:10 + * Now close handles 5-19 after an exec. + * echoflg is now correctly preserved when batch files are chained. See + * echoflg_save2. + * COM.C 1.19 93/01/21 14:29:44 + * Now do INT 21 ah=29 when changing default drive. + * COM.C 1.16 92/11/25 09:30:15 + * Password support enabled/disabled by #if defined(PASSWORD) statements. + * HOMEDIR support disabled. + * COM.C 1.12 92/09/25 19:48:56 + * Removed .cmd from search order if DOSPLUS defined. + * Fixed bug when ;; appears in path. + * COM.C 1.11 92/09/17 11:30:14 + * Piping a batch file through MORE no longer stops with Syntax Error + * displayed. + * COM.C 1.10 92/09/11 10:43:41 + * COMMAND /P: disables time and date prompt and copyright message. + * COMMAND ? no longer hangs. + * ENDLOG + */ + +#include "defines.h" + +#if 0 +#if defined(DLS) +#define MSG_VER 111 /* required message file version No. */ +#else +#define MSG_VER msg_ver111 /* required message file version No. */ +extern char *MSG_VER; +#endif +#endif + + +#include +#include + +#if defined(MWC) && defined(strlen) +#undef strcmp /* These are defined as macros in string.h */ +#undef strcpy /* which are expaneded in line under */ +#undef strlen /* Metaware C. These undefs avoid this. */ +#endif + +#include +#include +#if !defined(DOSPLUS) +#include +#include +#endif + +#include "command.h" /* Command Definitions */ +#include "support.h" /* Support routines */ +#include "dos.h" /* MSDOS function definitions */ +#include "dosif.h" /* DOS interface definitions */ +#include "toupper.h" +#include "global.h" /* Global Variables */ + +/* RG-00- */ +#define PATH_LEN 65 /* max path length (null terminated) */ +#if !defined(NOSECURITY) && (defined(CDOSTMP) || defined(CDOS)) +#include +#include "security.h" +#include "login.h" +#endif +/* RG-00- end */ + +MLOCAL BYTE valid_sepchar[] = ":.;,=+"; + + +#if defined(DOSPLUS) /* we now define initial */ +MLOCAL BYTE PATH_DIR[] = "A:\\OPENDOS"; +MLOCAL BYTE SET_PATH[] = "PATH=%s"; +MLOCAL BYTE SET_PROMPT[] = "PROMPT=$P$G"; +MLOCAL BYTE SET_OS[] = "OS=OPENDOS"; /* environment in COMMAND */ +MLOCAL BYTE SET_VER[] = "VER=7"; /* not in BIOSINIT */ +#if !defined(FINAL) +MLOCAL BYTE SET_BETA[] = "BETA=Beta 4"; +#endif +#endif + +GLOBAL jmp_buf break_env; + +#if defined(DOSPLUS) +EXTERN UWORD _psp; +EXTERN VOID *batchptr_off; +EXTERN VOID *batchflg_off; +EXTERN VOID *echoflg_off; +EXTERN UWORD FAR *batch_seg_ptr; +#endif + +/*RG-03*/ +EXTERN BOOLEAN if_context; /* BATCH.C */ +/*RG-03-end*/ + + +#if defined(DOSPLUS) +EXTERN VOID CDECL show_help(WORD); /* CSTART.ASM */ +EXTERN VOID CDECL put_resident_high(WORD); /* CSTART.ASM */ +EXTERN BYTE FAR * CDECL get_config_env(VOID); /* CTSART.ASM */ +EXTERN UWORD CDECL get_original_envsize(VOID); +EXTERN VOID CDECL copy_crit_msgs(VOID); /* CSUP.ASM */ +EXTERN VOID CDECL copy_rld_msgs(VOID); /* CSUP.ASM */ +EXTERN WORD CDECL dos_parse_filename(BYTE *); +EXTERN UWORD CDECL docmd_int2f(BYTE *, BYTE *, UWORD); +#endif +EXTERN void CDECL flush_cache(void); + +EXTERN BYTE *kbdptr; +EXTERN BYTE msg_patheq[]; /* Static Environ String "PATH=" */ +EXTERN S_CMD cmd_list[]; /* CMDLIST.C */ + +#if defined(DOSPLUS) +EXTERN VOID inherit_parent_state(); +#endif + +EXTERN WORD echoflg_save2; +EXTERN VOID batch_start(BYTE *, BYTE *, BYTE *); +EXTERN VOID batch_end(VOID); /* BATCH.C */ +EXTERN VOID batch_endall(VOID); /* BATCH.C */ +EXTERN VOID batch_close(VOID); /* BATCH.C */ +EXTERN VOID for_end(VOID); /* BATCH.C */ +EXTERN BOOLEAN getcmd(BYTE *); /* BATCH.C */ +#if !defined(CDOSTMP) +EXTERN VOID int2e_start(); /* BATCH.C */ +EXTERN VOID int2e_finish(); /* BATCH.C */ +#endif + +EXTERN VOID CDECL cmd_cd(BYTE *); /* COMINT.C */ +EXTERN VOID CDECL cmd_ver(); /* COMINT.C */ +EXTERN VOID CDECL cmd_set(BYTE *); /* COMINT.C */ + +GLOBAL VOID docmd(BYTE *, BOOLEAN); /* COM.C */ +MLOCAL VOID cmd_loop (BYTE *); /* COM.C */ +MLOCAL VOID error_code(UWORD); /* COM.C */ + +MLOCAL VOID cmd_cleantp(VOID); /* COM.C */ +GLOBAL BOOLEAN parse(BYTE *); /* COM.C */ +MLOCAL VOID init(BYTE *); /* COM.C */ +MLOCAL BOOLEAN doexec(BYTE *, BYTE *, UWORD, BYTE *); + +#if !defined(CDOSTMP) +MLOCAL BYTE msg_comspec[] = "COMSPEC="; +/*EXTERN BYTE *reload_file; CSTART.ASM */ + +EXTERN VOID CDECL get_reload_file(VOID); /* CSUP.ASM */ +EXTERN VOID CDECL set_reload_file(VOID); /* CSUP.ASM */ +EXTERN VOID CDECL get_out_pipe(VOID); /* CSUP.ASM */ + +EXTERN VOID CDECL install_perm(VOID); /* CSTART.ASM */ +EXTERN VOID CDECL master_env(UWORD); /* CSTART.ASM */ +GLOBAL WORD CDECL findfile(BYTE *, UWORD *); /* COM.C for MS-DOS */ +MLOCAL WORD checkfile(BYTE *, UWORD *, BYTE *, BYTE *, BYTE *, BYTE *); +EXTERN BYTE cbreak_ok; /* control break handler initialised */ +#else +EXTERN WORD CDECL findfile(BYTE *, UWORD *); /* DOSIF.A86 (P_PATH) */ +EXTERN VOID network_init(VOID); /* NETWORK.C */ +EXTERN PD FAR * CDECL pd; /* Far pointer to Current PD */ +MLOCAL BOOLEAN system_init = TRUE; +#endif +EXTERN BYTE FAR * CDECL farptr(BYTE *); +EXTERN BYTE FAR * CDECL cgroupptr(BYTE *); + +#if defined(CPM) +EXTERN UWORD CDECL cpm_init(VOID); /* CP/M Init Routine */ +#endif + +#if !defined(NOSECURITY) && (defined(CDOSTMP) || defined(CDOS)) +/* global VC data */ +UWORD vc_base; /* first vc number for this station */ +UWORD num_of_vcs; /* number of vcs on this station */ +#endif + +#if !defined(CDOSTMP) +BYTE autoexec_name[13] = "autoexec.bat"; +#endif + +#if defined(DOSPLUS) +UWORD boot_key_scan_code = 0; +#endif + +#if !defined(FINAL) +void save_psp(void); +void check_psp(void); +WORD psp_xsum; +#endif + +VOID FAR CDECL _main(cmd) +BYTE *cmd; +{ + BYTE cmd_buf[128]; + +#if defined(CDOSTMP) /* Insure the NETWORK_INIT */ + network_init(); /* function is called before */ +#endif /* any disk activity so that */ + /* Diskless DRNET systems can*/ + /* be generated. */ + +#if !defined(NOSECURITY) && (defined(CDOSTMP) || defined(CDOS)) + /* get the VC data and make global */ + vc_data(&vc_base, &num_of_vcs, &station); +#endif + +#if defined(DOSPLUS) && defined(DLS) + copy_crit_msgs(); + copy_rld_msgs(); +#endif + + init(cmd); /* Initialize COMMAND.??? */ + +#if defined(CPM) + if(cpm_init()) { /* If this is the CP/M Media */ + eprintf(MSG_SINGLECPM); /* Access program then call */ + ms_x_exit(1); /* the CPM_INIT function */ +} +#endif + + ms_drv_set(drive); /* try to set default drive */ + + FOREVER { + + error_code(setjmp(break_env)); /* Initialize Error Handler */ +#if !defined(CDOSTMP) + cbreak_ok = TRUE; /* we can handle break now */ +#endif +#if !defined(NOSECURITY) && (defined(CDOSTMP) || defined(CDOS)) +#if defined(CDOSTMP) + + ms_drv_set(drive); /* try to set default drive */ + + /* Ensure we are the foreground process on the Virtual Console */ + /* before displaying login prompt. */ + if(login_enabled()) { + disable_vc_switch(); /* stop user switching to another console */ + + /* if 1st time through on VC 0 then run system autoexec */ + if (system_init) { + login_save_initial_state(); + if (pd->P_CNS==0) { + /* log this event */ + logevent("",LOG_POWERON); + /* process system Autoexec.bat */ + while (*kbdptr || batchflg) + cmd_loop (cmd_buf); + } + system_init = FALSE; + } + if(waiting_on_login() && !background_proc()) + login_station(); /* login station */ + login_consoles(); /* initialise all VCs */ + enable_vc_switch(); + } +#endif + FOREVER { + error_code(setjmp(break_env)); /* Initialize Error Handler */ + + if (login_enabled()) { + if(!logged_in()) /* keep going until logged out */ + break; + } +#endif + cmd_loop (cmd_buf); + +#if !defined(NOSECURITY) && (defined(CDOSTMP) || defined(CDOS)) + } + if(login_enabled()) { + /* kill off any remaining batch processes still running */ + while (batchflg) + cmd_exit(""); +#if defined(CDOSTMP) + /* the logout event */ + if(!background_proc()) + logout(); +#else + return; /* CDOS.COM just dies when logout happens */ +#endif + } +#endif + } +} + +/*MLOCAL*/ VOID cmd_loop (cmd) +BYTE *cmd; +{ +WORD echoing; +REG BYTE *cmdline; +BYTE first_ch; + + cmd_cleanup(); /* Cleanup after the command */ + cmdline = cmd; + + if (!batchflg) flush_cache(); + echoing = getcmd(cmdline); /* do not echo Labels */ + + first_ch = *deblank(cmdline); + + if((pipe_out && !batchflg && !*deblank(kbdptr)) || + /* if "|" */ + (pipe_in && (first_ch == 0 || first_ch == ':'))) { + /* or "|" */ + eprintf(MSG_SYNTAX); /* report syntax error */ + pipe_out = NO; /* forget about pipes */ + pipe_in = NO; + if (!batchflg) + *kbdptr = '\0'; /* discard rest of line */ + crlfflg = YES; /* remember to do a LF */ + return; /* stop now before echo */ + } + + if(echoing && first_ch != ':') { + /* Echo command line if ECHO */ + puts(cmdline); /* ON and source not keyboard*/ + crlf(); /* and not a label */ + } + + crlfflg = NO; /* NO CR/LF req'd */ + cmdline = deblank(cmdline); /* remove leading spaces */ + + if(*cmdline && *cmdline != ':') /* Check for a command */ + { /* not a LABEL */ + + if (!strnicmp(cmdline,"IF",2)) docmd(cmdline,YES); + else { + if(!parse(cmdline)) { /* If the Parse succeeds then*/ + docmd(cmdline, YES); /* execute the command. */ + } + } + } +} + +/*.pa*/ +/* + * + */ +#define COMMAND_P (cflag & 1) /* Permanent Flag */ +#define COMMAND_C (cflag & 2) /* One Command Option */ +#define COMMAND_T (cflag & 4) /* CDOS TSR option */ + + +MLOCAL VOID init(cmd) +BYTE *cmd; +{ + UBYTE console = 1; /* Concurrent Console No. +1 */ + SYSDATE date; /* System Date Structure */ + WORD ret; /* General Variable */ + UWORD cflag; + BYTE *s; +#if defined(CDOSTMP) + UWORD vc_base, vc_num, pc_num; /* Virtual Console Data */ +#else + BYTE buf[MAX_ENVLEN], c; + UWORD envsize = 256; +#endif +#if defined(DOSPLUS) + BOOLEAN no_timedate = FALSE; + WORD prh_function = 0; + UWORD FAR *p_batch_seg; +#endif + BYTE lferror = 0; + strcpy(kbdptr, ""); /* start with no commands */ + +#if 0 +#if defined(DLS) + dls_msg_ver(MSG_VER); /* check message file version*/ +#else + s = MSG_VER; /* ensure label is referenced */ +#endif +#endif + +#if defined(CDOS) + ret = ioctl_ver(); + if(ret < 0x1450 || ret > 0x1499) { /* Get the CDOS BDOS Version */ + eprintf(MSG_BADOS); /* and quit if it is not 5.0 */ + ms_x_exit(-1); /* or Above */ + } +#endif + +#if defined(DOSPLUS) + + batchptr_off = (VOID *) &batch; + batchflg_off = (VOID *) &batchflg; + echoflg_off = (VOID *) &echoflg; + + envsize = get_original_envsize(); /* BAP - sets envsize to */ + /* same as original COMMAND */ + if ((envsize < 128) || (envsize > 32752)) envsize = 256; /* shouldn't really need this */ + + parent_psp = MK_FP(_psp, 0x16); /* our parental PSP is here */ + ret = ioctl_ver(); /* Get the BDOS Version No. */ + + if(ret < 0x1071) { /* Abort if this is not DOS */ + eprintf(MSG_BADOS); /* PLUS with a BDOS version */ + if ((*parent_psp) && (*parent_psp != _psp)) + ms_x_exit(-1); /* abort unless root process */ + while(1){}; + } + +#if 0 +#if defined(DLS) + dls_msg_crit(); /* init crit error messages */ +#endif +#endif + +#endif + +#if defined(CDOSTMP) + console = (UBYTE) bdos(C_GET, 0) + 1; /* CDOS Console No. + 1 */ + execed = NO; /* COMMAND.RSP not EXECED */ + err_ret = 0; /* Initial Error Code 0000 */ + +#else + execed = YES; /* Assume we have been loaded*/ + /* from the command line */ + break_flag = ms_set_break(NO); /* Get the Current Break Flag*/ + err_ret = ms_x_wait(); /* Get the completion code */ + /* for process's that cause */ + /* COMMAND.COM to be reloaded*/ + + init_switchar(); /* initialise switchar and */ + /* pathchar */ +#endif + + drive = ms_drv_get(); /* get default drive. */ + country.code = ms_s_country(&country); /* Initialise the Country data*/ + in_handle = psp_poke(STDIN, 0xFF); /* Get the standard input */ + psp_poke(STDIN, in_handle); /* and save internally */ + + out_handle = psp_poke(STDOUT, 0xFF); /* Get the standard Output */ + psp_poke(STDOUT, out_handle); /* and save internally */ + + for(ret=5;ret<20;ms_x_close(ret++)); /* close handles 5-20 */ + + if(initflg) /* is this a warm boot? */ + return; /* Yes then QUIT */ + + initflg = YES; /* there's only one 1st time */ + cflag = 0; /* Clear the switch variable */ + +#if !defined(CDOSTMP) + /* + * + * COMMAND.COM + * The following command line formats must be supported for + * applications that exec the command processor. + * + * COMMAND /CCOPY filex filey FrameWork Install + * COMMAND /C DIR *.* /P Procomm directory option + * COMMAND /C=DIR *.* + * + * These varients prevent support for multiple options and + * force the option scanning to be halted at the first command + * + * COMMAND /T - TSR support for CDOS + * + * We are auto-invoking COMMAND after detecting a TSR, so + * try and inherit any open batch files. + * + */ + + s = (BYTE *) heap_get(128); /* allocate some heap memory */ + + FOREVER { + cmd = deblank(cmd); /* Deblank the command line */ + if((*cmd == '\0') || (*cmd == *switchar)) + break; /* stop at option or end */ + + cmd = get_filename(s, cmd, NO); + + if(strlen(s)) { /* look for Loadpath/STDIO */ + if((ret = ms_x_open(s, OPEN_RW)) >= 0) { + if(isdev(ret)) { + strcat(kbdptr,"ctty "); /* if its a R/W device put */ + strcat(kbdptr, s); /* CTTY into buffer */ + strcat(kbdptr,"!"); + } + else /* otherwise its an error */ + eprintf(MSG_LOADPATH); /* an invalid loadpath */ + ms_x_close(ret); /* Close the handle */ + } + else { + append_slash(s); /* user specified loadpath */ + get_reload_file(); /* get reload_file on heap */ + strcat(s, fptr(heap())); + if(file_exist(s)) { /* append existing load file */ + ms_x_expand(heap(), s); + set_reload_file(); /* copy heap to reload_file */ + } + else { /* Print an error message if */ + eprintf(MSG_LOADPATH); /* an invalid path used. */ + lferror = 1; + break; + } + } + } + else { + eprintf(MSG_LOADPATH); + break; + } + } + + heap_set(s); /* free up heap memory */ + + c_option = FALSE; + k_option = FALSE; + FOREVER { + cmd = deblank(cmd); /* Deblank the command line */ + if(*cmd != *switchar) /* Stop the option check if */ + break; /* the next character is not */ + cmd++; /* a switch character. */ + c = toupper(*cmd++); + switch(c) { +/*RG-05-*/ +#if (defined(CDOS)||defined(DOSPLUS)) && !defined(NOHELP) + case 'H': /* Support /H Help Option */ + case '?': /* Support /? Help Option */ + cflag |= 2; + cmd_ver(); + crlf(); + printf(HELP_COM); + ms_x_exit(0); + break; +#endif +/*RG-05-end*/ + case 'C': /* Support /C Option */ + echoflg = ECHO_OFF; /* Don't issue CR LF */ + c_option = TRUE; + case 'K': + k_option = TRUE; + cmd = deblank(cmd); + if (*cmd == '=') { + cmd++; /* Skip optional '=' */ + cmd = deblank(cmd); + } + + cflag |= 2; + break; + + case 'N': + n_option = TRUE; + break; + + case 'P': /* Support /P Option */ + cflag |= 1; + if (*cmd == ':') { /* See if a different fname */ + cmd++; /* has been specified for */ + ret = 0; /* AUTOEXEC.BAT. */ + while ((*cmd > 32) && (ret < 12)) + autoexec_name[ret++] = *cmd++; + autoexec_name[ret] = 0; + while (*cmd > 32) cmd++; + } + break; + + case 'E': /* Environment Option */ + if(*cmd != ':') /* Check for /E:nnn */ + break; + cmd++; + if(getdigit(&ret, &cmd) && ret > 128 && ret < 32752) + envsize = ret; + break; + +#if defined(CDOS) + case 'T': /* TSR support */ + cflag |= 5; + inherit_TMP_state(); /* inherit batch files etc */ + break; +#endif + +#if defined(DOSPLUS) + case 'T': + inherit_parent_state(); + break; +#endif + + +#if defined(DOSPLUS) + case 'M': /* relocate resident portion */ + c = toupper(*cmd++); + if (c == 'H') prh_function = 1; + if (c == 'U') prh_function = 2; + if (c == 'L') prh_function = -1; + break; + + case 'D': + no_timedate = TRUE; + break; +#endif + + case '\0': /* Treat the NULL character */ + cmd--; /* specially in case some of*/ + break; /* the following command "/"*/ + + default: /* Skip invalid options. */ + break; + } + } +#if defined(DOSPLUS) +/* We cannot allow COMMAND to go into upper memory unless "/P" has also */ +/* been given. If we do the memory won't be freed up on exit */ + + switch(prh_function) { + case 0: /* try high, upper, then low */ + if(COMMAND_P) + put_resident_high(0); + else + put_resident_high(1); + break; + case 1: /* try high, then low */ + put_resident_high(1); + break; + case 2: /* try upper, then low */ + if(COMMAND_P) + put_resident_high(2); + break; + default:/* try low */ + break; + } +#endif + + master_env(envsize); /* Allocate the master */ + /* environment of ENVSIZE */ + /* bytes in length */ +#if 0 + /* + * If no COMSPEC has been defined or it is different from + * the RELOAD_FILE specification then update COMSPEC. + */ + if(env_scan(msg_comspec, heap()) || stricmp(heap(), reload_file)) { + sprintf(buf, "%s%s", msg_comspec, reload_file); + cmd_set(buf); + } +#else + /* BAP changed this */ + get_reload_file(); + if(env_scan(msg_comspec,heap())) { + sprintf(buf,"%s%s",msg_comspec,heap()); + cmd_set(buf); + } +#endif + +#if defined(DOSPLUS) + save_parent = *parent_psp; + *parent_psp = _psp; /* Always do this */ + + if(COMMAND_P) { /* Action the /P flag for */ + execed = NO; /* DOSPLUS.COM */ + + PATH_DIR[0] = drive + 'A'; /* if DRDOS directory exists */ + ret = ms_x_chmod(PATH_DIR, ATTR_ALL, 0); + if ((ret > 0) && (ret & 0x10)) {/* point the path at it */ + sprintf(buf, SET_PATH, PATH_DIR); + cmd_set(buf); + } + cmd_set(SET_PROMPT); + cmd_set(SET_OS); + cmd_set(SET_VER); +#if !defined(FINAL) + cmd_set(SET_BETA); +#endif + install_perm(); /* Install Backdoor entry */ + } + + /* process the environment created by config.sys */ + process_config_env(); +#endif + +#endif + + FOREVER { + if(execed) { /* If this is a transient */ + if (!lferror) + strcat(kbdptr, cmd); /* command processor then */ + ret = FALSE; /* get the command line and*/ + break; /* ignore AUTOEXEC.BAT. */ + } + + /* Check for the presence of STARTnnn.BAT in the root */ + /* of the boot disk if not found check for AUTOEXEC */ + /* if neither are present then if this is console 0 */ + /* and this is < 1987 ask for the date. */ + +#if defined(CDOSTMP) + vc_data(&vc_base, &vc_num, &pc_num); /* Get VC Data */ + vc_num = console - vc_base; /* Relative VC Num */ + sprintf(heap(), "!start%02d%1d.bat", pc_num, vc_num); + if((ret = file_exist(heap()+1)) == 0) { + strcpy(heap(), "!autoexec.bat"); + ret = file_exist(heap()+1); + } + + if(ret != 0) { + strcat(kbdptr, heap()); + sprintf(heap(), " %d %d %d", console, pc_num, vc_num); + strcat(kbdptr, heap()); + break; + } + +#else + strcpy(heap(), "!"); + strcat(heap(), autoexec_name); + if((ret = file_exist(heap()+1)) != 0) { + if (boot_key_scan_code != 0x3f00 /*F5*/) + strcat(kbdptr,heap()); + break; + } else { + boot_key_scan_code = 0; + } +#endif + +#if defined(DOSPLUS) + if (!no_timedate && *autoexec_name!=0) + strcat(kbdptr, "!date!time"); +#else + ms_getdate(&date); + if(console == 1 && date.year < 1987) + strcat(kbdptr, "!date!time"); +#endif + break; + } +#if defined(CDOS) && !defined(CPM) + if(COMMAND_P) /* Action the /P flag for */ + execed = NO; /* CDOS.COM to disable EXIT */ +#endif + +#if 0 + if(COMMAND_C) { /* Append EXIT if COMMAND.COM*/ + strcat(kbdptr, "!exit 0"); /* is just used to execute a */ + } /* a command. */ +#endif + +#if !defined(CDOSTMP) +#if 0 + else { +#else + if(!COMMAND_C) { +#endif +#if defined(DOSPLUS) + if (*autoexec_name != 0) { + cmd_ver(); /* display the signon */ + + printf(MSG_OEMCPYRT); + crlf(); + } +#else + if(!COMMAND_T) { /* if it's CDOS TSR support */ + cmd_ver(); /* don't display signon */ + crlf(); + } +#endif + + } +#endif +} + +/* + * The following function is called to clean up COMMAND.COM after + * an internal or external command has been executed. The major areas + * to be handled by this function are:- + * + * 1) Control-C termination for Batch file termination + * 2) I/O Redirection + * 3) Hiloading off + */ +MLOCAL VOID cmd_cleanup() +{ +BYTE cmdbuf[128]; +#if 0 + hiload_set(NO); /* HILOADing off now */ +#endif + + if(err_ret == BREAK_EXIT || /* Check for Control-C */ + err_ret == ERROR_EXIT) { /* or Critical Error Exit */ + + if(pipe_out) { /* If a Pipe'ed command is */ + pipe_out = NO; /* is aborted then absorb */ + getcmd(cmdbuf); /* the second command. */ + crlf(); + } + + if(batchflg) { + eprintf(MSG_BATTERM); /* Processing a BATCH file */ + err_flag = TRUE; /* ask if the uses wishes to */ + if(yes(NO, YES)) /* to abort this batch job */ + batch_endall(); /* Close ALL batch files */ + err_flag = FALSE; + } + else if(for_flag) /* If processing a FOR */ + for_end(); /* command outside a batch */ + } /* file then abort it. */ + + err_ret &= 0x00FF; /* Mask the Termination */ + /* condition this should only*/ + /* be tested once. */ + + /* + * After the termination of a Batch file or a Program then + * the relevant redirection is removed. If the redirection + * was instigated because of the PIPE facility then the + * correct clean up code is executed. + */ + + while(in_flag & REDIR_ACTIVE) { /* Is Redirection Active */ + if((in_flag & REDIR_BATCH) && batchflg) + break; + + if((in_flag & REDIR_FOR) && for_flag) + break; + + ms_x_close(STDIN); /* Close the Redirected File */ + psp_poke(STDIN, in_handle); /* Restore original Handle */ + + if(pipe_in) { + pipe_in = NO; + ms_x_unlink(old_pipe); + heap_set(old_pipe); + } + + in_flag = NULL; + } + + while(out_flag & REDIR_ACTIVE) { /* Is Redirection Active */ + if((out_flag & REDIR_BATCH) && batchflg) + break; + + if((out_flag & REDIR_FOR) && for_flag) + break; + + ms_x_close(STDOUT); /* Close the Redirected File */ + psp_poke(STDOUT, out_handle); /* Restore original Handle */ + + if(pipe_out) { + pipe_in = YES; pipe_out = NO; + old_pipe = heap_get(strlen(out_pipe)+1); + strcpy(old_pipe,out_pipe); + } + + out_flag = NULL; + } + + country.code = ms_s_country(&country); /* re-init the Country data */ +#if 0 +#if defined(DLS) + dls_msg_crit(); /* re-init crit error msgs */ +#endif +#endif +} + +/*.pa*/ +/* + * ERROR_INIT is the "CRITICAL" error handler which will initialize + * the error handling code, displays error messages and clean-up the + * environment after an error has occurred. + */ +/*RG-00*/ +/*MLOCAL VOID error_code(error)*/ +VOID error_code(error) +/*RG-00-end*/ +UWORD error; +{ + switch(error) { + case 0: /* Setting JMPBUF. Enable */ +#if !defined(CDOSTMP) /* break checking in case */ + ms_set_break(YES); /* this is the first time */ +#endif /* through the command proc. */ + return; + + case IA_BREAK: + putc('\r'); /* A CR here makes SideKick+ */ + /* look good when it */ + /* deinstalls itself */ +/* The following two function calls close the batch file during an INT 23 + thus disallowing to continue with a batch file if the user chooses to + do so after being prompted. However, there migh have been a reason why + this has been inserted before which I don't know of. JBM */ +/* ms_x_close(5); ##jc## Close Unused Handles*/ +/* ms_x_close(6); ##jc## Close Unused Handles*/ + mem_free(&bufaddr); /* Free External Copy Buffer */ +#if defined(CDOSTMP) /* On Concurrent DOS and */ + bdos(DRV_RESET, 0xFFFF); /* DOSPLUS reset the disk */ + crlf(); /* when we get a Control-C. */ +#endif + break; + + case IA_STACK: /* Stack Overflow Error */ + case IA_HEAP: /* Heap Overflow Error */ + batch_endall(); /* Out of memory error */ + eprintf(MSG_BATNEST); /* probably caused by nesting*/ + break; /* batch files TOO deep. */ + + case IA_FILENAME: /* FileName Error */ + eprintf(ERR_FILE); /* display an error message */ + break; /* and terminate the command */ + + default: + eprintf(MSG_LONGJMP, error); + break; + } + + crlfflg = NO; /* Reset CR/LF Flag */ +} + +/* + * This function is invoked after a CONTROL-BREAK or Critical Error + * during the execution of an internal function. Any BREAK specific + * cleanup is executed here. The break handler then restarts normal + * code execution by executing a LONGJMP. + */ +GLOBAL VOID CDECL int_break() +{ +int i; + + if (show_file_buf) mem_free(&show_file_buf); + + if (global_in_hiload) { + /* if ctrl-c pressed during a hiload, restore memory */ + /* allocation strategy. */ + + for(i=1;i<10;i++) { /* free up any UMB's we have */ + if (hidden_umb[i]) { + free_region(hidden_umb[i]); + hidden_umb[i] = 0; + } + } + set_upper_memory_link(global_link); + set_alloc_strategy(global_strat); + global_in_hiload = 0; + } + + err_ret = BREAK_EXIT; /* Update the Global Error Return */ + longjmp(break_env, IA_BREAK); /* Either Control-C or Critical */ + /* Error Process Termination. */ +} + +/*.pa*/ +/* + * This function parses the command line and extracts all unquoted + * >>, > and < character sequences and their corresponding filenames. + * The last redirection specification of the same type is used all + * previous references will be removed. Redirection will only be + * enabled if no redirection of the same type is already active. + * ie. If redirection is enabled on a batch file all redirection + * commands of the same type inside the file are ignored. + */ +GLOBAL BOOLEAN parse(s) /* Parse the command line looking */ +BYTE *s; /* for Redirection commands */ +{ +REG BYTE *bps; +BYTE *bpi, *bpo; +BYTE infile[MAX_FILELEN]; /* Input Redirection FileName */ +BYTE outfile[MAX_FILELEN]; /* Output Redirection FileName */ +BYTE cmdbuf[128]; /* Command buffer for Aborted Pipe */ +WORD h; +BOOLEAN quote = NO; /* Check for Quoted Statements */ +BOOLEAN append; /* Out Redirection Append */ + + crlfflg = YES; /* Force a CRLF in case an error */ + /* occurs in the command line parsing*/ + + for(bpi = NULL, bpo = NULL; *s; s++) { + + if(*s == '"') { /* Maintain the correct */ + quote = !quote; /* Status of the QUOTE flag*/ + continue; + } + + if(quote) /* If the QUOTE flag is */ + continue; /* then skip the following */ + + if(*s == '>') { /* Found Output redirection */ + bpo = outfile; /* Character extract the Path*/ + bps = s+1; append = FALSE; /* and save locally */ + + if(*(bps) == '>') { /* Check for append mode */ + append = TRUE; + bps++; + } + + bps = get_filename(bpo, deblank(bps), NO); + /* Extract the FileName */ + bps = deblank(bps); + strcpy(s--, bps); /* Then remove data from Line*/ + continue; /* S decrement to force new */ + } /* next character to be read */ + + if(*s == '<') { /* Found Input redirection */ + bpi = infile; /* Character extract the Path*/ + bps = get_filename(bpi, deblank(s+1), NO); + /* Extract the FileName */ + bps = deblank(bps); + strcpy(s--, bps); /* Then remove data from Line*/ + } /* S decrement to force new */ + } /* next character to be read */ + + +#if defined(DOSPLUS) + /* only redirect if not already redirected */ + if ((pipe_in || bpi) && (!(in_flag & REDIR_ACTIVE))) { +#else + if(pipe_in || bpi) { /* Check for any redirection */ + if(in_flag & REDIR_ACTIVE) { /* If Standard Input has been*/ + eprintf(MSG_INACTIVE); /* redirected then fail */ + return FAILURE; + } +#endif + + bpi = pipe_in ? out_pipe : infile; /* BPI points to the filename*/ + + h = ms_x_open(bpi, OPEN_READ); + if(h < 0) { + /* Attempt to Open the file */ + e_check(h); /* || device specified and */ + return FAILURE; /* print an error message if */ + } /* we fail. */ + + psp_poke(STDIN, psp_poke(h, 0xFF)); /* Force New input file onto */ + /* Standard Input and close */ + in_flag = REDIR_ACTIVE; /* the returned handle */ + } + +#if defined(DOSPLUS) + /* only redirect if not already redirected */ + if ((pipe_out || bpo) && (!(out_flag & REDIR_ACTIVE))) { +#else + if(pipe_out || bpo) { /* Check for any redirection */ + if(out_flag & REDIR_ACTIVE) { /* If Standard Output has been*/ + eprintf(MSG_OUTACTIVE); /* redirected then fail */ + return FAILURE; + } +#endif + + if(pipe_out) { +#if defined(CDOSTMP) + out_pipe[0] = *SYSDATB(TEMPDISK)+'A'; /* Initialise the DRIVE */ + out_pipe[3] = '\0'; /* Terminate String */ +#else + if (!env_scan("TEMP=",out_pipe)) { + + /* if TEMP != "d:\" check its a valid directory */ + if ((strlen(out_pipe) > 3) || (out_pipe[1] !=':')) { + + h = ms_x_chmod(out_pipe,ATTR_ALL,0); + if ((h<0) || !(h&0x10)) goto assume_root; + } + append_slash(out_pipe); + } + else { +assume_root: + get_out_pipe(); /* get string from low_seg */ + out_pipe[0] = drive+'A'; /* Initialise the DRIVE */ + out_pipe[3] = '\0'; /* Terminate String */ + } +#endif + bpo = out_pipe; + h = ms_x_unique(out_pipe, ATTR_SYS); + + } + else { /* Create the output file if */ + bpo = outfile; /* not Appending or the OPEN */ + /* on the file fails. */ + if(!append || (h = ms_x_open(bpo, OPEN_WRITE)) < 0) + h = ms_x_creat(bpo, 0); + } + + if(e_check(h) < 0) { /* Display any error message */ + if(pipe_out) { /* Pipe'ed command then */ + pipe_out = NO; /* absorb the second command*/ + getcmd(cmdbuf); /* return FAILURE on error */ + crlfflg = YES; + } + return FAILURE; + } + + if(append) /* If in APPEND mode then */ + ms_x_lseek(h, 0L, 2); /* seek to the end. */ + + psp_poke(STDOUT, psp_poke(h, 0xFF));/* Force New input file onto */ + /* Standard Ouput and close */ + out_flag = REDIR_ACTIVE; /* the returned handle */ + + if(pipe_out) + out_flag |= REDIR_PIPE; + } + + crlfflg = NO; + return SUCCESS; +} + + +MLOCAL BOOLEAN docmd_offer(BYTE *cp, BYTE *command, UWORD internal_flag) +{ +BYTE *lcp; +int i; +UWORD int2f_gotit = 0; + + lcp = heap(); + + lcp[0] = 0x80; /* copy command line to buffer */ + lcp[1] = strlen(cp); /* with "readline" format */ + for (i=0;i=0) && (loadfile[i+1] == ' '); i--); + loadfile[0] = i+1; /* set length of cmd */ + + for(;strchr(valid_sepchar,*cp);cp++); /* ignore leading separators */ + for(;is_filechar(cp);cp++); /* skip the command itself */ + /* offer command line to */ + /* interested parties */ + if(docmd_offer(lcp,loadfile,0xFF00+strlen(cp))) /* If they want it */ + return; /* we don't */ + + cp = lcp; + if ((cp[0] != 0) && (cp[1] == ':')) cp+=2; + for(;strchr(valid_sepchar,*cp);cp++); + for(;is_filechar(cp);cp++); /* skip the command itself */ + + cp1 = cp; + i = 0; + while (*cp1 != '\0') { + if (*cp1 == '"') + i ^= 1; + if (is_blank(cp1) == 2 && !i) /* replace each KANJI space */ + *cp1 = *(cp1 + 1) = ' '; /* with one ASCII space */ + cp1 = skip_char(cp1); + } + + s_cmd_p = (S_CMD FAR *)farptr((BYTE *)&cmd_list[0]); + while(internal && s_cmd_p->cmnd) { /* while more builtins */ + cpf = cgroupptr(s_cmd_p->cmnd); + for(i=0;cpf[i];i++) /* make upper case copy */ + argv0[i]=toupper(cpf[i]); + for(;i<8;argv0[i++]=' '); /* space fill it to 8 */ + + if(!strncmp(argv0,loadfile+1,8)) { /* Is this a match ? */ + +#if !defined(NOHELP) + /* Handle /H or /? in command */ + strcpy(heap(),deblank(cp)); + if(!strnicmp(heap(),"/h",2)||!strnicmp(heap(),"/?",2)) { + if (s_cmd_p->help_index != -1) + show_help(s_cmd_p->help_index); + crlf(); + return; + } +#endif + + /* check for embedded commands in IF that only have meaning in + that context */ + if(s_cmd_p->needparm==PARAM_IFCONTEXT) { + if(if_context==FALSE) break; + } + + cp1 = deblank(cp); /* Remove Blanks from Options*/ + + if(s_cmd_p->needparm!=PARAM_NONE /* if a parameter is needed */ + && !*cp1) { /* but none is supplied */ + + switch ((UWORD)s_cmd_p->needparm) /* display an error message */ + { + case PARAM_NEEDFILE: eprintf(MSG_NEEDFILE); break; + case PARAM_NEEDPATH: eprintf(MSG_NEEDPATH); break; + case PARAM_NEEDDEV: eprintf(MSG_NEEDDEV); break; + default: eprintf(MSG_SYNTAX); break; + } + eprintf("\n"); + return; /* ignore the command */ + } + + page_len = get_lines_page(); /* so /P works in 43 and 50 */ + /* line modes */ + (*s_cmd_p->func)(cp1, cp); /* Just Invoke builtin */ + return; + } + s_cmd_p ++; /* compare with next command */ + } + + /* it's not an internal command - could it be help ? */ + if ((!strnicmp(lcp,"/h",2))||(!strncmp(lcp,"/?",2))) { + show_help(0); + s_cmd_p = (S_CMD FAR *)farptr((BYTE *)&cmd_list[0]); + while(s_cmd_p->cmnd) { + cpf = cgroupptr(s_cmd_p->cmnd); + printf("%s\t",cpf); + s_cmd_p++; + } + crlf(); + return; + } + + /* command is not builtin, must be disk based so determine path ... */ + if(docmd_offer(lcp,loadfile,strlen(cp))) /* offer command line to */ + return; /* interested parties */ + /* If they want it, we don't */ + + cp = get_filename(loadfile, lcp, NO); + strcpy(argv0, loadfile); /* the original command name */ + strlwr(loadfile); + + if((loadfile[strlen(loadfile)-1] == '\\') || + ((strlen(loadfile) == 2) && (loadfile[1] == ':'))) { + if(!dos_parse_filename(loadfile) && d_check(loadfile)) { + if (ddrive != -1) + { + ms_drv_set(ddrive); /* then check the requested */ + drive = ddrive; /* drive and make it the */ + crlfflg = NO; /* default if OK. */ + } + } + else { + eprintf(ERR15); + crlf(); + } + return; + } + + if (strcmp(loadfile,"________") == 0) { + ms_x_first("________.???",ATTR_HID+ATTR_STD,(DTA *) heap()); + strcpy(loadfile,"C:\\________.COM"); + } + else if((i = findfile(loadfile, &loadtype)) < 0) { + if(i == ED_FILE || /* Determine the full */ + i == ED_ROOM || /* path and type of the */ + i == ED_PATH) { /* command and return if*/ + eprintf(MSG_BADCMD); /* file or command cannot be located */ + } + else { + e_check(i); + } + return; + } + + + if(!env_scan(msg_comspec, heap())) /* If COMSPEC is defined */ + set_reload_file(); /* then update RELOAD_FILE */ + + doexec(argv0, loadfile, loadtype, cp); /* Load the file */ + allow_pexec = TRUE; +} + + +/* + * FindFile searches the file system copying the actions of the + * Concurrent DOS P_PATH function. If this is TMP for Concurrent + * DOS then use the system call otherwise use the C function. + * + * If no extension is specified then check the file types in + * the following order .CMD, .COM, .EXE, .BAT + * + * If a Path is specified then just check that location otherwise + * check the current directory and then all entries in the path. + */ +#if !defined(CDOSTMP) +GLOBAL WORD CDECL findfile(loadpath, loadtype) +BYTE *loadpath; /* Command Name expanded to full path */ +UWORD *loadtype; /* Command file Type */ +{ + REG BYTE *s; + BYTE sppath[MAX_PATHLEN]; /* Buffer for the optional */ + /* load path. */ + BYTE fname[8+1+3+1+8+1]; /* Buffer for the filename */ + /* optional extension and */ + /* password */ + BYTE *path; /* Environment Load path */ + BYTE *ftype; /* Optional file type */ + BYTE *pwd; /* Optional Password */ + BYTE *envpath; /* current PATH= in env */ + WORD i, ret; +#if !STACK + BYTE pathbuf[MAX_ENVLEN]; /* temporary path buffer */ +#endif + + strip_path(loadpath, sppath); /* isolate the optional path*/ + ftype = loadpath+strlen(sppath); /* get the Filename Address */ + + if(strlen(ftype) < sizeof(fname)) /* If the filename is not */ + strcpy(fname, ftype); /* too long then copy to an */ + else /* internal buffer otherwise*/ + longjmp(break_env, IA_FILENAME); /* break with FILENAME error*/ + + if((ftype = strchr(fname, '.')) != 0) { /* then extract the optional*/ + *ftype++ = '\0'; /* file type from the name */ + pwd = ftype; + } + else { /* If no type has been */ + ftype = NULLPTR; /* specified then make it */ + pwd = fname; /* file type a NULL pointer */ + } + + if ((ret = ms_x_open (fname, 0)) > 0) { /* don't exec a device in */ + i = isdev (ret); /* any shape or form */ + ms_x_close (ret); + if (i) + return (ED_FILE); + } + +#if defined(PASSWORD) + if((pwd = strchr(pwd, *pwdchar)) != 0) /* Finally extract the */ + *pwd++ = '\0'; /* optional password if none*/ + else /* exists then default to a */ + pwd = NULLPTR; /* NULL pointer. */ +#endif + + if(ftype) { /* If a file type has been */ + for(i=0; ftypes[i]; i++) /* specified then check that*/ + if(!strcmp(ftype, ftypes[i])) /* is legal and return an */ + break; /* error if not. */ + + if(!ftypes[i]) /* If an illegal filetype */ + return ED_FILE; /* has been given then */ + } /* return FAILURE */ + + *loadtype = i; /* Save the Load File Type */ + + /* + * Check if a path is currently defined if YES then get + * a copy of the path and save locally on the heap. Protecting + * it against being overwritten. + */ + + if(!env_scan(msg_patheq, heap())) { + envpath = heap(); + while (*envpath) { /* process path in env */ + if(dbcs_lead(*envpath)) /* so delimiters are the */ + envpath++; /* pathchar we expect */ + else + if((*envpath == '/') || (*envpath == '\\')) + *envpath = *pathchar; + envpath++; + } +#if STACK + envpath = stack(strlen(heap()) + 1); +#else + envpath = &pathbuf[0]; +#endif + strcpy(envpath, heap()); + } + else + envpath = ""; + + /* + * First attempt to load the file from the default/specified + * path and then if no path was specified attempt to load the + * file from all the entries in the search path defined in the + * environment. + */ + + if(*sppath) + path = sppath; + else + path = ""; + + do { + i = checkfile(loadpath, loadtype, path, fname, ftype, pwd); + + switch (i) + { + case SUCCESS: + strupr(loadpath); + return SUCCESS; + case ED_FAIL: + case ED_DRIVE: /* if bad drive in search */ + if ((!*sppath) && (*path)) /* path, print msg & carry on*/ + { + eprintf(MSG_PATHDRV); + i = ED_FILE; + break; + } + default: + break; /* get next search path */ + } + + path = envpath; /* Set PATH to the next */ + if((s=strchr(envpath, ';')) != 0) { /* element in the search path*/ + while (*s == ';') { /* Skip over extra semicolons*/ + *s = 0; + s++; + } + envpath = s; + } + else + envpath = ""; /* path exhausted, -> null */ + + /* If you type FILENAME.EXE, it will search the current drive then */ + /* the path. If you type C:\DIR\FILENAME.EXE, it will search */ + /* C:\DIR. Now, if you type C:FILENAME.EXE, it will search the */ + /* current directory on C:, then path. This is done by resetting */ + /* sppath after the first run through, if it is just D: */ + if((strlen(sppath) == 2) && (sppath[1] == ':')) + sppath[0] = '\0'; + + } while(!*sppath && *path); + + return i; +} + +/* + * CHECKFILE generates the full path of the load file and + * attempts to open the file. If the file is located and + * can successfully be opened return SUCCESS with the full + * path in LOADPATH and the LOADTYPE initialised. + * + * If no file extension has been specified then use the standard + * search order. + * + * ATTR_SEARCH specifies the attributes used to locate the file + * to be loaded. + */ + +#define ATTR_SEARCH ATTR_STD + ATTR_HID + +MLOCAL WORD checkfile(loadpath, loadtype, path, fname, ftype, pwd) +BYTE *loadpath; +UWORD *loadtype; +BYTE *path, *fname, *ftype, *pwd; +{ + UWORD type; + WORD ret; + DTA search; + BYTE curpath[MAX_PATHLEN+1]; + + if((path = d_check(path)) == NULL) /* Remove the drive specifier*/ + return ED_DRIVE; /* and return on Error. */ +/* get path starting from root. n.b. don't use ms_x_expand (func 60h) */ +/* as it upsets Novell */ + + if (ddrive != -1) + { + sprintf(loadpath, "%c:%c", ddrive + 'A', *pathchar); + if((*path == '\\') || (*path == '/')) /* If path is absolute then */ + strcpy(loadpath+2, path); /* just append to drive */ + else { /* Otherwise append the */ + ms_x_curdir(ddrive+1, loadpath+3); /* path to the drive and */ + if(*fptr(loadpath)) /* current subdirectory. */ + append_slash(loadpath); + strcat(loadpath, path); + } + } + else + ms_x_expand(loadpath,path); + + + if(*fptr(loadpath)) + append_slash(loadpath); + + strcat(loadpath, fname); /* Add the FileName */ + strcat(loadpath, "."); + path = loadpath + strlen(loadpath); /* Save the Extension Offset */ + +#if defined(PCDOS) +/* + * If running under PCDOS the check if any extension has been specified + * if not then search first for filename.* and return if no match occurs + * This will be quicker than opening each file in turn. + */ + if(!ftype) { + strcat(path, "*"); + if((ret = ms_x_first(loadpath, ATTR_SEARCH, &search)) < 0) { + if( ret == ED_FILE || /* Abort if an error occurs */ + ret == ED_ROOM || /* but ignore File not Found */ + ret == ED_PATH) /* and invalid path errors */ + return ED_FILE; + else + return e_check(ret); + } + } +#endif + + if (ftype == 0) + type = COM_FILETYPE; /* Initialize the Type Index */ + else /* correctly depending on the */ + type = *loadtype; /* initial file type. */ + + do { + strcpy(path, ftypes[type]); /* Add the first file type */ + +#if defined(PASSWORD) + if(pwd) { /* followed by the optional */ + strcat(path, pwdchar); /* password and attempt to */ + strcat(path, pwd); /* open the file. */ + } +#endif + + if((ret = ms_x_first(loadpath, ATTR_SEARCH, &search)) < 0) { + if(ret == ED_PATH) /* Stop scanning this */ + return ED_FILE; /* element of the path if */ + /* it is invalid. */ +#if 0 + if(ret != ED_FILE && ret != ED_ROOM) + return ret; +#endif + } + else { + *loadtype = type; /* Set the correct loadtype */ + return SUCCESS; /* and return SUCCESS */ + } + if (++type > BAT_FILETYPE) +#if defined(DOSPLUS) || defined(NETWARE) + type = COM_FILETYPE; +#else + type = CMD_FILETYPE; +#endif + } while(!ftype && (type != COM_FILETYPE)); + return ED_FILE; +} +#endif + +MLOCAL BOOLEAN doexec(argv0, loadpath, loadtype, tail) +BYTE *argv0; /* Invoking Command */ +BYTE *loadpath; /* Fully expanded filename */ +UWORD loadtype; /* File Type .BAT, .EXE etc. */ +BYTE *tail; /* Command line options */ +{ + WORD ret; + WORD i; + BYTE *s; +#if !STACK + BYTE tailbuf[128]; +#endif + +#if 0 +printf("DOEXEC Load File \"%s\" Command Line \"%s\"\n", + loadpath, (tail ? tail : "")); +#endif + + + if(loadtype == BAT_FILETYPE) { /* if Batch file then:- */ + + if (batchflg == 0) echoflg_save2 = echoflg; + + ret = echoflg; /* Save the Current ECHO State */ + batch_end(); /* Close any Existing Batch file */ + echoflg = ret; /* restore the ECHO status */ + batch_start(argv0, loadpath, tail); /* and initialize the new batch */ + return YES; /* use "CALL" to nest batches. */ + } + /* if CMD, COM or EXE */ + if(batchflg) /* close the BATCH file if OPEN cos */ + batch_close(); /* some programs update the running */ + /* batch file. */ + + s = deblank(tail); /* No SPACE before options */ + if(!*s) /* if this is a blank line */ + tail = s; + +#if defined(CDOSTMP) + ret = exec(loadpath, loadtype, tail, back_flag); +#else + ms_set_break(break_flag); +#if STACK + s = stack(strlen(tail)+2)+1; +#else + s = &tailbuf[1]; +#endif + tail = strcpy(s, tail) - 1; + *tail = (UBYTE) strlen(tail+1); + strcat(tail+1, "\r"); +#if !defined(FINAL) + save_psp(); +#endif + ret = exec(loadpath, loadtype, tail, back_flag); +#if !defined(FINAL) + check_psp(); +#endif + init_switchar(); /* switch character may have changed */ + break_flag = ms_set_break(YES); +#endif + + /* + * Novell use the MS_DRV_GET function to detect abnormal + * program termination. They assume this function is only + * called by the command processor when a child has terminated. + * They close all Remote Handles when the parent command + * processor calls this function. + */ + drive = ms_drv_get(); /* get default drive. */ + + for (i=5;i<20;i++) ms_x_close(i); /* Close all handles */ + + if(ret < 0) { /* Get the returned Error Code */ +#if defined(CDOS) || defined(CDOSTMP) + if(ret == ED_ENVIRON) /* Check for an Environment */ + ret = (-255); /* error this is really */ +#endif /* a resource unavailable. */ + + /* Print a message if the exec */ + e_check(ret); /* went wrong otherwise get the */ + /* completion status and return */ + return FAILURE; + } + + err_ret = ms_x_wait(); + return YES; +} + +#if !defined(CDOSTMP) +VOID FAR CDECL int2e_handler (cmd) +BYTE *cmd; +{ +BYTE *p; +jmp_buf save_jmpbuf; + +/* save the normal setjmp environment and reset it to ourselves */ +/* so that the int2e caller does not get aborted on criterr or */ +/* Control break */ + + memmove (&save_jmpbuf, &break_env, sizeof (jmp_buf)); + + if (setjmp (break_env) == 0) { + + if ((p = strchr (cmd, 0xd)) != NULL) + *p = '\0'; + + int2e_start(); + + docmd (deblank (cmd), TRUE); + +/* if int2e is executing a batch file, do not return until all */ +/* batch file commands have been processed. Loop round as in main */ +/* loop */ + + while (batchflg > 0) + { + cmd_loop (cmd); + } + + int2e_finish(); + } + memmove (&break_env, &save_jmpbuf, sizeof (jmp_buf)); +} + + +MLOCAL VOID init_switchar() +{ + *switchar = ms_switchar(); /* get switch character */ + if (*switchar == '/') /* if not UNIX path char */ + *pathchar = '\\'; /* then be compatible */ + else + *pathchar = '/'; +} + +#endif + +#if defined(DOSPLUS) + +GLOBAL VOID process_config_env() +{ + BYTE FAR *config_env; + WORD i; + BYTE buff[128]; + BYTE *s; + + config_env = get_config_env(); + if (config_env) { + FOREVER { + i = 0; + while ((*config_env) && (*config_env!=0x1A) && + (i < 127)) { + + buff[i++] = *config_env++; + } + if (i == 0) { + while (*config_env != 0x1A) config_env++; + config_env++; + boot_key_scan_code = * ((UWORD far *) config_env); + break; + } + buff[i] = 0; + cmd_set(buff); + while (*config_env) config_env++; + config_env++; + } +#if 0 + s = heap(); + if (!env_scan("HOMEDIR=",s)) { + if (s[1] == ':') ms_drv_set(toupper(*s)-'A'); + ms_x_chdir(s); + } +#endif + } +} +#endif + +#if !defined(FINAL) +void save_psp() +{ + BYTE far *fp; + WORD i; + + fp = MK_FP(_psp,0); + + psp_xsum = 0; + for (i=64;i<128;i++) psp_xsum += fp[i]; +} + +void check_psp() +{ + BYTE far *fp; + WORD xsum; + WORD i; + + fp = MK_FP(_psp,0); + + xsum = 0; + for (i=64;i<128;i++) xsum += fp[i]; + + if (xsum != psp_xsum) { + printf("BETA DEBUG ERROR: Need more stack!\n"); + printf("Press a key to continue.\n"); + getch(); + } +} +#endif + diff --git a/COMMAND/COMCPY.C b/COMMAND/COMCPY.C new file mode 100644 index 0000000..6ef887d --- /dev/null +++ b/COMMAND/COMCPY.C @@ -0,0 +1,1490 @@ +/* +; File : $Workfile: COMCPY.C$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; ENDLOG +*/ + +/* + File COMCPY.C + Title Copy module for command.com + +Revision History:- +================== + +Date Description +----------------------------------------------------------------------------- +20/05/86 Command.com copy routine + Based on earlier comcpy.c but heavily modified + 6/06/86 Destination file given the same attributes as source file + (only applicable to non concatinate cases etc as per + timestamping) + Verify calls added +24/06/86 Special case of file+,, ('touch') supported +27/06/86 Destination now only opened at last possible moment + (in copy1 routine), to speed up floppy to floppy copying +03/07/86 ow supports copy bill+fred bill without destroying the + original contents of bill. Also supports copy ref.lst+*.lst + + 4 Aug 86 ANSI C compatibilty MSC /W1 + 3 Oct 86 Fix bug in REPWILD temp[12] to temp[13] +21 Nov 86 Fixed bug in DOSIF MS_DATETIME + +------------- DOS Plus 2.1 and 2.1b internal release + + 8 Dec 86 Rewritten to handle single drive copying better + added preread and readsrc +11 Dec 86 Number of files copied message moved into message.c +11 Dec 86 Gastly fix for single floppy drive copy of large file + as DOS Plus wont allow us to keep the destination file open + when swapping floppies + (ABswap and ABloop1 flags added) +12 Dec 86 Finished and thoroughly tested for DOS Plus 2.1d release + The few minor bugs remaining are documented in dosplus.doc + Although the code is now very messy it seems to work well! +31 Dec 86 If copying from aux device, set buffer size to 1 +16 Feb 87 Changed check for single physical floppy disk drive + to make more generic + 8 Sep 87 Incorporation of these DOS Plus sources into the Concurrent + DOS COMMAND.EXE and COPY.EXE files. The memory management + has been modified to use an internal static buffer for + copying. An unused routines have been deleted. +10 Sep 87 Force BufSize to be a multiple of 512 bytes otherwise + files greater than the buffer size are not copied. +10 Sep 87 Add an extra check to isfile to check for the case "d:" +13 Oct 87 Add the /Z option which will force the data to be masked + with 0x7F to zero the top bit. +16 Oct 87 /S option copies hidden files as well as system files +16 Oct 87 Copys files with passwords (if source password specified) + (nb destination does not receive a password unless one is + explicitly set) +19 Oct 87 Added /C confirm option +30 Oct 87 isfile() checks for trailing '\' as a special case +05 Nov 87 Moved isdev(fn1) test till after removing flags from fn1 +10 Nov 87 If destination is a device, assume ascii when reading source + and dont send a final ^Z (unless overridden by user flags) + 5 Apr 88 If Sharing mode open fails on the source file try using + a compatibilty mode open. For FrameWork SETUP.EXE. +20 May 88 Update the ISFILE routine to use the FPTR routine. Fixs the + Novell COPY bug. +25 May 88 Close any open batch files for WS2000 install which copies + over its installation batch file. +27 May 88 Added string undefs. +28 Sep 88 Read data from the source device till the buffer is full or + a ^Z has been reached. Donot append a ^Z to a file when copying + from a device unless /A used. +21 Dec 88 Use IOCTL to determine if a handle is attached to a device + or not. +1 Mar 89 Ignore '[',']','"' +14 Apr 89 If dest is a device and /b specified (either src or dst) set + device to binary +6 Jun 89 Do not explicitly set the hidden attribute on password + protected files let OS do it for us. +12 Jun 89 Use all of allocated buffer even for Device Reads +14 Jul 89 Move findeof to assembler for speed +4 Aug 89 Used to ignore /b on concat src if dest was device +6-Mar-90 Watcom C v 7.0 +22-Mar-90 Copy with control chars cmd string (get_pno terminate bug) +8-May-90 "File not found" error goes to STDOUT, not STDERR. +24-May-90 samefs uses ms_x_expand to check full physical path +5-Jun-90 BODGE copy to dev to be 1 char at a time so we can retry + correctly (BDOS bug workaround) +11-Jun-90 "COPY file1 file2 ; " hanging cured. I hate get_pno. +27-Nov-90 samefs() no longer uses ms_x_expand(), for PCNFS + compatibility. +15-Jan-91 "COPY a+b+c d" no longer stops if b does not exist. + +DRDOS BUXTON +------------ + +1-Mar-91 COPY /B FILE DEVICE is now supported. + Copying to a dev is no longer 1 char at a time, in anticipation + of a fix in the BDOS. +2-Apr-91 COPY no longer forces time/date/attributes of source onto + destination. +7-May-91 time/date is now preserved again, attributes are not. + +DRDOS PANTHER +------------- + +22-Jun-92 Support for Novell Remote copy added. + See call to novell_copy(). +---------------------------------------------------------------------------- +*/ + +#include "defines.h" + +#include + +#if defined(MWC) && defined(strlen) +#undef strcmp /* These are defined as macros in string.h */ +#undef strcpy /* which are expaneded in line under */ +#undef strlen /* Metaware C. These undefs avoid this. */ +#endif + +#include +#include + +#include "command.h" /* COMMAND Definitions */ +#include "dos.h" /* MSDOS Functions */ +#include "dosif.h" /* DOS interface definitions */ +#include "toupper.h" +#include "support.h" /* Support routines */ +#include "global.h" + + +EXTERN VOID batch_close(VOID); /* BATCH.C */ + +MLOCAL BYTE * skip_switch(BYTE *); +MLOCAL BYTE * get_p1(BYTE *, BYTE *, BYTE *); +MLOCAL BYTE * get_pno(BYTE *, BYTE *); +MLOCAL BOOLEAN isfile(BYTE *); +MLOCAL VOID addwild(BYTE *); +MLOCAL BOOLEAN dopen(BYTE *); +MLOCAL VOID dclose(BYTE *, WORD, WORD); +MLOCAL BOOLEAN preread(BYTE *); +MLOCAL WORD readsrc(VOID); +MLOCAL WORD copy1(BYTE *, BYTE *); +MLOCAL BOOLEAN lseek(BYTE *); +MLOCAL BOOLEAN samefs(BYTE *, BYTE *, WORD); +MLOCAL WORD ABcheck(BYTE *, BYTE *); +MLOCAL VOID prtsrc(BYTE *); +MLOCAL WORD conf_src(BYTE *); +MLOCAL VOID e_check2(WORD); +MLOCAL BOOLEAN touch(BYTE *); +MLOCAL BYTE * get_pswd(BYTE *); + + +/* define external variables used */ + + +#define COPY_VERIFY (global_flg & 1) /* Set Verify Flag */ +#define COPY_SYS (global_flg & 2) /* Include SYSTEM Files */ +#define COPY_ZERO (global_flg & 4) /* Zero the eighth Bit */ +#define COPY_CONFIRM (global_flg & 8) /* Confirm each file */ + +#define COPYSRC_ASC (sflag & 1) /* Source is ASCII */ +#define COPYSRC_BIN (sflag & 2) /* Source is Binary */ + +#define COPYDST_ASC (dflag & 1) /* Destination is ASCII */ +#define COPYDST_BIN (dflag & 2) /* Destination is BINARY*/ + +#define MIN_COPYBUF (10 * (1024/16)) /* Minimum Copy Buffer Size */ +#define MAX_COPYBUF (50 * (1024/16)) /* Maximum Copy Buffer Size */ + +/* define static variables for this module */ + +MLOCAL BYTE *lp; +MLOCAL UWORD global_flg; /* Global Flags Verify, System & Zero */ +MLOCAL UWORD dflag; +MLOCAL BOOLEAN sascii; /* treat current source file as ascii */ +MLOCAL BOOLEAN sbin; +MLOCAL BOOLEAN concat; +MLOCAL WORD nfiles; /* number of files copied */ + +MLOCAL WORD dfh; /* destination file handle */ +MLOCAL BOOLEAN dstopen; /* destination open */ +MLOCAL WORD sfh; +MLOCAL ULONG src_len; +MLOCAL BOOLEAN srcopen; /* flag whether src is still open */ +MLOCAL BOOLEAN srcdev; +MLOCAL BOOLEAN dstdev; +MLOCAL BOOLEAN fullbuf; /* buffer contains data */ +MLOCAL BOOLEAN dfailed; +MLOCAL BOOLEAN ABswap; /* single floppy disk drive copy with disk swap */ +MLOCAL BOOLEAN tstamp; /* set destination timestamp to same as source */ +MLOCAL UWORD date,time; /* source date and time */ +MLOCAL UWORD attrib; /* source file attributes */ + +MLOCAL UWORD amount; /* amount of real data in buffer */ + +/* ---- start of code ---------------------------------------------*/ + +GLOBAL VOID CDECL cmd_copy(cmd) +BYTE *cmd; +{ + WORD rmode = 0x0000; /* read mode - normal files only */ + BYTE delim; + BYTE npara; + BYTE src[MAX_FILELEN]; /* buffer in which to expand wild source filespec */ + BYTE dest[MAX_FILELEN]; /* buffer in which to expand wild destination filespec */ +#if defined(PASSWORD) + BYTE password[10]; /* keep note of src password */ +#endif + BYTE *olp, *tp; + BYTE *last_delim; + WORD ret; + BOOLEAN scheme1; + BOOLEAN init = YES; /* do initialisations during 1st loop */ + BOOLEAN pflag; + BOOLEAN tflag; /* touch flag (special case) */ + BOOLEAN confirmed; + UWORD dosvf; /* used to save current dos verify state */ + UWORD sflag; /* Source File Options */ + /* scheme2 extra bits */ + BYTE wdfn[13]; /* used by scheme2 to save wild destination filename */ + BYTE *dfptr; + BYTE *ocmd; + BYTE src2[MAX_FILELEN]; /* 2nd src buffer for scheme2 */ + DTA search; /* DOS Search Buffer */ + + sascii = NO; /* indicates if current source is ascii or not */ + sbin = NO; /* sbin indicates if an explicit /b found */ + concat = NO; + dfailed = ABswap = NO; + srcopen = dstopen = NO; /* No file are Open */ + nfiles=0; /* number of files copied */ + cmd = deblank(cmd); /* remove leading spaces */ + strlwr(cmd); /* force it all to lower case first */ + strcpy(heap(),cmd); /* make temp copy of cmd line */ + if(f_check(heap(), "vszcab", &global_flg, NO)) /* check for any bad flags */ + return; /* exit if any (with message) */ + /* also zaps any valid flags but not important is this is a temp copy */ + f_check(cmd,"vszc",&global_flg,YES); /* check for, and zap verify, sys, zero and confirm flags */ + if(COPY_SYS) { + rmode |= ATTR_SYS; /* read system files also*/ + rmode |= ATTR_HID; /* read hidden files also*/ + } /* nb /s flag acts globally */ + + cmd = deblank (cmd); /* deblank incase /v was at start of line */ + + while(*cmd == *switchar) { /* process any initial switches */ + if(*(cmd+1)=='a') + sascii=YES; + if(*(cmd+1)=='b') { + sascii=NO; + sbin=YES; + } + cmd = deblank (cmd+2); + } + + lp = get_pno(cmd,&npara); + olp =lp; /* save lp ptr (as lp possibly modified later) */ + /* olp is used as the end of the list of source parameters */ + if(npara > 1) /* dont remove switches if npara=1 as they will be processed when fn1 switches are checked */ + f_check( lp, "ab", &dflag, YES); /* check for, and zap destination a and b flags */ + /* store them in dflag for later use */ + + last_delim = lp-1; + while (*last_delim == 32) last_delim--; + + zap_spaces(lp); + + cmd = get_p1(src, deblank(cmd), &delim); /* separate 1st filename spec from rest */ + + if(delim == '=') { /* if the user spells PIP as COPY */ + syntax(); /* exit with syntax error */ + return; + } + + if(npara>2 && delim!='+') { + printf(MSG_INOP); /* invalid number of parameters */ + return; + } + + + if(!d_check(src)) + return; /* invalid drive */ + + f_check( src, "ab", &sflag, YES); /* check for, and zap flags in fn1 */ + + if(COPYSRC_ASC) + sascii=YES; + if(COPYSRC_BIN) { + sascii=NO; /* nb /b checked last by default */ + sbin=YES; + } + + zap_spaces (src); + +/* do adjustments for special cases */ + + if (COPYDST_BIN) { + sbin = YES; /* Does it make sense to have source ascii */ + sascii = NO; /* and dest binary? I think not. */ + } + + if(lp[strlen(lp)-1] == ',') + lp[strlen(lp)-1] = '\0'; /* remove comma from end of lp */ + + if(npara==1 && delim!='+') + if(isfile(lp)) { /* strip drive and path from lp */ + lp = fptr(lp); /* ie path\file becomes \path\file */ + } /* to file but not if \path\file+ */ + else + lp=lp+strlen(lp); /* if dir, lp=\0 */ + + if(npara==1 && delim=='+') { + delim=' '; /* not concat if 1 parameter */ + tp=lp; + while (*tp) { /* remove the + sign from end of lp filespec */ + if(*tp == '+') + *tp = ' '; + tp++; + } + } + + if(npara>=2 && delim=='+' && *last_delim=='+') { + /* copy fred+bill dest is fred */ + lp = fptr(src); /* copy path\fred+bill dest is fred */ + olp=cmd+strlen(cmd); /* fiddle olp to end of list of source parameters */ + } + + if(npara==2 && iswild(src) && /* handle special case */ + isfile(lp) && !iswild(lp)) /* of copy *.lst file */ + concat = YES; /* (implied concatination) */ + + tflag = (npara>=3 && delim=='+' && *cmd==','); /* touch special case so set tflag */ + + if(delim == '+') + concat = YES; + + if(concat && !sbin) /* concat is ascii unless a /b switch has occured */ + sascii = YES; + + dstdev = NO; + + if (!iswild(lp) && *lp) + { + get_filename(dest,lp,YES); /* this turns lpt1: into lpt1 */ + + ret = ms_x_open(dest, OPEN_READ); /* Check if destination is */ + if (ret >= 0) /* a device. If so, if /b */ + { /* on src OR dst, copy is */ + if (isdev(ret)) /* binary */ + { + dstdev = YES; + if (COPYSRC_BIN || (COPYDST_BIN && !concat) || sbin) + { + sbin = YES; + sascii = NO; + } /* If no /b, default to */ + else /* ascii */ + { + sbin = NO; + sascii = YES; + } + } + + ms_x_close (ret); + } + } + + mem_alloc(&bufaddr, &bufsize, MIN_COPYBUF, MAX_COPYBUF); + bufsize <<= 4; /* Allocate the Buffer */ + bufsize &= ~511; /* Force the buffer size to be a*/ + /* multiple of 512 Bytes */ + if(bufsize == 0) { /* If the memory allocation */ + e_check(ED_MEMORY); /* print a memory error and */ + return; /* return to the caller. */ + } +#if 0 /* UNBODGE */ +/** BODGE **/ + if(dstdev) /* copy to dev 1 char at a time */ + bufsize = 1; /* so retry operates correctly */ +/** BODGE **/ +#endif /* UNBODGE */ + + if(batchflg) /* close the BATCH file if OPEN cos */ + batch_close(); /* installation routines copy over */ + /* the current batch file. */ + + dosvf = ms_f_getverify(); /* read present dos verify flag*/ + if(COPY_VERIFY) + ms_f_verify(1); /* set verify */ + + + if (lp == get_filename(dest, lp, YES)) { + if (strlen(lp)) { + printf(MSG_SYNTAX); /* bad filename specified */ + return; + } + } + +#if TRUE +/* ##jc## + * This Code is a Special for IBM Display Write 4 which attempts + * to copy "A:DEFAULT.P*TÌ". Treat this a a secial case and convert + * it to "A:DEFAULT.P*". + */ + tp = strchr(fptr(src), '.'); /* Search for . in the */ + if(tp && !strnicmp(tp, ".p*t", 4)) /* and check for an ext */ + strcpy(tp, ".p?t"); /* of "P*T". */ +#endif + + /* never add *.* to CON */ + if (stricmp(src,"CON")) addwild(src); + /* if just a drive or path, add *.* */ + +/* cant do addwild(dest); yet as it will cause a drive B access on single floppy copy */ + + + tstamp = !concat; /* if concatinating, then dont alter timestamp */ + /*tstamp = NO;*/ /* ie leave timestamp as current time */ + + pflag = concat || iswild(src); /* pflag indicates whether to print out */ + /* intermediate file names as they are copied */ + + + /* see later for a description of schemes 1 and 2 */ + + /* common start for schemes 1 and 2 */ + +more1: +#if defined(PASSWORD) + strcpy(password,get_pswd(src)); /* keep copy of the src password */ + /* password incorporates the leading ';' */ + /* password = '\0' if no password */ +#endif + + tp=fptr(src); /* get ptr to filename part of src */ + + ret=ms_x_first(src,rmode,&search); /* get first explicit source (if src wild) */ + /* if(ret < 0) check moved till after prtsrc */ + +loop12: + if(ret >= 0) { /* copy explicit filename to src */ + strcpy(tp,search.fname); /* only do this if a file was found */ +#if defined(PASSWORD) + strcat(tp,password); /* add the src password */ +#endif + } + + strlwr(tp); /* convert to lower case */ + + if(pflag && !COPY_CONFIRM) + prtsrc(src); /* print name of this file */ + + if(COPY_CONFIRM && ret>=0) + confirmed = conf_src(src); /* print source name and ask whether to copy */ + else + confirmed = YES; + + if(ret < 0) { /* break out of wild src loop */ + if(ret == ED_ROOM) { + printf(ERR02); /* print "File not found" error */ + crlf(); /* to STDOUT, not STDERR, because*/ + } + else + e_check2(ret); /* dst open or not determines if */ + goto nextfile; /* nfiles gets incremented */ + } + + if(preread(src)==FAILURE) /* pre read a buffer full if error */ + /* goto sum1; */ /* break out of wild src loop - too drastic ! */ + confirmed=NO; /* if error just skip this file */ + + if(init) { /* if 1st time round the loop do dest checks */ + if (!dstdev) addwild(dest); + scheme1 = !iswild(dest); + /* do bits for scheme 2 */ + dfptr=fptr(dest); /* ptr to filename (wild) */ + strcpy(wdfn,dfptr); /* copy wild dest filename */ + ABswap=ABcheck(src,dest); /* check for single drive copy */ + init=NO; + } + + /* now we branch to scheme 1 or 2 */ + + if(scheme1) { /* ----- scheme1 ----- */ + if(confirmed) { + if(!dstopen && concat && /* special case for copy bill+fred */ + samefs(src,dest,NO)) { /* bill, copy ref.lst+*.lst etc */ + if(lseek(dest)==FAILURE) /* opens dest and lseeks to the end of it */ + goto end1; /* exit if dest error */ + } + else { /* this is the normal case */ + if(!samefs(src,dest,YES)) { /* check src!=dest */ + /* if src=dest then prints message and skips copying */ + if(copy1(src,dest)==FAILURE) { /* copy src to dest */ + if(dfailed) /* also opens destination if necessary */ + goto end1; /* dfailed if disk full or dest error */ + } + } /* nb nfiles++ done on dclose as refers to no of destination files */ + } + } /* above section skipped in not confirmed */ + else { + if (srcopen) ms_x_close(sfh); + } + ret = ms_x_next(&search); + if(!ret) goto loop12; /* loop round and do it again */ + /* if more files match wild src */ + + /* concatinate under scheme1 */ + /* if not concat or !dstopen could goto end1 */ +nextfile: while (*cmd==',') /* skip over commas */ + cmd++; + + if(cmd < olp && *cmd) { /* if there are more source parameters */ + cmd = get_p1(src, deblank(cmd), &delim); /* separate filename spec from rest */ + f_check( src, "ab", &sflag, YES); /* check for, and zap flags in fn1 */ + + if(COPYSRC_ASC) + sascii=YES; + + if(COPYSRC_BIN) { + sascii=NO; /* nb /b checked last by default */ + sbin=YES; + if (dstdev) /* 4 Aug JJS */ + ms_x_setdev (dfh, ms_x_ioctl (dfh) | 0x20); + /* set device to binary */ + } + + zap_spaces(src); + addwild(src); /* if just a drive or path, add *.* */ + + goto more1; /* loop back and copy next lot */ + } + + end1: /* closing of dest (if necessary) */ + ; /* done by sum1 */ + + } /* end of scheme1 */ + + else { /* ----- scheme2 ----- */ + + if(!confirmed) { + if (srcopen) ms_x_close(sfh); + goto skip2; /* forget it if user doesnt want to copy */ + } + + strcpy(dfptr,wdfn); /* get back wild dest fname */ + repwild(src,dest); /* replace wild part of dest with corresponding explicit details from src */ + + if(tflag && samefs(src,dest,NO)) { /* touch special case */ + if(touch(src)==SUCCESS) /* set timestamp */ + nfiles++; /* inc count if successful*/ + + goto skip2; /* jump to end of do loop */ + } + + if(samefs(src,dest,YES)) /* check src!=dest */ + goto end2; /* if src=dest then prints message */ + + copy1(src,dest); /* copy src to dest */ + /* also opens destination if necessary */ + + if(dfailed) { /* dfailed if disk full or dest error */ + dclose(dest,dfh,YES); + goto end2; /* get out of loop */ + } + + while(*cmd==',') /* skip over commas */ + cmd++; + + if(cmd < olp) { /* if there are more source */ + ocmd=cmd; /* parameters (concat only) */ + dfailed=NO; + + while (cmd < olp && *cmd) { + cmd = get_p1(src2, deblank(cmd), &delim); /* separate filename spec from rest */ + f_check(src2, "ab", &sflag, YES); /* check for, and zap flags in fn1 */ + if(COPYSRC_ASC) + sascii=YES; + if(COPYSRC_BIN) { + sascii=NO; /* nb /b checked last by default */ + sbin=YES; + } + + zap_spaces (src2); /* use src2 for these parameters so */ + addwild(src2); /* if just a drive or path, add *.* */ + repwild(dest,src2); /* replace wild part of src2 */ + if(pflag) + prtsrc(src2); /* print name of this file */ + + samefs(src2,dest,YES); /* do 'content of dest lost' mssg if applicable */ + + copy1(src2,dest); /* copy src2 to dest */ + if(dfailed) /* dfailed if disk full or dest error */ + break; /* break out of while cmd= 'a' && ch <= 'z'); + } + return cmd; +} + +/* + * Copy the next parameter including FILENAME and SWITCHES into + * PARAM and set DELIM to be the delimiting character. The return + * value is the start address of the next parameter. + */ +MLOCAL BYTE * get_p1(param, s, delp) +BYTE *param; +REG BYTE *s; +BYTE *delp; +{ + REG BYTE *ep; + + ep = s = get_filename(param, s, YES); /* Copy the Filename */ + s = deblank (s); /* skip trailing spaces */ + while( *s=='"' || *s=='[' || *s==']' || *s==';') + s++; /* Ignore non file character params*/ + s = deblank (s); /* skip trailing spaces */ + + while (*s == *switchar) /* Skip any Switches */ + s = deblank(skip_switch(s)); + + if(s-ep) /* Concatinate any switches */ + strncat(param, ep, s - ep); /* to the end of PARAM. */ + + if(*s && strchr("+=,", *s)) { /* Check for a separator */ + *delp = *s; /* return it in DELP and */ + return deblank(s+1); /* skip the character */ + } + + *delp = (*s ? ' ' : '\0'); + return s; +} + +/* + * Get number of filename parameters (including their switches) + * in string. Returns the address of the last command + * line parameter. + */ +MLOCAL BYTE * get_pno(s, nptr) +BYTE *s,*nptr; +{ +REG BYTE *tp; +BYTE temp; + + *nptr = 0; + tp = s; + + do { + (*nptr)++; + tp = s; + s = get_p1(heap(), s, &temp); + } + while (*s && s!=tp); + + return (tp); +} + +/* + * returns true if s is an explicit file + * (nb may not yet have been created) + * ie isnt just a drive designator or just a path + */ +MLOCAL BOOLEAN isfile(s) +REG BYTE *s; +{ + REG WORD ret; + + if(strlen(fptr(s)) == 0) /* point to the file sub-string */ + return(NO); /* if this is zero length then */ + /* this is not a file. */ + if (!strcmp(s,dotdot)) + return(NO); + + if(iswild(s)) /* If an ambiguous reference */ + return (NO); /* then no a specific file ref. */ + + ret = ms_x_chmod (s, ATTR_ALL, 0); /* get attributes of filespec */ + + if(ret == ED_FILE) /* file not found (file yet to be created) */ + return (YES); /* it will be a file */ + + if(ret < 0) + return (NO); /* any other error is not a file */ + + if(!(ret & ATTR_DIR)) + return (YES); /* if not a dir, then its a file */ + + return (NO); +} + +/* + * if s is just a drive designator or just a path, add *.* + * (or \*.* as appropriate) to it + */ +MLOCAL VOID addwild(s) +REG BYTE *s; +{ + REG BYTE tb; + + if(!iswild(s) && !isfile(s)) { /* if s is sub dir only, add *.* */ + if(*fptr(s)) + append_slash(s); + + strcat(s,d_slash_stardotstar+3); + } +} + + +/* + * Opens destination file (sets static variable dfh to destination file handle) + * Returns success or failure + * Uses/sets static variables - + * dstopen + * tstamp sets tstamp=NO if dest is a device + */ +MLOCAL BOOLEAN dopen(dest) +REG BYTE *dest; /* destination filename */ +{ + if(dstopen) + return (FAILURE); /* already open */ + + if(iswild(dest) || !*dest) + return (FAILURE); /* DONT create if wild */ + /* or nul */ + + if(!d_check(dest)) { + crlf(); + return (FAILURE); /* invalid dest drive */ + } + + if((dfh=ms_x_creat(dest,0)) < 0) { /* create destination file or truncate to empty */ + e_check2(dfh); /* if error */ + return (FAILURE); + } + + if(isdev(dfh)) /* if writing to a device */ + { + tstamp = NO; /* dont set timestamp */ + + if (sbin) /* if binary, set device to binary */ + { + ms_x_setdev (dfh, ms_x_ioctl (dfh) | 0x20); + } + } + + dstopen = YES; + return (SUCCESS); +} + +/* + * Closes destination file + * adds ^Z eof if necessary + * changes its timestamp if necessary + * deletes incomplete dest if failed flag set + * NB only does any of this if dstopen + * Uses static variables - + * dstopen + * tstamp + * date,time + * dflag + * sascii + */ +MLOCAL VOID dclose(dest,dfh,failed) +BYTE *dest; /* destination filename */ +REG WORD dfh; /* destination filehandle */ +BOOLEAN failed; +{ + BOOLEAN dascii; /* destination is ascii */ + UWORD dattrib; + BYTE xeof = ('Z'-64); /* ^Z */ + + dascii = sascii; /* use the (last) source ascii flag */ + + if(dstopen) { /* dont do anything if not open */ + if(!failed) { + + if(isdev(dfh)) + dascii=NO; /* dont send ^Z if dest is a device */ + + if(COPYDST_ASC) + dascii=YES; + + if(COPYDST_BIN) + dascii=NO; /* check for explicit /b last */ + + if(dascii) + ms_x_write(dfh,&xeof,1); /* add ^Z */ + + if(tstamp) /* change timestamp from current time to source files timestamp */ + ms_x_datetime(1,dfh,&time,&date); + } + + ms_x_close(dfh); /* close destination */ + dstopen = NO; + + if(failed) /* if failed, delete incomplete destination */ + ms_x_unlink(dest); + + else { /* (didnt fail) */ +#if 0 + if(tstamp) { + dattrib = attrib; /* dest attribs = src attribs */ + if (!COPY_SYS) { + dattrib &= ~ATTR_HID; /* if not /S , then dont let hidden attribute be set */ + } + ms_x_chmod(dest,dattrib,1); /* change destination attributes */ + } /* under same conditions as tstamp */ +#endif + } /* nb must be done after dest closed */ + } + return; +} + +/* + * Reads a buffer full of the source + * If eof src then closes source + * Returns success or failure + * + * Uses/sets static variables - + * sascii + * tstamp sets tstamp=NO if source is a device + * date,time + * bufaddr + * bufsize + * + * srcopen indicates if src still open + * srcdev indicates if current source is a device + * fullbuf indicates if data in buffer + * amount + * sfh + */ +MLOCAL BOOLEAN preread(src) +BYTE *src; /* source filename */ +{ + srcopen=NO; + fullbuf=NO; + + if(!d_check(src)) { + crlf(); + return (FAILURE); /* invalid src drive */ + } + + sfh = ms_x_open(src, OPEN_READ); /* Open the File/Device using*/ + if(sfh == ED_ACCESS) /* a sharing mode if Access */ + sfh = ms_x_open(src, OPEN_RO); /* denied try compatibility */ + /* mode. FrameWork Setup */ + if(sfh < 0) { /* leaves a control file Open*/ + e_check2(sfh); /* during the copy. */ + return (FAILURE); + } + + srcdev = isdev(sfh); /* Check if Source is a Device */ + if(srcdev) { /* Don't set the timestamp if */ + tstamp = NO; /* the source is a device */ + if(sbin) { /* If a Binary Read has been */ + ms_x_close(sfh); /* specified then terminate as */ + printf(MSG_BINRD); /* the source is a Device */ + return (FAILURE); + } + } + else { + ms_x_datetime(0,sfh,&time,&date); /* read files time stamp */ + /*tstamp = YES;*/ + } + + src_len = ms_x_lseek(sfh,0,2); + ms_x_lseek(sfh,0,0); + + srcopen=YES; + attrib=ms_x_chmod(src,attrib,0); /* read src file attributes */ + + /* Don't copy 0 length files */ + if (src_len == 0L && !srcdev) return(FAILURE); +#if 0 + if(readsrc()==FAILURE) /* read a buffer full */ + return (FAILURE); + + /* amount contains the size of real data in the buffer */ + /* srcopen set if source is still open */ + + fullbuf=YES; /* buffer contains data */ +#endif + return (SUCCESS); +} + +/* + * source already open + * Reads a buffer full of the source + * If eof src then closes source + * If error then closes source + * Returns success or failure + * + * Uses/sets static variables - + * sascii + * bufaddr + * bufsize + * + * srcopen indicates if src still open + * srcdev + * fullbuf indicates if data in buffer + * amount + * sfh + */ + +MLOCAL BOOLEAN readsrc() +{ + WORD ret; /* return code from source open */ + UWORD i; + BOOLEAN eofsrc; + + fullbuf = NO; /* Buffer Empty */ + eofsrc = NO; /* EOF not found */ + amount = 0; /* 0 Bytes read so far */ + + while(!eofsrc) { + ret = far_read(sfh, bufaddr+amount, bufsize-amount); + if((ret&(-256))==(-256)) { /* if error */ + e_check2(ret); + ms_x_close(sfh); + return (FAILURE); + } + + if(sascii || srcdev) { /* Check data for ^Z */ + i = findeof(bufaddr+amount, ret);/* if FINDEOF returns a */ + if(i < ret) { /* count less than RET */ + eofsrc=YES; /* then end of transfer */ + amount += i-ret; /* using the updated size */ + } + } + amount += ret; + + if(amount == bufsize) /* Check for a full buffer */ + break; /* and break when full. Else*/ + else if(!srcdev || ret == 0) /* if the source is not a */ + eofsrc = YES; /* device then must have */ + /* reached the EOF. */ + } + + if(eofsrc) { /* if eof src then close src */ + ms_x_close(sfh); + srcopen=NO; + } + + /* amount contains the size of real data in the buffer */ + /* srcopen set if source is still open */ + + fullbuf=YES; /* buffer contains data */ + +#if 0 + if (amount == 0) return(FAILURE); /* BAP - if file is 0 bytes, don't */ + /* copy it */ +#endif + + return (SUCCESS); +} + +/* + * If the destination is not open it gets opened (file handle dfh). + * Copies source file to destination file dfh + * (actually concatinates source file onto end of destination file). + * Returns success or failure + * If source has been preread then uses preread buffer full + * else opens the source + * Always ends by closing the source + * Destination is always closed except if concat **** + * + * Uses/sets static variables - + * dfh destination file handle + * sfh + * fullbuf + * sascii + * tstamp sets tstamp=NO if source is a device + * date,time + * dfailed if destination error + * bufaddr + * bufsize + * amount + * concat + */ +MLOCAL BOOLEAN copy1(src,dest) +BYTE *src; /* source filename */ +BYTE *dest; /* destination filename */ +{ + UWORD ret; /* return code from source open */ + UWORD bytes_left; + UWORD bytes_written; + BYTE FAR *tp; + BOOLEAN ABloop1; /* special case if single drive copy */ + /* must not leave destination open */ + + ABloop1=NO; + + /*printf("copying %s to %s\n",src,dest);*/ + + if (!ABswap && !concat && srcopen && !sascii) { + dfailed=dopen(dest); + if(dfailed) { + if(srcopen) + ms_x_close(sfh); + return (FAILURE); /* error - cant open dest */ + } + +#if 0 + src_len = ms_x_lseek(sfh,0,2); + ms_x_lseek(sfh,0,0); +#endif +#if 0 +/* taken out as it screws POWERLAN. */ + /*printf("novell_copy(%d,%d,%ld)\n",sfh,dfh,src_len);*/ + + if (novell_copy(sfh,dfh,src_len)) { + ms_x_close(sfh); + srcopen = NO; + ms_x_close(dfh); + dstopen = NO; + nfiles++; + return(SUCCESS); + } +#endif + } + + do { + if(!fullbuf) { /* if buffer not prefilled */ + /* then fill the buffer */ + if(!srcopen) { /* if src not open then use preread */ + if(preread(src)==FAILURE) /* (opens src)*/ + return (FAILURE); + } + /*else {*/ /* source open, therefore use readsrc */ + if(readsrc()==FAILURE) /* read next buffer full */ + return (FAILURE); + /*}*/ + } + + /* at this point we have a buffer full */ + /* src is closed if this is the last buffer full */ + + if(!dstopen) { /* if destination not open, open it */ + if(ABloop1) { /* special case if 2nd time round the loop */ + /* and single drive copy */ + dfh=ms_x_open(dest,OPEN_RDWR); /* open dest for rw */ + dstopen=YES; + ms_x_lseek(dfh, (LONG) 0,2); /* lseek to end of dest */ + } + else { /* normal case */ + dfailed=dopen(dest); + if(dfailed) { + if(srcopen) + ms_x_close(sfh); + return (FAILURE); /* error - cant open dest */ + } + } + } + + /* write to destination */ + if(COPY_ZERO) { + for(tp = bufaddr, ret = 0; ret < amount; ret++, tp++) + *tp &= 0x7F; + } + + +#if TRUE + /* This is a better way to do do things */ + bytes_left = amount; + bytes_written = 0; + while(bytes_left > 0) { + ret = far_write(dfh, bufaddr+bytes_written, bytes_left); + if ((ret > 0xFF00)||(ret == 0)) { + if (isdev(dfh)) printf(MSG_DEVFAIL); + else printf(MSG_FULL); + dfailed=YES; + if (srcopen) ms_x_close(sfh); + return(FAILURE); + } + bytes_left -= ret; + bytes_written += ret; + } +#else + if(far_write(dfh, bufaddr, amount)!=amount) { + if (isdev(dfh)) printf(MSG_DEVFAIL); + else printf(MSG_FULL); /* disk full error */ + dfailed=YES; + if(srcopen) + ms_x_close(sfh); + return (FAILURE); + } +#endif + fullbuf=NO; + + if(srcopen && ABswap) { /* must temp close destination if */ + ms_x_close(dfh); /* single drive copy with AB swap */ + dstopen=NO; + ABloop1=YES; + } + } while(srcopen); /* loop till end of source */ + + if(!concat) { /* CLOSE dest except if concatinating */ + dclose(dest,dfh,dfailed); + if(!dfailed) + nfiles++; /* nfiles refers to no of dest files */ + if(dfailed) + return (FAILURE); + } + return (SUCCESS); +} + +/* + * The destination file is opened, and the file pointer is + * lseeked to the end of the file. (or to the 1st ^Z if ascii) + * Returns success or failure + * + * Used by scheme1 for special case of copy bill+fred bill, + * copy ref.lst+*.lst etc + * + * Uses/sets static variables - + * dfh destination file handle + */ +MLOCAL BOOLEAN lseek(dest) +REG BYTE *dest; /* destination filename */ +{ + LONG lsize; + BOOLEAN seof; + WORD ret; + REG UWORD u, i; + + if(!d_check(dest)) { + crlf(); + return (FAILURE); /* invalid drive */ + } + + /* dont need to read files date and time as always concat case */ + /* but must set todays date */ + + touch(dest); /* set timestamp */ + + dfh=ms_x_open(dest,OPEN_RDWR); /* open file for read and write */ + +/* if(dfh==ED_FILE) */ /* if file doesnt exist, create it */ +/* return(dopen(dest)); */ /* not necessary as src/dest must exist as found by ms_x_first */ + + if(dfh < 0) { + e_check2(dfh); /* error (not necessary to set dfailed) */ + return (FAILURE); + } + + dstopen=YES; /* dest in now open */ + + if(sascii) { /* ascii file so look for 1st ^Z */ + lsize=0; + seof=NO; + do { /* do while !seof */ + u=ret=far_read(dfh, bufaddr, bufsize); /* read a buffer full */ + if((u&(-256))==(-256)) { /* if error */ + e_check2(ret); + return (FAILURE); + } + + i = findeof(bufaddr, u); /* if FINDEOF returns a */ + if(i < u) { /* count less than AMOUNT */ + seof=YES; /* then end of transfer */ + u = i; /* using the updated size */ + } + + if(u!=bufsize) /* if not full */ + seof=YES; /* then eof */ + + lsize += u; + + } while (!seof); /* lsize = size of file up to 1st ^Z (or total size if no ^Z) */ + + if(ms_x_lseek(dfh,lsize,0) < 0) /* lseek to ^Z or end of file (mode 0) */ + return (FAILURE); /* if error */ + + } + else { /* binary file so just lseek to end */ + lsize=0; + if(ms_x_lseek(dfh,lsize,2) < 0) /* lseek to end of file (mode 2) */ + return (FAILURE); /* if error */ + } + + return (SUCCESS); +} + +/* + * Checks whether the filespecs are different + * (src and dest are explicit filespecs (ie not wild)) + * Actually just checks relative filespec, taking drive into account + * (ie doesnt check full absolute filespecs) + * As per msdos + * + * Actually that isn't as per msdos - now we expand to physical path + * to catch SUBST drives, absolute filespecs etc. + * + * Prints message if same file, and returns YES or NO + */ +MLOCAL BOOLEAN samefs(src,dest,mess) +REG BYTE *src,*dest; +BOOLEAN mess; +{ +#if 1 +BYTE sp[MAX_PATHLEN+MAX_FILELEN+3]; +BYTE dp[MAX_PATHLEN+MAX_FILELEN+3]; + + ms_x_expand(sp, src); + ms_x_expand(dp, dest); + + if(strcmp(sp,dp)!=0) + return (NO); + +#else +/* EJH 27-11-90 START */ + + BYTE sd,dd; + + sd=drive + 'a'; /* assume current drive */ + dd=sd; + + /* if either src or dest end in a dot, remove dot */ + if(*src && src[strlen(src)-1]=='.') + src[strlen(src)-1]='\0'; + if(*dest && dest[strlen(dest)-1]=='.') + dest[strlen(dest)-1]='\0'; + + if(strlen(src)>2 && src[1]==':') { + sd=src[0]; /* get drive */ + src=src+2; /* skip drive */ + } + + if(strlen(dest)>2 && dest[1]==':') { + dd=dest[0]; /* get drive */ + dest=dest+2; /* skip drive */ + } + + if(sd!=dd) + return (NO); + + if(strcmp(src,dest)!=0) + return (NO); + +/* EJH 27-11-90 END */ +#endif + if(mess) { + if(concat) + eprintf(MSG_DLOST); + else + eprintf(MSG_CPYSELF); + } + + if(srcopen) /* if same file, close src */ + ms_x_close(sfh); /* as this is always an error return */ + /* or a special case */ + return (YES); +} + + +/* + * Checks for single physical floppy disk drive, + * with src and dest being different diskettes + */ +MLOCAL BOOLEAN ABcheck(src,dest) +REG BYTE *src,*dest; +{ + BYTE sd,dd; + + sd=drive+'a'; /* assume current drive */ + dd=sd; + + if(strlen(src)>2 && src[1]==':') + sd=src[0]; /* get drive */ + + if(strlen(dest)>2 && dest[1]==':') + dd=dest[0]; /* get drive */ + + /* should do logical to physical drive conversion */ + /* sd=pdrive(sd-'a')+'a' etc */ + + if(sd>'b' || dd>'b' || sd==dd) + return (NO); /* either src or dest is not floppy, */ + /* or they are on the same disk */ + /* then 'normal' case */ + /* reasonably safe to assume only A and B can be mapped onto a single physical floppy disk */ + + return (YES); /* single physical floppy drive special case */ + /* src and dest possibly on different diskettes */ + /* Returns YES even if there are two physical floppy disk drives */ +} + +/* + * Prints name of source file copied (in upper case) + * and handles msdos pecularities + * eg + * \fred prints out as a:\fred + * ie adds drive if 1st char = pathchar + */ +MLOCAL VOID prtsrc(src) +REG BYTE *src; +{ + strupr(src); /* convert to upper case */ + if(*src==*pathchar && src[1] != *pathchar) + printf("%c:", drive+'A'); + + printf("%s\n",src); + strlwr(src); /* convert back to lower case */ + return; +} + +/* Confirm copy message routine + * prints filename and asks Y/N + * returns TRUE if confirmed + */ +MLOCAL BOOLEAN conf_src(src) +REG BYTE *src; +{ +BOOLEAN answer; + + strupr(src); /* convert to upper case */ + + /* could do *src==*pathchar check etc as per prtsrc */ + + printf(MSG_ERAQ,src); /* same format as delq message */ + answer = yes(YES,NO); /* get answer, default = NO */ + + strlwr(src); /* convert back to lower case */ + return(answer); +} + + +MLOCAL VOID e_check2(ecode) /* e_check() + CR/LF */ +REG WORD ecode; +{ + e_check(ecode); + crlf(); + return; +} + +/* + * modifies file s's timestamp to todays date and time + * s maybe wild + */ +MLOCAL BOOLEAN touch (s) +REG BYTE *s; +{ + SYSDATE tdate; + SYSTIME ttime; + + WORD fh; + + ms_getdate(&tdate); + ms_gettime(&ttime); + + /* covert todays date to timestamp format */ + /* date = (year-1980)*512 + month*32 + day */ + /* time = hour*2048 + minute*32 + second/2 */ + + date=((tdate.year-1980)<<9) + (tdate.month<<5) + tdate.day; + time=(ttime.hour<<11) + (ttime.min<<5) + (ttime.sec>>1); + + if((fh=ms_x_open(s,OPEN_RDWR)) >=0) { /* open file for r/w if no error */ + ms_x_datetime(1,fh,&time,&date); /* change files timestamp */ + ms_x_close(fh); + return (SUCCESS); + } + else { + e_check2(fh); /* if error */ + return (FAILURE); + } +} + +#if defined(PASSWORD) +MLOCAL BYTE * get_pswd(s) /* return ptr to password part of s */ +REG BYTE *s; /* (including the ';' ) */ + /* return ptr to '\0' if no password */ +{ + while(*s) { /* while not at end */ + if(*s == *pwdchar) /* if next char is password delimiter */ + return (s); /* return its address */ + s ++; /* else goto next position */ + } + return (s); /* if end, return ptr to '\0' terminator */ +} +#endif diff --git a/COMMAND/COMINT.C b/COMMAND/COMINT.C new file mode 100644 index 0000000..543fa36 --- /dev/null +++ b/COMMAND/COMINT.C @@ -0,0 +1,2173 @@ +/* +; File : $Workfile: COMINT.C$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +*/ + +#include "defines.h" +#include + +#if defined(MWC) && defined(strlen) +#undef strcmp /* These are defined as macros in string.h */ +#undef strcpy /* which are expaneded in line under */ +#undef strlen /* Metaware C. These undefs avoid this. */ +#endif + +#include +#include + +#if !defined(DOSPLUS) +#include +#include +#include +#endif + +#include "command.h" /* COMMAND Definitions */ +#include "dos.h" /* MSDOS Functions */ +#include "dosif.h" /* DOS interface definitions */ +#include "toupper.h" +#include "support.h" /* Support routines */ +#include "global.h" + +/*RG-00-*/ +#if !defined(NOXBATCH) +#if !defined(NOSECURITY) && (defined(CDOSTMP) || defined(CDOS)) +#define PATH_LEN 65 /* max path length (null terminated) */ +#include "security.h" +#include "login.h" +#include "txlogin.h" +#endif +#endif /*NOXBATCH*/ +/*RG-00-end*/ + +EXTERN VOID CDECL restore_error_mode(); + +EXTERN VOID batch_start(BYTE *, BYTE *, BYTE *); +EXTERN VOID batch_end(VOID); /* BATCH.C */ +EXTERN VOID batch_close(VOID); /* BATCH.C */ + +MLOCAL VOID erase(BYTE *, BOOLEAN); /* COMINT.C */ +MLOCAL BYTE * date_format(UWORD); /* COMINT.C */ +MLOCAL BOOLEAN check_date(BYTE *); /* COMINT.C */ +MLOCAL BOOLEAN check_time(BYTE *); /* COMINT.C */ +MLOCAL VOID show_crlf(BOOLEAN); /* COMINT.C */ + +/*RG-02-*/ +#if !defined(NOXBATCH) +GLOBAL VOID CDECL cmd_pauseerr(BYTE *); /* COMINT.C */ +/*RG-02-end*/ +#endif +GLOBAL VOID CDECL cmd_pause(BYTE *); /* COMINT.C */ +GLOBAL VOID CDECL cmd_set(BYTE *); /* COMINT.C */ +GLOBAL VOID CDECL cmd_vol(BYTE *); /* COMINT.C */ + +EXTERN WORD CDECL findfile(BYTE *, UWORD *); /* DOSIF.A86 || COM.C */ +EXTERN VOID CDECL int_break(VOID); /* COM.C */ +EXTERN VOID docmd(BYTE *, BOOLEAN); /* COM.C */ + +#if defined(CPM) +EXTERN UWORD CDECL cpm_de_init(VOID); /* CP/M Clean-Up Routine*/ +#endif + + +MLOCAL WORD linesleft; /* Remaining lines on Screen */ +MLOCAL WORD ret; /* general BDOS return code */ + + +#if defined(CDOSTMP) || defined(CDOS) +/*.pa*/ +/* + * USER BEWARE + * + * A process descriptor exists in both DOS Plus and Concurrent + * DOS. But is an internal Structure in DOS Plus and should only + * be used with the upmost care. + */ +EXTERN PD FAR * CDECL pd; /* Far pointer to Current PD */ + +/* + * The following command will enable APPEND processing and set + * path searched by the BDOS on every OPEN function call. + * + * APPEND[=][d:]path[[;[d:]path]..] | [;] [/X|/E] + * + * APPEND without any command line options will display the current + * search path while APPEND ; will remove the Search Path and disable + * the APPEND facility. + * + * /E Forces the search path to be saved in the environment under + * Concurrent DOS this is always true and this flag is ignored. + * + * /X Forces APPEND to be active for the SEARCH FIRST(0x11), + * FIND FIRST(0x4E) and EXEC(0x4B) functions. In addition + * to the normal functions FCB OPEN(0x0F), FCB FileSize(0x23) + * and OPEN(0x3D). + * /B Forces APPEND to provide batch command compatible output + * that when redirected to a file, can be used to regenerate a + * given append state. + */ + +MLOCAL BYTE msg_appeq [] = "APPEND="; /* Static Environment String */ + +/*RG-03*/ +#if !defined(NOXBATCH) && (defined(CDOS) || defined(CDOSTMP)) +#define APPEND_BAT (flags & 4) /* /B Append Option */ +#endif +/*RG-03-end*/ +#define APPEND_X (flags & 2) /* /X Append Option */ +#define APPEND_E (flags & 1) /* /E Append Option */ + +GLOBAL VOID CDECL cmd_append(path) +REG BYTE *path; +{ + REG BYTE *s; + UWORD flags; /* Command Flags */ +#if !STACK + BYTE sbuf[MAX_ENVLEN]; +#endif + +#if defined(CDOS) || defined(CDOSTMP) + if (f_check (path, "exb", &flags, NO)) /* Check for valid Flags */ +#else + if (f_check (path, "ex", &flags, NO)) /* Check for valid Flags */ +#endif + return; + + zap_spaces(path); /* Remove White Space */ + if(!*path && !APPEND_X) { + if(env_scan(msg_appeq, s = (BYTE *)heap())) /* look for current value */ + s = NULLPTR; + + if(s && (pd->P_SFLAG & PSF_APPEND)) { /* If a path exists and the */ + printf(msg_appeq); /* Append bit is set in the */ + puts(s); + } +/*RG-03*/ + else { /* PD then display path */ +#if !defined(NOXBATCH) && (defined(CDOS) || defined(CDOSTMP)) + if (APPEND_BAT) + printf("APPEND="); + else +#endif + printf(MSG_APPEND); + } +/*RG-03-end*/ + + crlfflg = YES; + return; + } + + pd->P_SFLAG |= APPEND_X ? PSF_XAPPEND : 0; + + if(*path == '=' || *path == ';')/* Skip Leading '=' or ';' chars */ + path++; /* and disable the APPEND command */ + /* if no path is specified. */ + + if(*path) { /* Assign APPEND Path */ + pd->P_SFLAG |= PSF_APPEND; /* Set the APPEND and XAPPEND Bits */ + +#if STACK + s = stack(strlen(msg_appeq) + strlen(path) + 1); +#else + s = &sbuf[0]; +#endif + strcpy(s, msg_appeq); /* build command line for "SET" */ + strcat(s, strupr(path)); /* Force Path to UPPER case */ + cmd_set(s); /* set new path using "SET" */ + } + else if(!APPEND_X) { /* Disable APPEND Processing */ + pd->P_SFLAG &= ~(PSF_APPEND | PSF_XAPPEND); + cmd_set(msg_appeq); + } +} +#endif + +#if !defined(EXT_SUBST) + +/*.pa*/ +/************************************************************************/ +/* */ +/* ASSIGN (x [=] y ...) [/a][/b] */ +/* */ +/* This command forces future references to the X: to physically */ +/* reference the Y: drive. */ +/* */ +/* When no command line parameters are given then all assignments */ +/* are removed. If the /A option is used the current drive */ +/* assignments are displayed. For the purpose of the display and */ +/* remove functions an "ASSIGNed" drives is any physical drive */ +/* which does not reference itself. */ +/* */ +/************************************************************************/ + +/* + * ASSIGN_DRV returns TRUE if the drive pointed to by BP + * is a valid physical drive. + */ +MLOCAL BOOLEAN assign_drv(bp) +BYTE *bp; +{ + if(!d_check(bp)) + return FALSE; + + if(physical_drvs() & (1L << ddrive)) + return TRUE; + + e_check(ED_DRIVE); + return FALSE; +} + + +/*RG-03*/ +#define ASSIGN_BAT (flags & 2) /* Display Current Assignments in batch form */ +/*RG-03-end*/ +#define ASSIGN_ALL (flags & 1) /* Display Current Assignments */ + +GLOBAL VOID CDECL cmd_assign(s) +REG BYTE *s; +{ + BYTE temp[7]; /* Temporary Command Buffer */ + BYTE path[MAX_PATHLEN]; + BYTE src, dst; + ULONG vec,pvec,lvec,nvec; + UWORD drv; + UWORD flags; /* Command Flags */ + WORD ret; /* General purpose variable */ + + if (f_check (s, "ab", &flags, NO)) /* Check for Flags if any are */ + return; /* invalid then don't do it */ + + pvec = physical_drvs(); + lvec = logical_drvs(); + + /* + * Display the current drive assignments. + */ +/*RG-03*/ + if((ASSIGN_ALL)||(ASSIGN_BAT)) + { + vec = 1L; + drv = 0; + while(drv < 26) { + if((lvec & vec) && (pdrive(drv) != drv)) { + if (ASSIGN_BAT) + printf("ASSIGN %c = %c\n", drv+'A', pdrive(drv)+'A'); + else +/*RG-03-end*/ + printf("%c: => %c:\n", drv+'A', pdrive(drv)+'A'); + } + vec <<= 1; + drv++; + } + return; + } + + /* + * Remove ALL drive assignments. + */ + s = deblank(s); /* If no command line options */ + if(!*s) { /* are given then remove the */ + /* current assignments. */ + vec = 1L; + drv = 0; + while(drv < 26) { + if((lvec & vec) && (pdrive(drv) != drv)) { + sprintf(temp, "%c:=%c:", drv+'A', drv+'A'); + ms_x_chdir(temp); + } + vec <<= 1; + drv++; + } + return; + } + + /* + * Scan the command line and make all the drive assignments + * specified by the user. + */ + do { + dst = *s++; /* Get the Destinaion */ + s = deblank(s); + if(*s == '=') /* Skip the optional '=' */ + s = deblank(s+1); /* character and get the source */ + + if(!*s) { /* if no second drive has been */ + syntax(); /* specified the return error */ + return; + } + + src = *s++; + sprintf(temp, "%c:=%c:", dst, src); + +#if defined(DOSPLUS) + nvec = network_drvs(); + if ((nvec & (1L << (toupper(src)-'A'))) + || (nvec & (1L << (toupper(dst)-'A')))) { + eprintf(MSG_NETASSIGN); /* if either is remote */ + return; /* complain and exit */ + } +#endif + if(assign_drv(temp) && assign_drv(temp+3)) { + ret = ms_x_chdir(temp); + if (ret) { + e_check(ret); + return; + } + } + else + return; + + sprintf (path, "%c:%c", dst, *pathchar); + ms_x_curdir (tolower(src) - 'a'+1, path+3); + /* set dst drive to cur path on */ + /* source */ + ms_x_chdir (path); + + s = deblank(s); /* Deblank the renmainder of */ + } while(*s); /* command line and repeat */ +} +#endif + + +/* + * The CALL command accepts the name of a batch file with an + * optional parameter list. Any current batch processing is + * halted and the new batch file is used until the EOF is reached + * or an EXIT command is executed. Control then passes back to + * the original Batch file. + */ + +EXTERN UWORD CDECL heap_size(VOID); + +GLOBAL VOID CDECL cmd_call(line) +REG BYTE *line; +{ + BYTE path[MAX_FILELEN]; + UWORD loadtype; + BYTE argv0[MAX_FILELEN]; + BYTE *s; + + heap_get(0); /* check for stack overflow */ + + s = get_filename(path, deblank(line), NO); + + strcpy(argv0, path); + strlwr(path); + + if((ret = findfile(path, &loadtype)) >= 0) { + if(loadtype == BAT_FILETYPE) { /* treat .BAT differently */ + batch_start(argv0, path, s); /* nested batch files */ + return; + } + } + + line = deblank(line); + + docmd(line,YES); /* call normal code */ +} + +/* + * Display the current directory assignment of a logical drive + * Currently the Absolute path is specified with the physical drive + */ +/*RG-03*/ +#define CHDIR_BAT (flags & 2) /* Display dir in command line compatible form */ + +#if !defined(NOXBATCH) && (defined(CDOS) || defined(CDOSTMP)) +MLOCAL VOID display_cd(drv,flags) +#else +MLOCAL VOID display_cd(drv) +#endif +REG WORD drv; +#if !defined(NOXBATCH) && (defined(CDOS) || defined(CDOSTMP)) +UWORD flags; /* Command Flags */ +#endif +{ +BYTE dispbuf[MAX_PATHLEN]; +WORD ret; + + dispbuf[0] = (BYTE) (drv + 'A'); /* Display the path of the */ + dispbuf[1] = ':'; /* requested drive */ + dispbuf[2] = *pathchar; + + ret = ms_x_curdir(drv+1, dispbuf+3); + if (ret < 0) return; + +#if !defined(NOXBATCH) && (defined(CDOS) || defined(CDOSTMP)) + if (CHDIR_BAT) + printf ("CHDIR %s\n", dispbuf); + else +#endif + printf ("%s\n", dispbuf); +} +/*RG-03-end*/ + + +#define CHDIR_ALL (flags & 1) /* Display Current Assignments */ + +GLOBAL VOID CDECL cmd_cd(s) +REG BYTE *s; +{ + BYTE *cp; + ULONG login; /* Login Vector */ + WORD ret; /* General purpose variable */ + UWORD flags; /* Command Flags */ + +/*rbf remove trailing spaces from string 's'*/ +char *p = s; + +while ( (*p!=' ') && *p) + p++; +*p=0; +/*rbf-end*/ + +#if defined(CDOS) || defined(CDOSTMP) + if (f_check (s, "ab", &flags, NO)) /* Check for valid Flags */ +#else + if (f_check (s, "a", &flags, NO)) /* Check for valid Flags */ +#endif + return; /* invalid then don't do it */ + + if(CHDIR_ALL) { /* Display the current drive */ + + for(ret = 0; ret < 26; ret++) +/*RG-03*/ +#if !defined(NOXBATCH) && (defined(CDOS) || defined(CDOSTMP)) + display_cd(ret,flags); +#else + display_cd(ret); +#endif +/*RG-03-end*/ + + return; + } + + cp = s = deblank(strlwr(s)); /* Deblank after the Flag Check */ + + if(*(s+1) == ':') { /* check for a drive specifier */ + ddrive = *s - 'a'; /* Get the drive letter and check */ + s = deblank(s+2); /* that it is a valid drive and */ + /* is not the LOAD Drive. */ + + if(INVALID_DRV(ddrive)) { + e_check(ED_DRIVE); + return; + } + } + else + ddrive = drive; /* Use the default drive */ + + if(*s == '=') { /* Floating Drive Assignment */ + if(*++s) { /* Check source drive if spec. */ + if((s = d_check(s)) == 0)/* Abort if an illegal drive is */ + return; /* selected. */ + + if(!*s) /* If the command is of the form */ + strcpy(s, "."); /* x:=y: then append a "." */ + } + } + else if(!*s) { /* Display the selected drives */ + if(d_check(cp)) /* current sub-directory. */ +/*RG-03-*/ +#if !defined(NOXBATCH) && (defined(CDOS) || defined(CDOSTMP)) + display_cd(ddrive,flags); +#else + display_cd(ddrive); +#endif +/*RG-03-end*/ + return; + } + + if (*cp == '.') { + while (cp[1] == 32) { + ret = 1; + while (cp[ret]) { + cp[ret] = cp[ret+1]; + ret++; + } + } + } + /* Make the drive Assignment */ + if (!d_check(cp)) ddrive = -1; + e_check(ddrive != -1 ? ms_x_chdir(cp) : ED_DRIVE); +} + + +#if !defined(EXT_SUBST) + +/*.pa*/ +#define SUBST_DEL (flags & 1) +/*RG-03-*/ +#if !defined(NOXBATCH) && (defined(CDOS) || defined(CDOSTMP)) +#define SUBST_BAT (flags & 2) +#endif +/*RG-03-end*/ + +GLOBAL VOID CDECL cmd_subst(s) +BYTE *s; +{ + BYTE cp[MAX_FILELEN+3]; /* CHDIR Path Buffer */ + BYTE root[4]; + ULONG login; /* Logical Drive Vector */ + UWORD flags; /* Command Flags */ + UWORD drv; + WORD i; + +#if defined(CDOS) || defined(CDOSTMP) + if(f_check(s, "db", &flags, NO)) /* Check for Flags if any are */ +#else + if(f_check(s, "d", &flags, NO)) /* Check for Flags if any are */ +#endif + return; /* invalid then don't do it */ + + s = deblank(strlwr(s)); /* Deblank after the Flag Check */ + + if(!*s) { /* If the command line is blank */ + login = logical_drvs(); /* then display the assignments */ + /* for all the logical drives */ + + for(drv = 0; drv < 26; drv++, login >>= 1) + if(login & 1L) { + sprintf(root,"%c:\\", drv+'A'); + ms_x_expand(cp, root); +/*RG-03*/ +#if !defined(NOXBATCH) && (defined(CDOS) || defined(CDOSTMP)) + if(SUBST_BAT) + printf("SUBST %c: %s\n", drv + 'A',cp); + else +#endif +/*RG-03-end*/ + printf("%c: => %s\n", drv + 'A',cp); + } + + return; + } + + if(*(s+1) == ':') { /* Check for a drive specifier */ + ddrive = *s - 'a'; /* Get the drive letter and check */ + s = deblank(s+2); /* that it is a valid drive and */ + /* is not the LOAD Drive. */ + + if(INVALID_DRV(ddrive)) { + e_check(ED_DRIVE); + return; + } + } + else { + syntax(); /* If no drive is specified then */ + return; /* return after displaying a */ + } /* syntax error message */ + +#if defined(DOSPLUS) + if(network_drvs() & (1L << ddrive)) { /* if requested drive is */ + eprintf(MSG_NETSUBST); /* remote then complain */ + return; /* and don't do anything */ + } +#endif + sprintf(cp, "%c:=", ddrive+'A'); /* Prepare CHDIR command */ + + if(!SUBST_DEL) { /* Check for the Delete Flag */ + strcat(cp, s); + if((s = d_check(s)) == 0) /* Abort if an illegal drive */ + return; /* is selected. */ + + if(!*s) { /* If no PATH is specified then */ + printf(MSG_INOP); /* display display error message. */ + return; + } + } + + e_check(ms_x_chdir(cp)); /* Make the drive Assignment */ +} +#endif + +/*.pa*/ +/* + * DATE [DD/MM/YY] + * + * Display or Set the current date making full use of the DOS + * international system call. + */ + +GLOBAL VOID CDECL cmd_date(s) +BYTE *s; +{ + BYTE buffer[18]; /* Local Input Buffer */ + + if (*s) { + if(check_date(s)) + return; + printf (INV_DATE); + } + else { + printf (CUR_DATE); + disp_sysdate(); + } + + FOREVER { + printf (NEW_DATE, date_format(country.dt_fmt)); + buffer[0] = sizeof(buffer) -2; /* Set maximum string length */ + system(MS_C_READSTR, buffer); + crlf (); + + if (buffer[1] == 0) /* Check for 0 length input */ + return; /* and return if so */ + + buffer [buffer[1]+2] = '\0'; + if (check_date (buffer+2)) + return; + + printf (INV_DATE); + } +} + + +MLOCAL BYTE * date_format(fmt) +UWORD fmt; +{ + switch (fmt) + { + case 1: return EURO_DATE; + case 2: return JAP_DATE; + default: break; + } + + return US_DATE; +} + + + +/* + * Parse the string pointed to by s and check for a valid date + * specification. If the date has been specified correctly then + * set the system date. + */ + +MLOCAL BYTE date_sep[] = "/.-"; + +MLOCAL BOOLEAN check_date(s) +BYTE *s; +{ + SYSDATE date; + WORD p1, p2, p3; /* Input Parameters */ + + deblank(s); /* Remove spaces */ + + if (!getdigit (&p1, &s) || + !strchr(date_sep, *s++) || + !getdigit (&p2, &s) || + !strchr(date_sep, *s++) || + !getdigit (&p3, &s)) + { + return NO; + } + + switch (country.dt_fmt) { + case 1: /* European Format dd/mm/yy */ + date.day = p1; + date.month = p2; + date.year = p3; + break; + + case 2: /* Japanese Format yy/mm/dd */ + date.day = p3; + date.month = p2; + date.year = p1; + break; + + default: /* US Format mm/dd/yy */ + date.day = p2; + date.month = p1; + date.year = p3; + break; + } + + if (date.year >= 80 && date.year <= 99) + date.year += 1900; + + return !ms_setdate(&date); +} + + +/*.pa*/ +/* + * DEL [d:][path][filename][.ext] + * + * Erase a file(s) as specified by the path if no path is given + * erase all files on the default|specified drive. + */ +GLOBAL VOID CDECL cmd_del(path) +BYTE *path; +{ + erase (path, NO); /* erase files, don't confirm */ +} + +#define DIR_DIR (0x0001) /* Display Directory Files */ +#define DIR_SYS (0x0002) /* Display System Files */ +#define DIR_ALL (0x0004) /* Display ALL Files */ +#define DIR_WIDE (0x0008) /* Wide Directory Listing */ +#define DIR_LONG (0x0010) /* Long Directory Listing */ +#define DIR_PAGE (0x0020) /* Page Output */ +#define DIR_REM (0x0040) /* Remember these Options */ +#define DIR_CHANGE (0x0080) /* Change the Default Opts */ +#define DIR_NOPAGE (0x0100) /* No Paging of Output */ +#define DIR_2COLS (0x0200) /* double column listing */ +#define OPT(x) (flags & x) /* Return Flag Conditions */ + +MLOCAL UWORD dir_default = DIR_DIR | DIR_LONG; + +MLOCAL UWORD dir_flags(flags) +REG UWORD flags; +{ + if(OPT(DIR_NOPAGE)) /* Force DIR_PAGE to be cleared */ + flags &= ~DIR_PAGE; /* if NOPAGE has be selected */ + + if(OPT(DIR_LONG)) { /* Force DIR_WIDE to be cleared */ + flags &= ~DIR_WIDE; /* if the LONG format has been */ + flags &= ~DIR_2COLS; /* selected. */ + } + + if(OPT(DIR_2COLS)) { + flags &= ~DIR_LONG; + flags &= ~DIR_WIDE; + } + + if(page_wid < 76) /* Check the screen is wide */ + flags &= ~DIR_WIDE; /* enough to display directory */ + + if(page_wid < 78) + flags &= ~DIR_2COLS; + + if(OPT(DIR_DIR)) + flags &= ~DIR_SYS; + /* Check if the new options */ + if(OPT((DIR_CHANGE|DIR_REM))) { /* should become the default */ + dir_default = flags & ~(DIR_CHANGE|DIR_REM); + } + + if (flags) return(flags); + else return(dir_default); +} + + +GLOBAL VOID CDECL cmd_dir (cmd) +REG BYTE *cmd; +{ + WORD nfiles, system, others, i; + LONG nfree = 0L; + DTA search; + BYTE path[MAX_FILELEN]; + BYTE s[MAX_PATHLEN], temp[3]; + BYTE *ext, *memory; + UWORD free, secsiz, nclust; + UWORD flags; + + if(f_check (cmd, "dsawlprcn2", &flags, NO)) /* if any bad flags */ + return; /* don't do it */ + + flags = dir_flags(flags); /* Manipulate the flags to remove */ + /* duplication and conflicts */ + if(OPT(DIR_CHANGE)) /* Just change the default values */ + return; /* then return to the caller */ + + get_filename(path, deblank(cmd), YES); /* Extract the filename */ + + if (path[0]=='.' && path[1]=='.' && path[2]=='.' && path[3]=='\0') + { + path[0]='*'; + path[2]='\0'; + } + if (d_check(path) == NULLPTR) return;/* get out now if invalid drive */ + if (ddrive != -1) + { + strcpy(s,"d:"); s[0] = (BYTE) (ddrive + 'A'); + append_slash(s); + ms_x_curdir(ddrive+1,s+3); /* get the current dir */ + } + else + ms_x_expand(s,path); + + ext = fptr(path); + if(*ext == '.' && strcmp(dotdot+1, ext) && strcmp(dotdot, ext)) { + strcpy(heap(), ext); + strcpy(ext, "*"); + strcat(ext, heap()); + } + +#if defined(PASSWORD) + *(BYTE *)heap() = '\0'; /* Remove the Password */ + memory = strchr(ext, *pwdchar); /* if one has been used */ + if(memory) { /* and save on the heap */ + strcpy(heap(), memory); + *memory = '\0'; + } +#endif + + while(*ext && !strchr(ext, '.')) { /* If a filename has been */ + if(!iswild(ext)) { /* specified and it does not*/ + +#if defined(PASSWORD) + if (ddrive != -1 && ms_x_chdir(s) < 0) { + /* if cd to current dir fails then current dir must be password */ + /* protected. So let's do the next bit the non-novell way. */ + + /* This method of determining if the user has specified a directory */ + /* DOES NOT work on NOVELL drives. */ + + ret = ms_x_chmod(path, 0, 0); /* contain a '.'. Skip if */ + if(ret > 0 && (ret & ATTR_DIR)) /* a path was specified. */ + break; /* Otherwise append ".*". */ + + } + else { +#endif + /* This method of determining if the user has specified a directory */ + /* DOES work on NOVELL drives. */ + + /* But not when the current directory is password protected! */ + +#if defined(PASSWORD) + if (memory) strcpy(memory,heap()); /* reattach password */ +#endif + if (ddrive != -1) + { + ret = ms_x_chdir(path); /* try to cd to path specified */ +#if defined(PASSWORD) + if (memory) *memory = 0; /* remove password again */ +#endif + if (ret >= 0) { /* if there wasn't an error... */ + ms_x_chdir(s); /* ...restore original directory... */ + break; /* ...and get the hell out */ + } + } + else + { + ret = ms_x_chmod(path,0,0); + if (ret >= 0 && (ret & ATTR_DIR)) break; + } +#if defined(PASSWORD) + } +#endif + } + strcat(ext, ".*"); /* append ".*" to pathname */ + } + +#if defined(PASSWORD) + strcat(ext, heap()); /* Reattach the Password */ +#endif + + if(nofiles(path, ATTR_ALL, NO, YES)) /* if no files/dirs or error*/ + return; /* then we can't do this */ + + if (ddrive != -1) + { + strcpy (temp, "d:"); /* Display the drive Volume */ + temp[0] = (BYTE) (ddrive+'A'); /* label using the VOL command */ + cmd_vol(temp); + } + else + show_crlf(OPT(DIR_PAGE)); + +#if 0 + /* this has been done earlier */ + strcpy(s, "d:"); s[0] = (BYTE) (ddrive + 'A'); + append_slash(s); + ms_x_curdir(ddrive+1, s+3); /* Get the current dir */ +#endif + + strip_path(path, memory = (BYTE *)heap());/* Get the Path Spec and */ + if((i = strlen(memory)) > /* Remove the Trailing */ + (memory[1] == ':' ? 3 : 1)) /* Path Character. */ + memory[--i] = '\0'; + + if(i == 0 || (i == 2 && memory[1] == ':')) { + printf (MSG_DIR, temp, s+3); /* DIR of current Directory */ + } + else + { + if (ddrive == -1 || ms_x_chdir(s) < 0) { /* assume this means pword protected */ + ext = memory+strlen(memory)+1; + ms_x_expand(ext,memory); + if (ddrive != -1) + printf(MSG_DIR, temp, ext+3); + else + printf(MSG_DIR,"",ext+1); + } + else { + ms_x_chdir(memory); /* Change the directory */ + ms_x_curdir(ddrive+1, memory); /* Get the current directory */ + ms_x_chdir(s); /* Restore the directory */ + printf (MSG_DIR, temp, memory); + } + } + + others = 0; /* assume no SYS/DIR files */ + nfiles = 0; /* initialize file count */ + linesleft = page_len - 4; /* lines until pause */ + + system = OPT(DIR_SYS) ? ATTR_SYS : 0; + + ret = ms_x_first(path, ATTR_ALL, &search); + + if(!ret && (search.fattr & ATTR_DEV)) /* Check if the user has */ + ret = ED_FILE; /* specified a device then */ + /* generate an error. */ + while(!ret) { + if(!OPT(DIR_ALL) && (search.fattr & ATTR_SYS) != system) { + /* not the correct file type*/ + others++; /* remember others do exist */ + ret = ms_x_next(&search); /* get the next file and */ + continue; /* continue the display */ + } + + ext = strchr(search.fname, '.'); /* Get the file extension */ + if(ext && ext != search.fname) /* set the extension to NULL*/ + *ext++ = '\0'; /* if no '.' exists or this */ + else /* is the ".." or "." entry.*/ + ext = ""; + + if(OPT(DIR_WIDE)) { + if ((nfiles % 5) == 0) + show_crlf(OPT(DIR_PAGE)); + + printf ("%c:%c%-9s%-3s", + (nfiles % 5) ? ' ' : ddrive + 'A', + (search.fattr & ATTR_DIR) ? *pathchar : ' ', + search.fname, ext); + } + else { + if (OPT(DIR_2COLS)) { + if ((nfiles % 2) == 0) show_crlf(OPT(DIR_PAGE)); + } + else + show_crlf(OPT(DIR_PAGE)); + printf("%-9s%-3s", search.fname, ext); + if (search.fattr & ATTR_DIR) + printf(" "); + else + printf ("%9lu", search.fsize); + + if(search.fdate) { /* if timestamp exists */ + printf (" "); disp_filedate (search.fdate); + printf (" "); disp_filetime (search.ftime); + if ((OPT(DIR_2COLS)) && (nfiles%2 == 0)) printf (" "); + } + else { + if ((OPT(DIR_2COLS)) && (nfiles%2 == 0)) printf("\t\t\t"); + } + } + nfiles ++; + ret = ms_x_next(&search); + } + + if(others + nfiles == 0) { /* If no matching files then exit */ + e_check(ED_FILE); /* after displaying File Not Found */ + } + + if(ddrive != -1 && (ret = ms_drv_space(ddrive+1, &free, &secsiz, &nclust)) < 0) { + /*e_check(ED_PATH);*/ + /*return;*/ + ret = 0; /* This prevents 'Invalid directory...' when looking */ + /* at a PNW login drive. */ + } + + show_crlf(OPT(DIR_PAGE)); + nfree = (LONG)ret * (LONG)free * (LONG)secsiz; + if (ddrive != -1) + printf ("%9d %s%10ld %s", nfiles, MSG_FILES, nfree, MSG_FREE); + else + printf ("%9d %s", nfiles, MSG_FILES); + show_crlf(OPT(DIR_PAGE)); + + if(others) /* if others do exist, tell them */ + printf (MSG_EXIST, system ? MSG_NSYS : MSG_NDIR); +} + + +GLOBAL VOID CDECL cmd_echo(s, o) +REG BYTE *s; /* Deblanked Command Line */ +REG BYTE *o; /* Original Untainted Commmand */ +{ + + if (*o) o++; /* delete 1 whitespace or */ + /* punctuation char from the*/ + /* original command line */ + s = deblank(s); + + switch(onoff(s)) { /* if "ECHO=on/off" */ + case YES: /* ECHO = ON */ + echoflg = ECHO_ON; + break; + + case NO: /* ECHO = OFF */ + echoflg = ECHO_OFF; + break; + + default: + if(*s || (o != s && batchflg)) { /* if command line */ + puts(o); /* display string */ + crlf(); + } + else + printf (MSG_ECHO, /* print current */ + echoflg ? MSG_ON : MSG_OFF); /* echo status */ + break; + } +} +#if !defined(NOXBATCH) && (defined(CDOS) || defined(CDOSTMP)) +/*RG-02-*/ +GLOBAL VOID CDECL cmd_echoerr(s, o) +REG BYTE *s; /* Deblanked Command Line */ +REG BYTE *o; /* Original Untainted Commmand */ +{ + BOOLEAN err_save; + + err_save=err_flag; + err_flag = TRUE; + cmd_echo(s,o); + err_flag = err_save; +} +#endif +/*RG-02-end*/ + + +GLOBAL VOID CDECL cmd_exit(cmd) +BYTE *cmd; +{ + err_ret = 0; + + if(*deblank(cmd)) /* If a number has be */ + check_num(cmd, 0, 255, &err_ret); /* specified use this for */ + /* the exit code. */ + if(batchflg) { /* If processing a batch file */ + batch_end(); /* then exit batch file */ +#if defined(CDOSTMP) + return; +#endif + } + +#if defined(CDOSTMP) + bdos(C_DETACH, 0); /* Allow another process to attach */ + bdos(P_DISPATCH, 0); /* to the console if they are */ + bdos(C_ATTACH, 0); /* waiting in the background. */ + +#else + if(execed) { /* If command.com has been execed */ + *parent_psp = save_parent; + + ms_set_break(break_flag); /* then return to the invoking prog */ + /* Otherwise ignore the command */ + +#if defined(CPM) /* Clean-Up the CPM disk handling */ + cpm_de_init(); /* code before we terminate. */ +#endif + restore_error_mode(); + restore_term_addr(); /* restore the PSP terminate address*/ + ms_x_exit(err_ret); /* If we return from the EXIT call */ + execed = NO; /* then this must be the root */ + printf("Hello\n"); + } /* process. Invoked without '/P' */ +#endif +} + + +GLOBAL VOID CDECL cmd_md(s) +REG BYTE *s; +{ + /*BYTE path[MAX_FILELEN];*/ + + crlfflg = YES; +#if 0 + get_filename(path, deblank(s), FALSE); /* Pathname */ + + if(!d_check(path)) + return; +#endif + if((ret = ms_x_mkdir(s)) != 0) { /* if any errors occurred */ + if (ret == ED_DRIVE) /* if invalid drive */ + e_check(ret); /* then say so */ + else /* else use standard formula */ + eprintf(MSG_MKDIR); /* Unable to create directory*/ + return; + } + + crlfflg = NO; +} + + +/*.pa*/ +/* + * PATH [[d:]path[[;[d:]path]..]] | [;] + * + * Display or set the command search path in environment. + */ +GLOBAL BYTE msg_patheq [] = "PATH="; /* Static Environment String */ + +GLOBAL VOID CDECL cmd_path(path) +REG BYTE *path; +{ + REG BYTE *s; +#if !STACK + BYTE sbuf[MAX_ENVLEN]; +#endif + + zap_spaces(path); /* Remove all white space */ + if(!*path) { + if(env_scan(msg_patheq, s = (BYTE *)heap())) + printf(MSG_PATH); /* If no path exists then */ + else { /* display "NO PATH" otherwise */ + printf(msg_patheq); /* display the current path */ + /*printf("%.122s\n",s);*/ + printf(path_template,s); + } + crlfflg = YES; + return; + } + + if(*path == '=' || *path == ';')/* Skip Leading '=' or ';' chars */ + path++; /* then set the PATH */ + +#if STACK + s = stack(strlen(msg_patheq) + strlen(path) + 1); +#else + s = &sbuf[0]; +#endif + strcpy(s, msg_patheq); /* build command line for "SET" */ + strcat(s, strupr(path)); + cmd_set(s); /* set new path using "SET" */ +} + +GLOBAL VOID CDECL cmd_pause(msg) +BYTE *msg; +{ +BYTE c; + + if (*msg) printf("%s\n",msg); + + batch_close(); /* Close Any Batch files in case */ + /* the user is going to swap the */ + /* disk with the batch file. */ + printf(MSG_PAUSE); /* prompt to hit any key */ + +#if defined(CDOSTMP) + c =(BYTE) bdos(C_RAWIO, 0xFD); /* Get a character from console */ + + if ((c==0) ||(dbcs_lead(c))) + bdos(C_RAWIO, 0xFD); /* skip second byte in DBCS pair */ +#else + c = (BYTE) msdos(MS_C_RAWIN, 0);/* Get a character from console */ + if ((c==0) || (dbcs_lead(c))) + msdos(MS_C_RAWIN, 0); /* skip second byte in DBCS pair */ +#endif + + sprintf(heap(), "%s", MSG_PAUSE); /* Copy MSG_PAUSE into */ + printf("\r%*s\r", strlen(heap()), ""); /* Data Segment and */ + /* then calculate length*/ + + if(c == 0x03) /* Control C Check */ + int_break(); +} + +/* + * This PAUSE command will output the prompt string to STDOUT regardless + * of its destination. However it will ensure that the character is read + * from the console device by "POKING" the PSP. + */ +GLOBAL VOID CDECL cmd_stdin_pause(void) +{ +UWORD in_h,stderr_h; +BYTE c; + + batch_close(); /* Close Any Batch files in case */ + /* the user is going to swap the */ + /* disk with the batch file. */ + printf(MSG_PAUSE); /* prompt to hit any key */ + + stderr_h = psp_poke(STDERR,1); + in_h = psp_poke(STDIN, stderr_h); /* Get the Real Console */ + psp_poke(STDERR,stderr_h); + +#if defined(CDOSTMP) + c =(BYTE) bdos(C_RAWIO, 0xFD); /* Get a character from console */ + + if ((c==0) ||(dbcs_lead(c))) + bdos(C_RAWIO, 0xFD); /* skip second byte in DBCS pair */ +#else + c = (BYTE) msdos(MS_C_RAWIN, 0);/* Get a character from console */ + if ((c==0) || (dbcs_lead(c))) + msdos(MS_C_RAWIN, 0); /* skip second byte in DBCS pair */ +#endif + + psp_poke(STDIN, in_h); /* restore original handle */ + + sprintf(heap(), "%s", MSG_PAUSE); /* Copy MSG_PAUSE into */ + printf("\r%*s\r", strlen(heap()), ""); /* Data Segment and */ + /* then calculate length*/ + + if(c == 0x03) /* Control C Check */ + int_break(); +} + +#if !defined(NOXBATCH) && (defined(CDOS) || defined(CDOSTMP)) +/* + * The PAUSE command will output the prompt string to STDOUT regardless + * of its destination. However it will ensure that the character is read + * from the console device by "POKING" the PSP. + */ +GLOBAL VOID CDECL cmd_pauseerr() +{ + BOOLEAN err_save; + + err_save=err_flag; + err_flag = TRUE; + cmd_pause(); + err_flag = err_save; +} +#endif +/*RG-02-end*/ + +/*.pa*/ +/* + * PROMPT [prompt-text] + * + * Set the system prompt as specified by the prompt text if no + * prompt text is specified then the default $n$g is used. + */ +GLOBAL BYTE msg_prmeq [] = "PROMPT="; /* Static Environment String */ + +GLOBAL VOID CDECL cmd_prompt(s) +REG BYTE *s; +{ + REG BYTE *bp; +#if !STACK + BYTE bpbuf[MAX_ENVLEN]; +#endif + + if (!*s) /* if no string */ + s = DEFAULT_PROMPT; /* use the default */ + + while ((*s == '=') || (*s == ' ')) s++; + +#if STACK + bp = stack(strlen(msg_prmeq) + strlen(s) + 1); +#else + bp = &bpbuf[0]; +#endif + strcpy(bp, msg_prmeq); /* environment variable */ + strcat(bp, s); /* add new value */ + cmd_set(bp); /* update environment */ +} + + +GLOBAL VOID CDECL cmd_rem () +{ + crlfflg = 0; +/* Make sure REM turns off pipes too */ +/* You can't do this !!!!! MSDOS allows "REM | DIR" etc - IJ */ +#if 0 + pipe_in=pipe_out=NO; +#endif +} + + + +#define REN_CHECK (flags & 1) + +GLOBAL VOID CDECL cmd_ren(s) +REG BYTE *s; +{ + BYTE srcfile[MAX_FILELEN], dstfile[MAX_FILELEN]; + BYTE pattern[MAX_FILELEN-MAX_PATHLEN]; + BYTE *enddir; +#if defined(PASSWORD) + BYTE *password; +#endif + DTA search; + UWORD flags; + WORD attr; +#if !STACK + BYTE passbuf[MAX_FILELEN]; +#endif + char lastchar; + unsigned length; + + if(f_check(s, "c", &flags, NO)) /* Check the selected flags */ + return; /* and return on error */ + + s = get_filename(srcfile, deblank(s), TRUE); /* Source Filename */ + + s = get_filename(dstfile, deblank(s), TRUE); /* Destination File */ + + length = strlen(dstfile); + lastchar = dstfile[ length-1]; + + if (dbcs_expected()){ + if ( (length > 2) && (!dbcs_lead(dstfile[length-2])) ){ +/* + if ( (lastchar == ':') || (lastchar == '\\') ){ +*/ + if (lastchar == ':'){ + printf(msg_invalid_file); + return; + } + } + } + else{ +/* + if ( (lastchar == ':') || (lastchar == '\\') ){ +*/ + if (lastchar == ':'){ + printf(msg_invalid_file); + return; + } + } + + if (!iswild(srcfile)) { + attr = ms_x_chmod(srcfile,0,0); + if ((attr > 0) && (attr & ATTR_DIR)) { + + /* Don't try to rename directories. Leave it to RENDIR. */ + + printf(MSG_USE_RENDIR); + return; + } + } + + if(nofiles(srcfile, ATTR_ALL, YES, NO)) /* if no source files then */ + return; /* error message and stop */ + + if(nofiles(dstfile, ATTR_ALL, NO, NO)) /* Check the Destination */ + return; /* path exists */ + + if(fptr(srcfile) != srcfile && fptr(dstfile) == dstfile) { + strcpy(heap(), dstfile); /* If no path is specified */ + strip_path(srcfile, dstfile); /* on the NewFile then force*/ + strcat(dstfile, heap()); /* use the OldFile Path. */ + /* Because of the Holy Grail*/ + } /* of MS-DOS compatiblity. */ + + enddir = fptr(srcfile); /* Isolate source filename */ +#if defined(PASSWORD) + password = strchr(enddir, *pwdchar); /* Check for Source password*/ + if(password) { /* and save in internal buf.*/ +#if STACK + password = stack(strlen(password)+1); +#else + password = &passbuf[0]; +#endif + strcpy(password, strchr(enddir, *pwdchar)); + } +#endif + + strcpy(pattern, fptr(dstfile)); /* Save the destination */ + /* match pattern. */ + + ms_x_first (srcfile, (ATTR_STD&(~ATTR_SYS)), &search); + do { + strcpy(enddir, search.fname); /* append file name to path */ + + if(REN_CHECK) { /* confirm option active? */ + printf(MSG_ERAQ, srcfile); /* then prompt the user and */ + if(!yes(YES, NO)) /* act on the reponse */ + continue; + } + + strcpy(fptr(dstfile), pattern); /* Assert the Destination */ + repwild(srcfile, dstfile); /* pattern. */ + +#if defined(PASSWORD) + if(password) /* Append the password to */ + strcat(srcfile, password); /* the sorce file if one */ + /* has been specified. */ +#endif + + if((ret = ms_x_rename(srcfile, dstfile)) < 0) { + crlfflg = YES; +#if defined(CDOSTMP) || defined(CDOS) + if((ret == ED_ACCESS) && + (ms_x_first(dstfile, ATTR_ALL, &search) >= 0)) +#else + if(ret == ED_ACCESS) +#endif + eprintf(MSG_REN); + else + e_check(ret); + return; + } + } while(!ms_x_next(&search)); /* get the next file */ +} + + +/*.pa*/ +/* + * + */ +GLOBAL VOID CDECL cmd_rd(s) +REG BYTE *s; +{ + /*BYTE path[MAX_FILELEN];*/ + + crlfflg = YES; +#if 0 + get_filename(path, deblank(s), FALSE); /* Pathname */ + + if(!d_check(path)) + return; +#endif + if((ret = ms_x_rmdir(s)) != 0) { /* if can't remove directory */ + if(ret == ED_DIR || ret == ED_FILE || ret == ED_ACCESS) + /* because its in use by */ + eprintf(MSG_RMDIR); /* by another process or is */ + else /* empty then print special */ + e_check(ret); /* message other wise use */ + return; /* standard error handler */ + } + + crlfflg = NO; +} + + +GLOBAL VOID CDECL cmd_set(s) +BYTE *s; +{ + BYTE c; + REG BYTE *key; + BYTE *t; + WORD i; + + if(!*s) { /* if no cmd, display env */ + for(i=0; !env_entry(key = (BYTE *)heap(), i); i++) { + puts(key); /* Print the Environment */ + crlf(); /* variables directly to */ + } /* avoid size problems. */ + return; + } + /* else need to set env var */ + + /* msdos removes leading blanks, commas, semicolons and equal signs, + but keeps spaces in the variable name (SPR 770044) JBM */ + +/* remove any spaces before the equals sign + key = s; + while (*s && (*s != '=')) { + if (*s == 32 || *s == 9) { + t = s; + while (*t++) *(t-1) = *t; + } + if (*s == '=') break; + s++; + } +*/ + key = s; + while (*s && (*s == 0x20 || *s == 0x09 || *s == ',' || *s == ';' || *s == '=')) { + t = s; + while (*t++) *(t-1) = *t; + } + + s = key; + while (*s && (*s != '=')) /* look for end of variable */ + s ++; + + if (!*s || key == s) { /* If no key has been specified */ + syntax(); /* or the '=' is missing return */ + return; + } /* a syntax error. */ + + s++; + +#if 0 + /* msdos doesn't do this */ + + /* remove any space after the equals sign */ + while (*s == 32 || *s == 9) { + t = s; + while (*t++) *(t-1) = *t; + } +#endif + + c = *s; /* Save Character */ + *s = '\0'; /* terminate keyword */ + strupr (key); /* make keyword upper case */ + if(env_del(key) < 0) { /* remove it first */ + printf(MSG_ENVERR); /* check for an error. */ + crlfflg = YES; + return; + } + if((*s-- = c) != 0) { /* Add the definition to the end*/ + /* of the environment if the new*/ + if(env_ins(key)) { /* definition is not NULL */ + printf(MSG_ENVFULL); /* check for an error. */ + crlfflg = YES; + return; + } + } +} + + +/*.pa*/ +/* + * Displays or Sets the current system time + */ +#define TIME_CON (flags & 1) + +GLOBAL VOID CDECL cmd_time(s) +REG BYTE *s; +{ + BYTE buffer[18]; /* Local Input Buffer */ + UWORD flags; /* Continuous Display */ + + if(f_check (s, "c", &flags, NO)) /* Check for valid Flags */ + return; + + if(TIME_CON) { + crlfflg = YES; + printf(CUR_TIME); /* Display the Message */ + + FOREVER { + disp_systime (); /* Display the Current Time */ + printf("\b\b\b\b\b\b\b\b\b\b\b"); /* BackSpace over the Time */ +#if defined(CDOSTMP) + if(bdos(C_RAWIO, 0xFE)) /* check for a character */ + return; /* and return if one typed */ +#else + if(msdos(MS_C_STAT, 0) & 0xFF) { /* Check for a character */ + msdos(MS_C_RAWIN, 0xFF); /* read it and return to the*/ + return; /* main routine. */ + } +#endif + } + } + + if(*s) { + if (check_time(s)) + return; + printf(INV_TIME); + } + else { + printf(CUR_TIME); + disp_systime (); + } + + FOREVER { + printf (NEW_TIME); + buffer[0] = sizeof(buffer)-2; /* Set maximum string length */ + system(MS_C_READSTR, buffer); + crlf (); + + if (!buffer[1]) /* Check for 0 length input */ + return; /* and return if so */ + + buffer[buffer[1]+2] = '\0'; + if (check_time (buffer+2)) + return; + + printf (INV_TIME); + } +} + +/*.pa*/ +/* + * + */ +GLOBAL VOID CDECL cmd_truename(s) +REG BYTE *s; +{ + BYTE path[MAX_FILELEN]; + + *path = 0; + + /* expand path, current directory if none specified */ + if (*s) + ret = ms_x_expand(path, s); + else + ret = ms_x_expand(path, "."); + + /* if we get an error report it, otherwise display expanded path */ + if (ret) + e_check(ret); + else + printf(path); +} + + +/* + * Parse the string pointed to by s and check for a valid date + * specification. If the time has been specified correctly then + * set the system time. + */ +MLOCAL BYTE hour_sep[] = ":."; +MLOCAL BYTE sec_sep[] = ".,"; + +MLOCAL BOOLEAN check_time(s) +BYTE *s; +{ + SYSTIME time; + WORD hour, min, sec, hsec; + + min = sec = hsec = 0; /* Seconds and Hundredths are optional */ + /* and default to zero when omitted */ + zap_spaces(s); /* Remove all spaces from command */ + + if (!getdigit (&hour, &s)) + return NO; + + while(*s) { /* if more than HH */ + if (!strchr(hour_sep,*s)) return NO; /* Check for Minute */ + s++; + if (!getdigit (&min, &s)) return NO; + + if (!*s) break; + + if (!strchr(hour_sep,*s)) break; /* Check for Seconds */ + s++; + if (!getdigit (&sec, &s)) break; + + if (!*s) break; + + if (!strchr(sec_sep,*s)) break; + s++; + if (!getdigit (&hsec, &s)) break; + + break; + } + + if (*s) { + *s = toupper(*s); + if (*s == 'P' && hour != 12) hour += 12; + if (*s == 'A' && hour == 12) hour = 0; + } + + time.hour = hour; + time.min = min; + time.sec = sec; + time.hsec = hsec; + + return !ms_settime(&time); +} + +#define BUFSIZE 256 /* SHOW_FILE buffer size */ + +MLOCAL VOID show_crlf(paging) +BOOLEAN paging; +{ + crlf(); + if(paging && (--linesleft == 0)) { + cmd_pause(""); + linesleft = page_len - 1; + } +} + +/* + * Read from channel h until the first Control-Z or the endof file + * has been reached. The display is paged if the PAGE_MODE flag is + * true otherwise the information is displayed continuous using + * the standard flow control. + */ +/*RG-00-make this one public*/ +/* MLOCAL VOID show_file(h, paging) */ +VOID show_file(h, paging) +/*RG-00-end*/ +UWORD h; /* Channel for File access */ +BOOLEAN paging; /* Page Mode Flag */ +{ + BYTE FAR *cp; /* pointer to end of path */ + BYTE FAR *ptr; /* temporary address for printing */ + BYTE FAR *buf; /* Input Buffer */ + UWORD bufsize; + WORD n; + /*BOOLEAN lfflg = NO;*/ /* Last character a LineFeed */ + BOOLEAN eof = FALSE; /* End of File Flag */ + UWORD scr_width; + UWORD nchars = 0; + UWORD stderr_h,in_h; + + scr_width = get_scr_width(); + + mem_alloc(&show_file_buf,&bufsize,BUFSIZE,BUFSIZE); + buf = show_file_buf; + + while (!eof && (n = far_read (h, buf, BUFSIZE)) > 0) { + + cp = ptr = buf; + while (n) { /* while more data */ + + while (n && /* while more data */ + (*cp != 0x1a) && /* and not EOF Char */ + (*cp != '\n') && /* and Linefeed Char */ + (nchars= 0)); +} + +/* + * Displays the data read from Channel 0 until the end of file or + * Control-Z. If no output redirection is inforce then MORE pages + * the display using the CMD_PAUSE function. + * + * MORE will only enable PAGING if the output device is the CONSOLE + * otherwise paging is disabled. + */ +GLOBAL VOID CDECL cmd_more() +{ + linesleft = page_len -1; /* Set the Page length and */ + show_file(STDIN, YES); /* display STDIN till EOF */ + /* or a Control-Z */ +} + +/*.pa*/ +/* + * + */ +GLOBAL VOID CDECL cmd_ver() +{ + printf(MSG_VERSION, (env_scan("VER=", heap()) ? "" : heap())); + printf(MSG_CPYRIGHT); +#if !defined(FINAL) + if(!env_scan("BETA=", heap())) + printf("%s\n", heap()); +#endif +} + +GLOBAL VOID CDECL cmd_vol(path) +BYTE *path; +{ + BYTE *s; + BYTE temp[7]; + DTA search; + WORD ret,i; + BYTE label[12]; + + strcpy(temp,d_slash_stardotstar); + + if ((path = d_check(path)) == 0) + return; + if (ddrive == -1) return; + + temp[0] = (BYTE) (ddrive+'A'); + + ret = ms_x_first(temp, ATTR_LBL, &search); + if (ret == ED_DRIVE) + e_check(ret); /* display error if invalid drive */ + else { + printf(MSG_LBL, ddrive+'A'); + + if (ret) + printf(MSG_NOLBL); + else { + s = search.fname; + for (i = 0; *s && (i < 8); i++) + label[i] = (*s == '.') ? ' ' : *s++; + + if (*s == '.') s++; /* if there was a '.' skip it */ + for (; *s && (i < 11); ) label[i++] = *s++; /* copy the rest */ + label[i] = '\0'; /* null terminate label */ + + printf(MSG_OKLBL, label); + } + crlf(); + } +} + +/*.pa*/ +/* + * + */ +GLOBAL VOID CDECL cmd_delq(path) /* erase files with query */ +BYTE *path; +{ + erase (path, YES); /* erase files, confirm deletes */ +} + +EXTERN BYTE FAR * CDECL farptr(BYTE *); +#define YES_CHAR (*farptr(YES_NO+0)) +#define NO_CHAR (*farptr(YES_NO+1)) + +#define ERASE_CONFIRM (flags & 3) +#define ERASE_SYS (flags & 4) + +MLOCAL VOID erase(s, confirm) +BYTE *s; +BOOLEAN confirm; +{ + BYTE path[MAX_FILELEN]; /* FileName Buffer */ + BYTE answer[20]; /* Yes/No string */ + BYTE *files; /* pointer to file spec */ +#if defined(PASSWORD) + BYTE *password; +#endif + UWORD flags; /* only one switch permitted*/ + DTA search; /* Local Search Buffer */ + UWORD attr; /* Erase Search Attributes */ +#if !STACK + BYTE passbuf[MAX_FILELEN]; +#endif +#if !(defined (CDOSTMP)) + BYTE savepath[MAX_PATHLEN+1]; + BYTE newpath[MAX_PATHLEN+2]; /* including trailing \ */ + BYTE fcb[37]; + WORD ret; + WORD i; +#endif + + if(f_check(s, "cps", &flags, NO)) /* if any bad flags return */ + return; + + get_filename(path, s, YES); /* Extract the Filename */ + if(strlen(path) == 0) { /* and check for 0 length */ + printf(MSG_NEEDFILE); /* path caused by invalid */ + crlfflg = YES; /* filename characters in */ + return; /* the command line. */ + } + + if ((strcmp(path,dotdot+1) == 0) || (strcmp(path,dotdot) == 0)) { + strcat(path,d_slash_stardotstar+2); + } + +/* Neil's bodge */ +/* del d:. should be the same as del d:*.* */ + if (strlen(path)==3 && path[1] == ':' && path[2] == '.') { + path[2] = 0; + strcat(path,d_slash_stardotstar+3); + } +/* end of Neil's bodge */ + + attr = ATTR_STD & ~ATTR_SYS; /* Prevent SYS files from */ + attr |= ERASE_SYS ? ATTR_SYS : 0; /* being deleted unless the */ + /* /S option is specified. */ + + if(nofiles(path, attr, YES, YES)) /* if no files or error */ + return; /* then we can't do this */ + + files = fptr(path); /* isolate the filename */ + +#if defined(PASSWORD) + password = strchr(files, *pwdchar); /* Check for Source password*/ + if(password) { /* and save in internal buf.*/ +#if STACK + password = stack(strlen(password)+1); +#else + password = &passbuf[0]; +#endif + strcpy(password, strchr(files, *pwdchar)); + } +#endif + + confirm |= ERASE_CONFIRM; /* DELQ implies "/c" switch */ + if (!confirm && /* if not confirming anyway */ + (!strncmp(files, "*", 1)&& /* and all files specified */ + strstr(files, ".*"))) /* ie * at start of name & ext */ + { + printf(MSG_ERAALL); /* "Are you sure (Y/N)? " */ + answer[0] = sizeof(answer)-2; /* max. one character */ + answer[1] = 0; /* no command recall permitted */ + system (MS_C_READSTR, answer);/* read the response */ + crlf(); + if ((answer[2] & 0xdf) != YES_CHAR) { + crlfflg = YES; /* if not 'Y' or 'y' given */ + return; /* then return */ + } + } + + if(!confirm && ERASE_SYS && /* If no confirmation is required */ +#if !(defined (CDOSTMP)) + !iswild(path) && /* and this is an ambigous file */ +#endif + !ms_x_unlink(path)) /* specification and all the files*/ + return; /* are deleted without error then */ + /* return to the calling function */ + /* otherwise delete files */ + /* individually. */ + +#if !(defined (CDOSTMP)) +/* use fcb delete if no confirm and system files are not to be */ +/* deleted, since it's much quicker. Any problems, go and do it the */ +/* standard way so we can report on problem files. */ + + d_check (path); + if (ddrive != -1 && (!confirm) && (!ERASE_SYS) +#if defined(PASSWORD) + && (!password) +#endif + ) { + if (!d_check (path)) + return; + + if ((ms_f_parse (fcb, files, 0)) < 0) /* set up fname in fcb */ + goto fcbdel_end; + *fcb = ddrive+1; + + strcpy (savepath, "d:\\"); /* get curpath on relevant drive */ + *savepath = ddrive + 'A'; + ms_x_curdir (ddrive+1, savepath+3); + + strncpy (newpath, path, files - path); + /* extract new path */ + newpath[files - path] = '\0'; + + if ((i = strlen (newpath)) > (newpath[1] == ':' ? 3 : 1)) + newpath[--i] = '\0'; /* remove trailing backslash */ + + if (! ((i == 0) || ((i == 2) && (newpath[1] == ':'))) ) + if (ms_x_chdir (newpath)) + goto fcbdel_end; + + ret = ms_f_delete (fcb); + ms_x_chdir (savepath); + + if (!ret) + return; /* all done */ +fcbdel_end: + ; + } +#endif + + if (ms_x_first(path, attr, &search)) return; + do { + strcpy(files, search.fname); /* make it full file name */ + strcpy(heap(), path); /* copy to an internal */ +#if defined(PASSWORD) + if(password) /* buffer and append the */ + strcat(heap(), password); /* password if present */ +#endif + + if(confirm) { + printf(MSG_ERAQ, path); + if(!yes(YES, NO)) + continue; + } + + if((ret = ms_x_unlink(heap())) != 0) { + printf(MSG_ERA, path); + e_check(ret); + crlf(); + } + } while (!ms_x_next (&search)); +} + +#if defined(DOSPLUS) +/* + * The HILOAD command accepts a trailing command line. + * It will attempt to execute the command line, running any programs + * specified in high memory. + */ +GLOBAL VOID CDECL cmd_hiload(s) +REG BYTE *s; +{ +int region, i; + + s = deblank(s); + if (*s == 0) { + printf(msg_inop); + return; + } + + global_in_hiload++; + + if (global_in_hiload == 1) { + global_link = get_upper_memory_link(); + global_strat = get_alloc_strategy(); + region = 1; + + set_upper_memory_link(1); + + /* Look out for /L:r1[,s1][;r2[,s2]...] */ + /* We parse r1, and discard the rest */ + + if ((s[0]==*switchar)&&(toupper(s[1])=='L')&&(s[2]==':')&&isdigit(s[3])){ + region = s[3]-'0'; /* assume region is 1 digit */ + s += 4; /* skip what we parsed */ + while ((*s==';') || (*s==',') || isdigit(*s)) + s++; + s = deblank(s); /* deblank rest of line */ + } + + /* discard any /S we find (really we should minimise) */ + if ((s[0]==*switchar) && (toupper(s[1])=='S')) { + s += 2; /* skip the /S */ + s = deblank(s); /* deblank rest of line */ + } + + /* only bother if we have upper memory and are forcing location */ + if ((region > 1) && (get_upper_memory_link() != 0)) { + set_alloc_strategy(0x40); /* First fit high only */ + for(i=1;i 25 || (drv == *SYSDATB(SRCHDISK))) +#else +#define INVALID_DRV(drv) (drv < 0 || drv > 31) +#endif + +/* DOS file attribute bit masks */ + +#define ATTR_RO 0x0001 /* file is read/only */ +#define ATTR_HID 0x0002 /* file is hidden */ +#define ATTR_SYS 0x0004 /* file system is system */ +#define ATTR_STD (ATTR_SYS | ATTR_RO) +#define ATTR_ALL 0x0014 /* find all but labels & hidden */ +#define ATTR_LBL 0x0008 /* find labels */ +#define ATTR_DIR 0x0010 /* find directories, too */ +#define ATTR_DEV 0x0040 /* Attribute returned for Device*/ + +#define STDIN 0 /* Standard Console Input Handle */ +#define STDOUT 1 /* Standard Console Output Handle */ +#define STDERR 2 /* Standard Error Output */ +#define STDAUX 3 /* Auxilary Device Handle */ +#define STDPRN 4 /* Printer Device Handle */ +#define STDCON 5 /* Internal Console Handle */ + +#define OPEN_RO 0x0000 /* Open in Read Only */ +#define OPEN_WO 0x0001 /* Open in Write Only */ +#define OPEN_RW 0x0002 /* Open in Read/Write mode */ + +#define OPEN_DRW 0x0010 /* Deny Read/Write Access */ +#define OPEN_DW 0x0020 /* Deny Write Access */ +#define OPEN_DR 0x0030 /* Deny Read Access */ +#define OPEN_DN 0x0040 /* Deny None */ + +#define OPEN_NI 0x0080 /* Prevent Child Inheriting */ + +#define OPEN_READ (OPEN_RO | OPEN_DW) /* Open Read Only */ +#define OPEN_WRITE (OPEN_WO | OPEN_DRW) /* Open Write Only */ +#define OPEN_RDWR (OPEN_RW | OPEN_DRW) /* Open Read and Write */ + +/* + * Set STACK to 1 to use dynamic string storage fuunction STACK + * which will reserve a any number of bytes on the stack for + * the life of the calling function. However this routine relies + * on a certain type of function exit code and cannot be used + * with all compilers + */ +#define STACK defined(MSC) + +/* macros to break 'far' pointers into segment and offset components */ + +#define FP_OFF(__p) ((unsigned)(__p)) +#define FP_SEG(__p) ((unsigned)((unsigned long)(void far*)(__p) >> 16)) + +/* make a far pointer from segment and offset */ +#define MK_FP(__s,__o) ((void far*)(((unsigned long)(__s)<<16)|(unsigned)(__o))) + diff --git a/COMMAND/COMMAND.MAP b/COMMAND/COMMAND.MAP new file mode 100644 index 0000000..16a877d --- /dev/null +++ b/COMMAND/COMMAND.MAP @@ -0,0 +1,1258 @@ +LINK : warning L4021: no stack segment + + Start Stop Length Name Class + 00000H 000EEH 000EFH R_TEXT CDOS_DATA + 000EFH 000EFH 00000H NULL BEGDATA + 000F0H 0048FH 003A0H _DATA DATA + 00490H 00490H 00000H DATA DATA + 00490H 006B5H 00226H CONST DATA + 006B6H 006B6H 00000H CONST CONST + 006B6H 006B6H 00000H FIXED FDATA + 006B6H 00787H 000D2H _BSS BSS + 00788H 00788H 00000H HEAP BSS + 00788H 00788H 00000H C_COMMON BSS + 00788H 00FE7H 00860H STACK STACK + 00FF0H 01596H 005A7H ED_TEXT CDATA + 015A0H 015A0H 00000H DYNAMIC DDATA + 015A0H 09677H 080D8H _TEXT CODE + 09678H 0A5A5H 00F2EH _MSG CODE + 0A5B0H 0A5B0H 00000H _TEXTEND CODE + 0A5B0H 0A7AFH 00200H ETEXT XEND + 0A7B0H 0A7B0H 00000H ETEXTEND XEND + + Origin Group + 015A:0 CGROUP + 0000:0 DGROUP + 0A5B:0 CEND + + Address Publics by Name + + 0000:0419 abort_char + 0000:041B abort_msg + 0000:100C alloc_com_memory + 015A:8E69 am_time + 015A:452E append_slash_ + 015A:8E2A apr_m + 015A:8E3E aug_m + 015A:5229 batch_close_ + 015A:5149 batch_endall_ + 015A:5155 batch_end_ + 015A:5400 batch_new_ + 015A:4FB9 batch_start_ + 0000:0410 charmsg + 015A:3E3B check_num_ + 015A:05D3 cmd_loop_ + 0000:00FE code_seg + 0000:1410 com_criterr + 015A:3B95 copy_char_ + 015A:41BA crlf_ + 015A:8EB6 cur_date + 015A:8E89 cur_time + 015A:41D6 c_write_ + 015A:3989 day_names_ + 0000:0169 dbcs_table_ptr + 015A:3C18 deblank_ + 015A:8E60 dec_m + 015A:38E4 disp_filedate_ + 015A:3899 disp_filetime_ + 015A:39BB disp_sysdate_ + 015A:393B disp_systime_ + 015A:1089 docmd_ + 0000:0408 drivemsg + 015A:42F7 d_check_ + 0000:0FF0 ed_text_start + 015A:8CD6 err02 + 015A:8CE5 err03 + 015A:8D01 err04 + 015A:8D15 err05 + 015A:8D23 err08 + 015A:8D35 err15 + 015A:8D4D err19 + 015A:8D62 err20 + 015A:8D78 err83 + 015A:8D8D err86 + 015A:0D2A error_code_ + 015A:8CC3 err_file + 015A:8EF1 euro_date + 015A:4218 e_check_ + 0000:0436 fail_char + 0000:0438 fail_msg + 015A:8E1B feb_m + 015A:44D8 file_exist_ + 015A:63C4 for_end_ + 015A:3F89 fptr_ + 015A:8E0B fri_d + 015A:435A f_check_ + 015A:4CC4 getcmd_ + 015A:3DDF getdigit_ + 015A:3EF4 get_filename_ + 015A:8E77 greeting_afternoon + 015A:8E81 greeting_evening + 015A:8E6F greeting_morning + 0000:01C1 heap_top + 015A:8744 help_com + 015A:8719 help_prog + 0000:042B ignore_char + 0000:042D ignore_msg + 015A:5261 inherit_batch_file_ + 015A:5390 inherit_parent_state_ + 015A:659C int2e_finish_ + 015A:6573 int2e_start_ + 015A:8ED0 inv_date + 015A:8F03 inv_num + 015A:8E9E inv_time + 015A:4516 isdev_ + 015A:3B63 isdigit_ + 015A:3E7E iswild_ + 015A:3BE4 is_blank_ + 015A:3EA1 is_filechar_ + 015A:60D7 is_it_or_ + 015A:3EC9 is_pathchar_ + 015A:8E13 jan_m + 015A:8EFA jap_date + 015A:8E39 jul_m + 015A:8E34 jun_m + 015A:8054 longjmp_ + 0000:0104 low_seg + 015A:8E24 mar_m + 015A:8E30 may_m + 015A:807E memmove_ + 015A:8DFB mon_d + 0000:1257 msdos_exec + 0000:0350 msg0 + 0000:036E msg2 + 0000:03C9 msg20 + 0000:03B4 msg21 + 0000:03DF msg22 + 0000:0364 msg3 + 0000:037E msg4 + 0000:0389 msg6 + 0000:0394 msg7 + 0000:03A3 msg8 + 015A:84F5 msg_badcmd + 015A:8A08 msg_badcp + 015A:84A7 msg_badopt + 015A:8BDD msg_bados + 015A:8565 msg_batmiss + 015A:857C msg_batnest + 015A:8549 msg_batterm + 015A:8C4D msg_binrd + 015A:86EA msg_break + 015A:8A2C msg_cpnf + 015A:8AAE msg_cpyright + 015A:8B79 msg_cpyself + 0000:03F3 msg_crlf + 015A:89F0 msg_curcp + 015A:8FBC msg_debug + 015A:84CB msg_devfail + 015A:859C msg_dir + 015A:8F7F msg_disabled + 015A:8C79 msg_dlost + 015A:8DD6 msg_drv_invalid + 015A:85B2 msg_echo + 015A:8BCB msg_enverr + 015A:8BBA msg_envfull + 015A:85F5 msg_era + 015A:85DF msg_eraall + 015A:85D3 msg_eraq + 015A:8486 msg_exist + 015A:8BA9 msg_fcopied + 015A:8458 msg_files + 015A:8460 msg_free + 015A:84BF msg_full + 015A:8621 msg_gosub + 015A:8703 msg_idle + 015A:8F13 msg_inactive + 015A:8C31 msg_inop + 015A:8F90 msg_internal + 015A:846B msg_invalid_file + 015A:860C msg_label + 015A:8426 msg_lbl + 015A:8C04 msg_loadpath + 015A:8FC9 msg_longjmp + 015A:865D msg_mkdir + 015A:8496 msg_ndir + 015A:8DC1 msg_needdev + 015A:8DAC msg_needfile + 015A:8D9E msg_needpath + 015A:8A8D msg_netassign + 015A:8A6D msg_netsubst + 015A:8FA9 msg_network + 015A:8FDB msg_nohelp + 015A:8723 msg_nohelpprog + 015A:8442 msg_nolbl + 015A:849D msg_nsys + 015A:8B21 msg_oemcpyrt + 015A:8AFE msg_oempatch + 015A:8F59 msg_off + 015A:843C msg_oklbl + 015A:8F56 msg_on + 015A:8CA5 msg_onoff + 015A:853D msg_optline + 015A:8F34 msg_outactive + 015A:8679 msg_path + 015A:8519 msg_pathdrv + 015A:8F60 msg_pause + 015A:868A msg_ren + 015A:863B msg_return + 015A:86C1 msg_rmdir + 015A:8AEC msg_serialno + 015A:8B0C msg_serno + 015A:84E7 msg_syntax + 015A:869F msg_use_rendir + 015A:8424 msg_ver111 + 015A:86F6 msg_verify + 015A:8B61 msg_version + 015A:85BD msg_xbatch + 015A:8EBD new_date + 015A:8E90 new_time + 015A:4419 nofiles_ + 015A:8E57 nov_m + 015A:8E4F oct_m + 015A:4100 onoff_ + 015A:459A optional_line_ + 015A:0DEE parse_ + 015A:8682 path_template + 015A:8E6C pm_time + 015A:18A2 process_config_env_ + 015A:4571 prompt_exec_ + 0000:043F prompt_msg + 015A:3A6B putc_ + 015A:41CB puts_ + 0000:03F6 readmsg + 0000:045B RELOAD_MSGF + 0000:0484 RELOAD_MSGM + 0000:0443 RELOAD_MSGS + 015A:3FC0 repwild_ + 0000:0421 retry_char + 0000:0423 retry_msg + 015A:3A8B revoff_ + 015A:3A7F revon_ + 015A:8E0F sat_d + 015A:8E45 sep_m + 015A:3098 show_file_ + 015A:3B72 skip_char_ + 0000:01BF stack_min + 015A:7FF7 strcat_ + 015A:7FC9 strchr_ + 015A:7F9F strcmp_ + 015A:7F76 strcpy_ + 015A:7F3A stricmp_ + 015A:3D87 strip_path_ + 015A:7F21 strlen_ + 015A:3C2C strlwr_ + 015A:7EF3 strncat_ + 015A:7EC1 strncmp_ + 015A:7E98 strncpy_ + 015A:3CD8 strnicmp_ + 015A:7DEF strstr_ + 015A:3C80 strupr_ + 015A:8DF7 sun_d + 015A:41A3 syntax_ + 015A:8E07 thu_d + 015A:3B4B tolower_ + 015A:8DFF tue_d + 015A:42BF UNC_ + 015A:8EE8 us_date + 015A:8E03 wed_d + 0000:03FF writemsg + 015A:407F yes_ + 015A:8F5D yes_no + 015A:3D5A zap_spaces_ + 0000:0419 _ABORT_CHAR + 0000:041B _ABORT_MSG + 015A:1ED3 _alloc_region + 0000:0324 _allow_pexec + 015A:8E69 _am_time + 015A:8E2A _apr_m + 015A:8E3E _aug_m + 0000:01B0 _autoexec_name + 0000:0310 _back_flag + 0000:0756 _batch + 0000:02AE _batchflg + 0000:0013 _batchflg_off + 0000:0011 _batchptr_off + 0000:0738 _batch_save + 0000:00E7 _batch_seg_ptr + 0000:01BD _boot_key_scan_code + 0000:06B6 _break_env + 0000:0730 _break_flag + 0000:073E _bufaddr + 0000:072E _bufsize + 015A:1F89 _call_novell + 0000:00EB _cbreak_ok + 015A:0159 _cgroupptr + 0000:0410 _CHARMSG + 015A:6B21 _cmd_break + 015A:1FE9 _cmd_call + 015A:20A3 _cmd_cd + 015A:6BC3 _cmd_chcp + 015A:3A58 _cmd_cls + 015A:6D37 _cmd_copy + 015A:6C2C _cmd_ctty + 015A:21A7 _cmd_date + 015A:22F3 _cmd_del + 015A:3432 _cmd_delq + 015A:234B _cmd_dir + 015A:285F _cmd_echo + 015A:28C7 _cmd_exit + 015A:625A _cmd_for + 015A:5B0B _cmd_gosub + 015A:5A83 _cmd_goto + 015A:374F _cmd_hiload + 015A:6CCE _cmd_idle + 015A:6113 _cmd_if + 015A:80D8 _cmd_list + 015A:2934 _cmd_md + 015A:332C _cmd_more + 015A:61AF _cmd_or + 015A:296B _cmd_path + 015A:29EF _cmd_pause + 015A:2B1F _cmd_prompt + 015A:2D5F _cmd_rd + 015A:2B5C _cmd_rem + 015A:2B63 _cmd_ren + 015A:5BE8 _cmd_return + 015A:2D97 _cmd_set + 015A:5A27 _cmd_shift + 015A:2A77 _cmd_stdin_pause + 015A:5C63 _cmd_switch + 015A:2E69 _cmd_time + 015A:2F2D _cmd_truename + 015A:31D1 _cmd_type + 015A:333B _cmd_ver + 015A:6B78 _cmd_verify + 015A:336B _cmd_vol + 0000:0708 _country + 0000:02AC _crlfflg + 015A:8EB6 _cur_date + 015A:8E89 _cur_time + 0000:031E _c_option + 015A:1F00 _dbcs_expected + 015A:1F11 _dbcs_lead + 0000:0732 _ddrive + 015A:1924 _debug + 015A:8E60 _dec_m + 015A:0570 _docmd_int2f + 015A:1B00 _dos_parse_filename + 0000:0306 _dotdot + 0000:02A8 _drive + 0000:0408 _DRIVEMSG + 0000:0309 _d_slash_stardotstar + 0000:02AA _echoflg + 0000:0015 _echoflg_off + 0000:06FA _echoflg_save2 + 0000:06B6 _edata + 0000:0788 _end + 015A:1995 _env_del + 015A:1927 _env_entry + 015A:19C5 _env_ins + 015A:1960 _env_scan + 015A:4667 _eprintf + 015A:8CD6 _err02 + 015A:8CE5 _err03 + 015A:8D01 _err04 + 015A:8D15 _err05 + 015A:8D23 _err08 + 015A:8D35 _err15 + 015A:8D4D _err19 + 015A:8D62 _err20 + 015A:8D78 _err83 + 015A:8D8D _err86 + 015A:8CC3 _err_file + 0000:0734 _err_flag + 0000:073C _err_ret + 015A:8EF1 _euro_date + 015A:0000 _exec + 0000:072C _execed + 015A:1F36 _extended_error + 0000:0436 _FAIL_CHAR + 0000:0438 _FAIL_MSG + 015A:0146 _farptr + 015A:1BE4 _far_read + 015A:1BE9 _far_write + 015A:8E1B _feb_m + 015A:1AE4 _findeof + 015A:1453 _findfile + 015A:1B1C _flush_cache + 0000:02B0 _for_flag + 015A:46C4 _fprintf + 015A:1EF2 _free_region + 015A:8E0B _fri_d + 0000:0316 _ftypes + 015A:1EC0 _get_alloc_strategy + 015A:68F9 _get_am_pm + 015A:04BD _get_config_env + 015A:6AB3 _get_connection + 015A:6A52 _get_day + 015A:6A81 _get_day_of_week + 015A:6707 _get_full_name + 015A:6937 _get_greeting + 015A:687E _get_hour + 015A:68B7 _get_hour24 + 015A:1F40 _get_lines_page + 015A:6656 _get_login_name + 015A:68D1 _get_minute + 015A:69B7 _get_month + 015A:69E2 _get_month_name + 015A:6A68 _get_nday_of_week + 015A:04D2 _get_original_envsize + 015A:6AA0 _get_os_version + 015A:0553 _get_out_pipe + 015A:66D1 _get_pstation + 015A:0513 _get_reload_file + 015A:1F53 _get_scr_width + 015A:68E5 _get_second + 015A:6996 _get_short_year + 015A:1EAC _get_upper_memory_link + 015A:6980 _get_year + 0000:032E _global_in_hiload + 0000:0736 _global_link + 0000:072A _global_strat + 0000:0326 _gp_far_buff + 015A:8E77 _greeting_afternoon + 015A:8E81 _greeting_evening + 015A:8E6F _greeting_morning + 015A:1AAA _heap + 015A:1A6A _heap_get + 015A:1AAE _heap_set + 015A:1A97 _heap_size + 015A:8744 _help_com + 015A:8719 _help_prog + 0000:0742 _hidden_umb + 0000:0206 _ifcond + 0000:0204 _if_context + 0000:042B _IGNORE_CHAR + 0000:042D _IGNORE_MSG + 0000:02A6 _initflg + 015A:0190 _install_perm + 015A:0287 _int10_cls + 015A:1824 _int2e_handler + 015A:0D7E _int_break + 015A:8ED0 _inv_date + 015A:8F03 _inv_num + 015A:8E9E _inv_time + 0000:02B2 _in_flag + 0000:02B6 _in_handle + 015A:1E52 _ioctl_ver + 015A:8E13 _jan_m + 015A:8EFA _jap_date + 015A:8E39 _jul_m + 015A:8E34 _jun_m + 0000:0208 _kbdbuf + 0000:028A _kbdptr + 0000:0320 _k_option + 015A:8E24 _mar_m + 015A:021A _master_env + 015A:8E30 _may_m + 015A:1DFF _mem_alloc + 015A:1E27 _mem_free + 015A:8DFB _mon_d + 015A:1E41 _msdos + 0000:0350 _MSG0 + 0000:036E _MSG2 + 0000:03C9 _MSG20 + 0000:03B4 _MSG21 + 0000:03DF _MSG22 + 0000:0364 _MSG3 + 0000:037E _MSG4 + 0000:0389 _MSG6 + 0000:0394 _MSG7 + 0000:03A3 _MSG8 + 015A:84F5 _msg_badcmd + 015A:8A08 _msg_badcp + 015A:84A7 _msg_badopt + 015A:8BDD _msg_bados + 015A:8565 _msg_batmiss + 015A:857C _msg_batnest + 015A:8549 _msg_batterm + 015A:8C4D _msg_binrd + 015A:86EA _msg_break + 015A:8A2C _msg_cpnf + 015A:8AAE _msg_cpyright + 015A:8B79 _msg_cpyself + 0000:03F3 _MSG_CRLF + 015A:89F0 _msg_curcp + 015A:8FBC _msg_debug + 015A:84CB _msg_devfail + 015A:859C _msg_dir + 015A:8F7F _msg_disabled + 015A:8C79 _msg_dlost + 015A:8DD6 _msg_drv_invalid + 015A:85B2 _msg_echo + 015A:8BCB _msg_enverr + 015A:8BBA _msg_envfull + 015A:85F5 _msg_era + 015A:85DF _msg_eraall + 015A:85D3 _msg_eraq + 015A:8486 _msg_exist + 015A:8BA9 _msg_fcopied + 015A:8458 _msg_files + 015A:8460 _msg_free + 015A:84BF _msg_full + 015A:8621 _msg_gosub + 015A:8703 _msg_idle + 015A:8F13 _msg_inactive + 015A:8C31 _msg_inop + 015A:8F90 _msg_internal + 015A:846B _msg_invalid_file + 015A:860C _msg_label + 015A:8426 _msg_lbl + 015A:8C04 _msg_loadpath + 015A:8FC9 _msg_longjmp + 015A:865D _msg_mkdir + 015A:8496 _msg_ndir + 015A:8DC1 _msg_needdev + 015A:8DAC _msg_needfile + 015A:8D9E _msg_needpath + 015A:8A8D _msg_netassign + 015A:8A6D _msg_netsubst + 015A:8FA9 _msg_network + 015A:8FDB _msg_nohelp + 015A:8723 _msg_nohelpprog + 015A:8442 _msg_nolbl + 015A:849D _msg_nsys + 015A:8B21 _msg_oemcpyrt + 015A:8AFE _msg_oempatch + 015A:8F59 _msg_off + 015A:843C _msg_oklbl + 015A:8F56 _msg_on + 015A:8CA5 _msg_onoff + 015A:853D _msg_optline + 015A:8F34 _msg_outactive + 015A:8679 _msg_path + 015A:8519 _msg_pathdrv + 0000:01CA _msg_patheq + 015A:8F60 _msg_pause + 0000:01D0 _msg_prmeq + 015A:868A _msg_ren + 015A:863B _msg_return + 015A:86C1 _msg_rmdir + 015A:8AEC _msg_serialno + 015A:8B0C _msg_serno + 015A:84E7 _msg_syntax + 015A:869F _msg_use_rendir + 015A:8424 _msg_ver111 + 015A:86F6 _msg_verify + 015A:8B61 _msg_version + 015A:85BD _msg_xbatch + 015A:1B6C _ms_drv_get + 015A:1B60 _ms_drv_set + 015A:1B72 _ms_drv_space + 015A:1DE2 _ms_f_delete + 015A:1DC1 _ms_f_getverify + 015A:1DC7 _ms_f_parse + 015A:1DB5 _ms_f_verify + 015A:1D48 _ms_getdate + 015A:1D72 _ms_gettime + 015A:1D9D _ms_idle_ptr + 015A:1D5E _ms_setdate + 015A:1D87 _ms_settime + 015A:1DEF _ms_set_break + 015A:1DAB _ms_switchar + 015A:1B8F _ms_s_country + 015A:1BA8 _ms_x_chdir + 015A:1C66 _ms_x_chmod + 015A:1BC7 _ms_x_close + 015A:1BAD _ms_x_creat + 015A:1C88 _ms_x_curdir + 015A:1D19 _ms_x_datetime + 015A:1C9E _ms_x_exit + 015A:1CAA _ms_x_expand + 015A:1BD6 _ms_x_fdup + 015A:1CCD _ms_x_first + 015A:1E60 _ms_x_getcp + 015A:1C3D _ms_x_ioctl + 015A:1C21 _ms_x_lseek + 015A:1B9E _ms_x_mkdir + 015A:1CE2 _ms_x_next + 015A:1BB2 _ms_x_open + 015A:1C01 _ms_x_read + 015A:1D04 _ms_x_rename + 015A:1BA3 _ms_x_rmdir + 015A:1E7C _ms_x_setcp + 015A:1C4F _ms_x_setdev + 015A:1BD2 _ms_x_unique + 015A:1C1C _ms_x_unlink + 015A:1CC8 _ms_x_wait + 015A:1C06 _ms_x_write + 015A:8EBD _new_date + 015A:8E90 _new_time + 015A:1F5E _novell_copy + 015A:8258 _novell_ext_list + 015A:1FD6 _nov_connection + 015A:8E57 _nov_m + 015A:1FB1 _nov_station + 0000:0322 _n_option + 015A:8E4F _oct_m + 0000:0700 _old_pipe + 0000:02B4 _out_flag + 0000:02B8 _out_handle + 0000:02C0 _out_pipe + 0000:0312 _page_len + 0000:0314 _page_wid + 0000:0702 _parent_psp + 0000:0300 _pathchar + 015A:8682 _path_template + 0000:02BC _pipe_in + 0000:02BA _pipe_out + 015A:8E6C _pm_time + 0000:02BE _preserve_pipe + 015A:4609 _printf + 0000:043F _PROMPT_MSG + 015A:1B43 _psp_poke + 015A:041A _put_resident_high + 0000:0302 _pwdchar + 015A:00E0 _readline + 0000:03F6 _READMSG + 0000:045B _reload_msgf + 0000:0484 _reload_msgm + 0000:0443 _reload_msgs + 015A:0211 _restore_error_mode + 015A:01F1 _restore_term_addr + 0000:0421 _RETRY_CHAR + 0000:0423 _RETRY_MSG + 015A:8E0F _sat_d + 0000:0706 _save_parent + 015A:8E45 _sep_m + 015A:802A _setjmp_ + 015A:1EC6 _set_alloc_strategy + 015A:0532 _set_reload_file + 015A:1EB3 _set_upper_memory_link + 0000:032A _show_file_buf + 015A:02DF _show_help + 0000:0000 _small_code_ + 015A:4716 _sprintf + 015A:8DF7 _sun_d + 0000:0304 _switchar + 015A:8E07 _thu_d + 015A:1E8D _toupper + 015A:8DFF _tue_d + 015A:8EE8 _us_date + 015A:8E03 _wed_d + 0000:03FF _WRITEMSG + 015A:8F5D _yes_no + 0000:9876 Abs __acrtused + 015A:7D14 __I4D + 015A:7CFC __I4M + 015A:05A6 __main + 0000:00E5 __psp + 015A:1ACA __STK + 015A:7D61 __U4D + 015A:7CFC __U4M + + Address Publics by Value + + 0000:0000 _small_code_ + 0000:0011 _batchptr_off + 0000:0013 _batchflg_off + 0000:0015 _echoflg_off + 0000:00E5 __psp + 0000:00E7 _batch_seg_ptr + 0000:00EB _cbreak_ok + 0000:00FE code_seg + 0000:0104 low_seg + 0000:0169 dbcs_table_ptr + 0000:01B0 _autoexec_name + 0000:01BD _boot_key_scan_code + 0000:01BF stack_min + 0000:01C1 heap_top + 0000:01CA _msg_patheq + 0000:01D0 _msg_prmeq + 0000:0204 _if_context + 0000:0206 _ifcond + 0000:0208 _kbdbuf + 0000:028A _kbdptr + 0000:02A6 _initflg + 0000:02A8 _drive + 0000:02AA _echoflg + 0000:02AC _crlfflg + 0000:02AE _batchflg + 0000:02B0 _for_flag + 0000:02B2 _in_flag + 0000:02B4 _out_flag + 0000:02B6 _in_handle + 0000:02B8 _out_handle + 0000:02BA _pipe_out + 0000:02BC _pipe_in + 0000:02BE _preserve_pipe + 0000:02C0 _out_pipe + 0000:0300 _pathchar + 0000:0302 _pwdchar + 0000:0304 _switchar + 0000:0306 _dotdot + 0000:0309 _d_slash_stardotstar + 0000:0310 _back_flag + 0000:0312 _page_len + 0000:0314 _page_wid + 0000:0316 _ftypes + 0000:031E _c_option + 0000:0320 _k_option + 0000:0322 _n_option + 0000:0324 _allow_pexec + 0000:0326 _gp_far_buff + 0000:032A _show_file_buf + 0000:032E _global_in_hiload + 0000:0350 _MSG0 + 0000:0350 msg0 + 0000:0364 _MSG3 + 0000:0364 msg3 + 0000:036E msg2 + 0000:036E _MSG2 + 0000:037E _MSG4 + 0000:037E msg4 + 0000:0389 msg6 + 0000:0389 _MSG6 + 0000:0394 _MSG7 + 0000:0394 msg7 + 0000:03A3 msg8 + 0000:03A3 _MSG8 + 0000:03B4 msg21 + 0000:03B4 _MSG21 + 0000:03C9 msg20 + 0000:03C9 _MSG20 + 0000:03DF _MSG22 + 0000:03DF msg22 + 0000:03F3 msg_crlf + 0000:03F3 _MSG_CRLF + 0000:03F6 _READMSG + 0000:03F6 readmsg + 0000:03FF _WRITEMSG + 0000:03FF writemsg + 0000:0408 _DRIVEMSG + 0000:0408 drivemsg + 0000:0410 _CHARMSG + 0000:0410 charmsg + 0000:0419 _ABORT_CHAR + 0000:0419 abort_char + 0000:041B abort_msg + 0000:041B _ABORT_MSG + 0000:0421 retry_char + 0000:0421 _RETRY_CHAR + 0000:0423 _RETRY_MSG + 0000:0423 retry_msg + 0000:042B _IGNORE_CHAR + 0000:042B ignore_char + 0000:042D ignore_msg + 0000:042D _IGNORE_MSG + 0000:0436 _FAIL_CHAR + 0000:0436 fail_char + 0000:0438 fail_msg + 0000:0438 _FAIL_MSG + 0000:043F prompt_msg + 0000:043F _PROMPT_MSG + 0000:0443 RELOAD_MSGS + 0000:0443 _reload_msgs + 0000:045B RELOAD_MSGF + 0000:045B _reload_msgf + 0000:0484 RELOAD_MSGM + 0000:0484 _reload_msgm + 0000:06B6 _break_env + 0000:06B6 _edata + 0000:06FA _echoflg_save2 + 0000:0700 _old_pipe + 0000:0702 _parent_psp + 0000:0706 _save_parent + 0000:0708 _country + 0000:072A _global_strat + 0000:072C _execed + 0000:072E _bufsize + 0000:0730 _break_flag + 0000:0732 _ddrive + 0000:0734 _err_flag + 0000:0736 _global_link + 0000:0738 _batch_save + 0000:073C _err_ret + 0000:073E _bufaddr + 0000:0742 _hidden_umb + 0000:0756 _batch + 0000:0788 _end + 0000:0FF0 ed_text_start + 0000:100C alloc_com_memory + 0000:1257 msdos_exec + 0000:1410 com_criterr + 015A:0000 _exec + 015A:00E0 _readline + 015A:0146 _farptr + 015A:0159 _cgroupptr + 015A:0190 _install_perm + 015A:01F1 _restore_term_addr + 015A:0211 _restore_error_mode + 015A:021A _master_env + 015A:0287 _int10_cls + 015A:02DF _show_help + 015A:041A _put_resident_high + 015A:04BD _get_config_env + 015A:04D2 _get_original_envsize + 015A:0513 _get_reload_file + 015A:0532 _set_reload_file + 015A:0553 _get_out_pipe + 015A:0570 _docmd_int2f + 015A:05A6 __main + 015A:05D3 cmd_loop_ + 015A:0D2A error_code_ + 015A:0D7E _int_break + 015A:0DEE parse_ + 015A:1089 docmd_ + 015A:1453 _findfile + 015A:1824 _int2e_handler + 015A:18A2 process_config_env_ + 015A:1924 _debug + 015A:1927 _env_entry + 015A:1960 _env_scan + 015A:1995 _env_del + 015A:19C5 _env_ins + 015A:1A6A _heap_get + 015A:1A97 _heap_size + 015A:1AAA _heap + 015A:1AAE _heap_set + 015A:1ACA __STK + 015A:1AE4 _findeof + 015A:1B00 _dos_parse_filename + 015A:1B1C _flush_cache + 015A:1B43 _psp_poke + 015A:1B60 _ms_drv_set + 015A:1B6C _ms_drv_get + 015A:1B72 _ms_drv_space + 015A:1B8F _ms_s_country + 015A:1B9E _ms_x_mkdir + 015A:1BA3 _ms_x_rmdir + 015A:1BA8 _ms_x_chdir + 015A:1BAD _ms_x_creat + 015A:1BB2 _ms_x_open + 015A:1BC7 _ms_x_close + 015A:1BD2 _ms_x_unique + 015A:1BD6 _ms_x_fdup + 015A:1BE4 _far_read + 015A:1BE9 _far_write + 015A:1C01 _ms_x_read + 015A:1C06 _ms_x_write + 015A:1C1C _ms_x_unlink + 015A:1C21 _ms_x_lseek + 015A:1C3D _ms_x_ioctl + 015A:1C4F _ms_x_setdev + 015A:1C66 _ms_x_chmod + 015A:1C88 _ms_x_curdir + 015A:1C9E _ms_x_exit + 015A:1CAA _ms_x_expand + 015A:1CC8 _ms_x_wait + 015A:1CCD _ms_x_first + 015A:1CE2 _ms_x_next + 015A:1D04 _ms_x_rename + 015A:1D19 _ms_x_datetime + 015A:1D48 _ms_getdate + 015A:1D5E _ms_setdate + 015A:1D72 _ms_gettime + 015A:1D87 _ms_settime + 015A:1D9D _ms_idle_ptr + 015A:1DAB _ms_switchar + 015A:1DB5 _ms_f_verify + 015A:1DC1 _ms_f_getverify + 015A:1DC7 _ms_f_parse + 015A:1DE2 _ms_f_delete + 015A:1DEF _ms_set_break + 015A:1DFF _mem_alloc + 015A:1E27 _mem_free + 015A:1E41 _msdos + 015A:1E52 _ioctl_ver + 015A:1E60 _ms_x_getcp + 015A:1E7C _ms_x_setcp + 015A:1E8D _toupper + 015A:1EAC _get_upper_memory_link + 015A:1EB3 _set_upper_memory_link + 015A:1EC0 _get_alloc_strategy + 015A:1EC6 _set_alloc_strategy + 015A:1ED3 _alloc_region + 015A:1EF2 _free_region + 015A:1F00 _dbcs_expected + 015A:1F11 _dbcs_lead + 015A:1F36 _extended_error + 015A:1F40 _get_lines_page + 015A:1F53 _get_scr_width + 015A:1F5E _novell_copy + 015A:1F89 _call_novell + 015A:1FB1 _nov_station + 015A:1FD6 _nov_connection + 015A:1FE9 _cmd_call + 015A:20A3 _cmd_cd + 015A:21A7 _cmd_date + 015A:22F3 _cmd_del + 015A:234B _cmd_dir + 015A:285F _cmd_echo + 015A:28C7 _cmd_exit + 015A:2934 _cmd_md + 015A:296B _cmd_path + 015A:29EF _cmd_pause + 015A:2A77 _cmd_stdin_pause + 015A:2B1F _cmd_prompt + 015A:2B5C _cmd_rem + 015A:2B63 _cmd_ren + 015A:2D5F _cmd_rd + 015A:2D97 _cmd_set + 015A:2E69 _cmd_time + 015A:2F2D _cmd_truename + 015A:3098 show_file_ + 015A:31D1 _cmd_type + 015A:332C _cmd_more + 015A:333B _cmd_ver + 015A:336B _cmd_vol + 015A:3432 _cmd_delq + 015A:374F _cmd_hiload + 015A:3899 disp_filetime_ + 015A:38E4 disp_filedate_ + 015A:393B disp_systime_ + 015A:3989 day_names_ + 015A:39BB disp_sysdate_ + 015A:3A58 _cmd_cls + 015A:3A6B putc_ + 015A:3A7F revon_ + 015A:3A8B revoff_ + 015A:3B4B tolower_ + 015A:3B63 isdigit_ + 015A:3B72 skip_char_ + 015A:3B95 copy_char_ + 015A:3BE4 is_blank_ + 015A:3C18 deblank_ + 015A:3C2C strlwr_ + 015A:3C80 strupr_ + 015A:3CD8 strnicmp_ + 015A:3D5A zap_spaces_ + 015A:3D87 strip_path_ + 015A:3DDF getdigit_ + 015A:3E3B check_num_ + 015A:3E7E iswild_ + 015A:3EA1 is_filechar_ + 015A:3EC9 is_pathchar_ + 015A:3EF4 get_filename_ + 015A:3F89 fptr_ + 015A:3FC0 repwild_ + 015A:407F yes_ + 015A:4100 onoff_ + 015A:41A3 syntax_ + 015A:41BA crlf_ + 015A:41CB puts_ + 015A:41D6 c_write_ + 015A:4218 e_check_ + 015A:42BF UNC_ + 015A:42F7 d_check_ + 015A:435A f_check_ + 015A:4419 nofiles_ + 015A:44D8 file_exist_ + 015A:4516 isdev_ + 015A:452E append_slash_ + 015A:4571 prompt_exec_ + 015A:459A optional_line_ + 015A:4609 _printf + 015A:4667 _eprintf + 015A:46C4 _fprintf + 015A:4716 _sprintf + 015A:4CC4 getcmd_ + 015A:4FB9 batch_start_ + 015A:5149 batch_endall_ + 015A:5155 batch_end_ + 015A:5229 batch_close_ + 015A:5261 inherit_batch_file_ + 015A:5390 inherit_parent_state_ + 015A:5400 batch_new_ + 015A:5A27 _cmd_shift + 015A:5A83 _cmd_goto + 015A:5B0B _cmd_gosub + 015A:5BE8 _cmd_return + 015A:5C63 _cmd_switch + 015A:60D7 is_it_or_ + 015A:6113 _cmd_if + 015A:61AF _cmd_or + 015A:625A _cmd_for + 015A:63C4 for_end_ + 015A:6573 int2e_start_ + 015A:659C int2e_finish_ + 015A:6656 _get_login_name + 015A:66D1 _get_pstation + 015A:6707 _get_full_name + 015A:687E _get_hour + 015A:68B7 _get_hour24 + 015A:68D1 _get_minute + 015A:68E5 _get_second + 015A:68F9 _get_am_pm + 015A:6937 _get_greeting + 015A:6980 _get_year + 015A:6996 _get_short_year + 015A:69B7 _get_month + 015A:69E2 _get_month_name + 015A:6A52 _get_day + 015A:6A68 _get_nday_of_week + 015A:6A81 _get_day_of_week + 015A:6AA0 _get_os_version + 015A:6AB3 _get_connection + 015A:6B21 _cmd_break + 015A:6B78 _cmd_verify + 015A:6BC3 _cmd_chcp + 015A:6C2C _cmd_ctty + 015A:6CCE _cmd_idle + 015A:6D37 _cmd_copy + 015A:7CFC __I4M + 015A:7CFC __U4M + 015A:7D14 __I4D + 015A:7D61 __U4D + 015A:7DEF strstr_ + 015A:7E98 strncpy_ + 015A:7EC1 strncmp_ + 015A:7EF3 strncat_ + 015A:7F21 strlen_ + 015A:7F3A stricmp_ + 015A:7F76 strcpy_ + 015A:7F9F strcmp_ + 015A:7FC9 strchr_ + 015A:7FF7 strcat_ + 015A:802A _setjmp_ + 015A:8054 longjmp_ + 015A:807E memmove_ + 015A:80D8 _cmd_list + 015A:8258 _novell_ext_list + 0000:9876 Abs __acrtused + 015A:8424 msg_ver111 + 015A:8424 _msg_ver111 + 015A:8426 _msg_lbl + 015A:8426 msg_lbl + 015A:843C _msg_oklbl + 015A:843C msg_oklbl + 015A:8442 _msg_nolbl + 015A:8442 msg_nolbl + 015A:8458 msg_files + 015A:8458 _msg_files + 015A:8460 _msg_free + 015A:8460 msg_free + 015A:846B _msg_invalid_file + 015A:846B msg_invalid_file + 015A:8486 _msg_exist + 015A:8486 msg_exist + 015A:8496 _msg_ndir + 015A:8496 msg_ndir + 015A:849D msg_nsys + 015A:849D _msg_nsys + 015A:84A7 _msg_badopt + 015A:84A7 msg_badopt + 015A:84BF msg_full + 015A:84BF _msg_full + 015A:84CB _msg_devfail + 015A:84CB msg_devfail + 015A:84E7 _msg_syntax + 015A:84E7 msg_syntax + 015A:84F5 _msg_badcmd + 015A:84F5 msg_badcmd + 015A:8519 _msg_pathdrv + 015A:8519 msg_pathdrv + 015A:853D msg_optline + 015A:853D _msg_optline + 015A:8549 _msg_batterm + 015A:8549 msg_batterm + 015A:8565 _msg_batmiss + 015A:8565 msg_batmiss + 015A:857C _msg_batnest + 015A:857C msg_batnest + 015A:859C msg_dir + 015A:859C _msg_dir + 015A:85B2 _msg_echo + 015A:85B2 msg_echo + 015A:85BD msg_xbatch + 015A:85BD _msg_xbatch + 015A:85D3 _msg_eraq + 015A:85D3 msg_eraq + 015A:85DF msg_eraall + 015A:85DF _msg_eraall + 015A:85F5 _msg_era + 015A:85F5 msg_era + 015A:860C msg_label + 015A:860C _msg_label + 015A:8621 _msg_gosub + 015A:8621 msg_gosub + 015A:863B _msg_return + 015A:863B msg_return + 015A:865D _msg_mkdir + 015A:865D msg_mkdir + 015A:8679 msg_path + 015A:8679 _msg_path + 015A:8682 _path_template + 015A:8682 path_template + 015A:868A msg_ren + 015A:868A _msg_ren + 015A:869F _msg_use_rendir + 015A:869F msg_use_rendir + 015A:86C1 msg_rmdir + 015A:86C1 _msg_rmdir + 015A:86EA msg_break + 015A:86EA _msg_break + 015A:86F6 _msg_verify + 015A:86F6 msg_verify + 015A:8703 msg_idle + 015A:8703 _msg_idle + 015A:8719 _help_prog + 015A:8719 help_prog + 015A:8723 msg_nohelpprog + 015A:8723 _msg_nohelpprog + 015A:8744 help_com + 015A:8744 _help_com + 015A:89F0 _msg_curcp + 015A:89F0 msg_curcp + 015A:8A08 msg_badcp + 015A:8A08 _msg_badcp + 015A:8A2C msg_cpnf + 015A:8A2C _msg_cpnf + 015A:8A6D _msg_netsubst + 015A:8A6D msg_netsubst + 015A:8A8D msg_netassign + 015A:8A8D _msg_netassign + 015A:8AAE _msg_cpyright + 015A:8AAE msg_cpyright + 015A:8AEC _msg_serialno + 015A:8AEC msg_serialno + 015A:8AFE msg_oempatch + 015A:8AFE _msg_oempatch + 015A:8B0C msg_serno + 015A:8B0C _msg_serno + 015A:8B21 msg_oemcpyrt + 015A:8B21 _msg_oemcpyrt + 015A:8B61 _msg_version + 015A:8B61 msg_version + 015A:8B79 _msg_cpyself + 015A:8B79 msg_cpyself + 015A:8BA9 _msg_fcopied + 015A:8BA9 msg_fcopied + 015A:8BBA _msg_envfull + 015A:8BBA msg_envfull + 015A:8BCB _msg_enverr + 015A:8BCB msg_enverr + 015A:8BDD _msg_bados + 015A:8BDD msg_bados + 015A:8C04 msg_loadpath + 015A:8C04 _msg_loadpath + 015A:8C31 msg_inop + 015A:8C31 _msg_inop + 015A:8C4D msg_binrd + 015A:8C4D _msg_binrd + 015A:8C79 _msg_dlost + 015A:8C79 msg_dlost + 015A:8CA5 _msg_onoff + 015A:8CA5 msg_onoff + 015A:8CC3 _err_file + 015A:8CC3 err_file + 015A:8CD6 _err02 + 015A:8CD6 err02 + 015A:8CE5 _err03 + 015A:8CE5 err03 + 015A:8D01 err04 + 015A:8D01 _err04 + 015A:8D15 err05 + 015A:8D15 _err05 + 015A:8D23 err08 + 015A:8D23 _err08 + 015A:8D35 _err15 + 015A:8D35 err15 + 015A:8D4D err19 + 015A:8D4D _err19 + 015A:8D62 err20 + 015A:8D62 _err20 + 015A:8D78 _err83 + 015A:8D78 err83 + 015A:8D8D err86 + 015A:8D8D _err86 + 015A:8D9E _msg_needpath + 015A:8D9E msg_needpath + 015A:8DAC msg_needfile + 015A:8DAC _msg_needfile + 015A:8DC1 msg_needdev + 015A:8DC1 _msg_needdev + 015A:8DD6 _msg_drv_invalid + 015A:8DD6 msg_drv_invalid + 015A:8DF7 sun_d + 015A:8DF7 _sun_d + 015A:8DFB _mon_d + 015A:8DFB mon_d + 015A:8DFF _tue_d + 015A:8DFF tue_d + 015A:8E03 _wed_d + 015A:8E03 wed_d + 015A:8E07 thu_d + 015A:8E07 _thu_d + 015A:8E0B fri_d + 015A:8E0B _fri_d + 015A:8E0F _sat_d + 015A:8E0F sat_d + 015A:8E13 jan_m + 015A:8E13 _jan_m + 015A:8E1B feb_m + 015A:8E1B _feb_m + 015A:8E24 mar_m + 015A:8E24 _mar_m + 015A:8E2A _apr_m + 015A:8E2A apr_m + 015A:8E30 _may_m + 015A:8E30 may_m + 015A:8E34 jun_m + 015A:8E34 _jun_m + 015A:8E39 jul_m + 015A:8E39 _jul_m + 015A:8E3E aug_m + 015A:8E3E _aug_m + 015A:8E45 _sep_m + 015A:8E45 sep_m + 015A:8E4F _oct_m + 015A:8E4F oct_m + 015A:8E57 nov_m + 015A:8E57 _nov_m + 015A:8E60 _dec_m + 015A:8E60 dec_m + 015A:8E69 am_time + 015A:8E69 _am_time + 015A:8E6C pm_time + 015A:8E6C _pm_time + 015A:8E6F greeting_morning + 015A:8E6F _greeting_morning + 015A:8E77 _greeting_afternoon + 015A:8E77 greeting_afternoon + 015A:8E81 _greeting_evening + 015A:8E81 greeting_evening + 015A:8E89 _cur_time + 015A:8E89 cur_time + 015A:8E90 _new_time + 015A:8E90 new_time + 015A:8E9E _inv_time + 015A:8E9E inv_time + 015A:8EB6 cur_date + 015A:8EB6 _cur_date + 015A:8EBD _new_date + 015A:8EBD new_date + 015A:8ED0 _inv_date + 015A:8ED0 inv_date + 015A:8EE8 _us_date + 015A:8EE8 us_date + 015A:8EF1 _euro_date + 015A:8EF1 euro_date + 015A:8EFA jap_date + 015A:8EFA _jap_date + 015A:8F03 inv_num + 015A:8F03 _inv_num + 015A:8F13 msg_inactive + 015A:8F13 _msg_inactive + 015A:8F34 _msg_outactive + 015A:8F34 msg_outactive + 015A:8F56 msg_on + 015A:8F56 _msg_on + 015A:8F59 _msg_off + 015A:8F59 msg_off + 015A:8F5D _yes_no + 015A:8F5D yes_no + 015A:8F60 msg_pause + 015A:8F60 _msg_pause + 015A:8F7F msg_disabled + 015A:8F7F _msg_disabled + 015A:8F90 _msg_internal + 015A:8F90 msg_internal + 015A:8FA9 msg_network + 015A:8FA9 _msg_network + 015A:8FBC msg_debug + 015A:8FBC _msg_debug + 015A:8FC9 _msg_longjmp + 015A:8FC9 msg_longjmp + 015A:8FDB _msg_nohelp + 015A:8FDB msg_nohelp diff --git a/COMMAND/CONFIG.C b/COMMAND/CONFIG.C new file mode 100644 index 0000000..8cef821 --- /dev/null +++ b/COMMAND/CONFIG.C @@ -0,0 +1,574 @@ +/* +; File : $Workfile: CONFIG.C$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; ENDLOG +*/ + +/* + * 28 Oct 87 Always decrement the MEMSIZE field by 0x0A paragraphs to + * allow for the SAT's. + * 9 Nov 87 Recheck the login vector after detemining the specified + * drive in NETDRIVE. + * 9 Dec 87 Always display Physically Remote drives as Remote. + * 28 Jan 88 Support the CTTY command for DOS Plus command interpreter + * 27 May 88 Added string undefs. + * 15 Jun 88 DBG is now permanent. + * 23 Jun 88 Use new ONOFF function for XXX [=] ON|OFF parsing + * 29 Jun 88 Check OWNER field in ?CB for valid AUX and LIST devices + * 5 Aug 88 Let L_SET and A_SET determine the validity of a Device No. + * 12 Aug 88 Enforce default AUX and PRINTER on COM1 and LPT1 mapping + * 7 Feb 89 Support the CHCP command for DR DOS + * 14 Apr 89 cmd_chcp: Print relevant msg if ED_FILE returned + * 30 Aug 89 DR Dos idle command + * 30 Oct 89 "DEBUG is" moved to message.c (ie. non-resident) + * 6-Mar-90 Watcom C v 7.0 + * 20-Sep-90 is_filechar() now takes pointer instead of byte. + * 2-Oct-90 Prevent exec of XSTOP.EXE from within STOP command + * 3-Oct-90 remove 8087 command + * 4-Oct-90 Netdrive goes CCB based + * 12-Oct-90 cmd_printer/cmd_aux removed (now part of printmap) + * 12-Oct-90 NETDRIVE now says "netdrive d: /Local" to aid Richard + * (You can save and restore state in batch files) + */ + +#include "defines.h" +#include + +#if defined(MWC) && defined(strlen) +#undef strcmp /* These are defined as macros in string.h */ +#undef strcpy /* which are expaneded in line under */ +#undef strlen /* Metaware C. These undefs avoid this. */ +#endif + +#include +#include +#if !defined(DOSPLUS) +#include +#include +#include +#else +#include /*#NOIDLE#*/ +#endif + +#include "command.h" /* COMMAND Definitions */ +#include "support.h" +#include "dosif.h" /* DOS interface definitions */ +#include "toupper.h" +#include "global.h" + +/* + * USER BEWARE + * + * A process descriptor exists in both DOS Plus and Concurrent + * DOS. But is an internal Structure in DOS Plus and should only + * be used with the upmost care. + */ +#if !defined(DOSPLUS) +EXTERN PD FAR * CDECL pd; /* Far pointer to Current PD */ +#endif + +MLOCAL VOID setflag(cmd, msg, field, flag) +BYTE *cmd; /* Pointer to the Users Command Line */ +BYTE *msg; /* Status Message String */ +UWORD FAR *field; /* FAR pointer to the Flags field */ +UWORD flag; /* The Flag to be updated */ +{ + + switch(onoff(cmd)) { /* Check for "=on/off" */ + case YES: /* Turn Flag ON */ + *field |= flag; + break; + + case NO: /* Turn Flag OFF */ + *field &= ~flag; + break; + + default: + if(*deblank(cmd)) /* Display an error message */ + printf(MSG_ONOFF); /* for a non blank commnad */ + else + printf(msg, *field & flag ? MSG_ON : MSG_OFF); + break; + } +} + +/*.pa*/ +#if defined(CDOSTMP) +/* + * BREAK [ON|OFF] + */ +GLOBAL VOID CDECL cmd_break(cmd) +REG BYTE *cmd; +{ + setflag(cmd, MSG_BREAK, (UWORD FAR *) &pd->P_SFLAG, PSF_BREAK); +} + +/* + * VERIFY [ON|OFF] + */ +GLOBAL VOID CDECL cmd_verify(cmd) +REG BYTE *cmd; +{ + setflag(cmd, MSG_VERIFY, (UWORD FAR *) &pd->P_SFLAG, PSF_VERIFY); +} + +#else +/* + * BREAK [ON|OFF] + * + * The break flag is emulated during by the COMMAND processor and + * only set to the users value when a program is loaded or when + * leaving COMMAND.COM using the EXIT command. + */ +GLOBAL VOID CDECL cmd_break(cmd) +REG BYTE *cmd; +{ + switch(onoff(cmd)) { /* Check for "=on/off" */ + case YES: /* Turn Flag ON */ + break_flag = YES; + break; + + case NO: /* Turn Flag OFF */ + break_flag = NO; + break; + + default: + if(*deblank(cmd)) /* Display an error message */ + printf(MSG_ONOFF); /* for a non blank commnad */ + else + printf(MSG_BREAK, break_flag ? MSG_ON : MSG_OFF); + break; + } +} + +/* + * VERIFY [ON|OFF] + */ +GLOBAL VOID CDECL cmd_verify(cmd) +REG BYTE *cmd; +{ + switch(onoff(cmd)) { /* Check for "=on/off" */ + case YES: /* Turn Flag ON */ + ms_f_verify(YES); + break; + + case NO: /* Turn Flag OFF */ + ms_f_verify(NO); + break; + + default: + if(*deblank(cmd)) /* Display an error message */ + printf(MSG_ONOFF); /* for a non blank commnad */ + else + printf(MSG_VERIFY, ms_f_getverify() ? MSG_ON : MSG_OFF); + break; + } +} +#endif + +#if defined(DOSPLUS) +/* + * CHCP [CodePage] + * + * CHCP displays or changes the current global codepage + * + */ +GLOBAL VOID CDECL cmd_chcp(cmd) +REG BYTE *cmd; +{ + UWORD systemcp, globalcp; + WORD ret; + + zap_spaces(cmd); + if(*cmd) { + if(check_num(cmd, 0, 999, &globalcp)) + printf(INV_NUM); + else { + if((ret = ms_x_setcp(globalcp)) < 0) + if (ret == ED_FILE) + printf (MSG_CPNF); + else + printf(MSG_BADCP, globalcp); + } + } + else { + ms_x_getcp(&globalcp, &systemcp); + printf(MSG_CURCP, globalcp); + } +} + +/* + * CTTY Device Name + * + * CTTY redirects all console output to the specified character + * device. Note CTTY will only allow a DEVICE to be specified. + * + */ +GLOBAL VOID CDECL cmd_ctty(cmd) +REG BYTE *cmd; +{ + BYTE device[MAX_FILELEN]; + WORD h, j; + + get_filename(device, deblank(cmd), NO); /* Extract the Device Name */ + + FOREVER { + if((h = ms_x_open(device, OPEN_RW)) < 0) + break; + + j = ms_x_ioctl(h); /* Check the user specified a */ + if((j & 0x0080) == 0) { /* device or not. If a file was */ + ms_x_close(h); /* Close the handle and quit */ + break; + } + + j |= 0x03; + ms_x_setdev(h,j); + + ms_x_fdup(STDIN, h); /* Force duplicate this handle */ + ms_x_fdup(STDOUT, h); /* onto STDIN, STDOUT and */ + ms_x_fdup(STDERR, h); /* STDERR. */ + + /* + * Update the internal variables which contain the handle + * table index to be updated with the new values. So that + * all the Command Processor error messages go to the right + * device. + */ + in_handle = out_handle = psp_poke(h, 0xFF); + psp_poke(h, in_handle); + + ms_x_close(h); /* Finally close the handle and */ + return; /* return to the caller. */ + } + + crlfflg = YES; /* Display the Device Name */ + printf(MSG_NEEDDEV); /* required error message and */ + return; /* Terminate. */ +} + +/*#if 0 #NOIDLE#*/ +/* + * IDLE [ON|OFF] + */ +GLOBAL VOID CDECL cmd_idle(cmd) +REG BYTE *cmd; +{ +IDLE_STATE FAR *idle; + + idle = ms_idle_ptr (); + + if (idle->flags & IDLE_ENABLE) { + printf(MSG_DISABLED); /* say if idle is installed */ + return; + } + + switch(onoff(cmd)) { /* Check for "=on/off" */ + case YES: /* Reset flag */ + idle->flags &= ~IDLE_ON; + break; + + case NO: /* Set flag */ + idle->flags |= IDLE_ON; + break; + + default: + if(*deblank(cmd)) /* Display an error message */ + printf(MSG_ONOFF); /* for a non blank commnad */ + else + printf(MSG_IDLE, idle->flags & IDLE_ON ? MSG_OFF : MSG_ON); + break; + } +} +/*#endif #NOIDLE#*/ +#endif + +#if defined(CDOSTMP) || defined(CDOS) +/* + * Enforce the current PRINTER and AUX mapping for LPT1 and COM1. + * Using the console number and the number of devices supported + * update the correct mapping byte in the table. + */ + +#define INT17_PTR 0x0C46 /* List Mapping Table */ +#define INT14_PTR 0x0C48 /* Aux Mapping Table */ + +MLOCAL VOID map_device(tbl, dev) +UWORD tbl; +UWORD dev; +{ +UBYTE console; + + tbl = *SYSDATW(tbl); + console = (UBYTE) bdos(C_GET, 0); + *SYSDATB(tbl + (*SYSDATB(tbl) * console) +1) = (BYTE) dev; +} + +GLOBAL VOID CDECL cmd_stop(cmd) +REG BYTE *cmd; +{ +UWORD vc_base, vc_num, pc_num, i; +struct { + UWORD pd; /* PD address */ + UWORD term; /* Process termination Code */ + UWORD cns; /* Console Number and Zero field*/ + BYTE name[8]; /* Process Name */ + } apb; + + cmd = deblank(cmd); /* Get the Process Name ABORT */ + + if(!*cmd) { /* If no command line options */ + printf(MSG_BADSTOP); /* return with syntax error */ + return; /* disk based version of STOP. */ + } + + memset(apb.name, ' ', 8); /* Blank fill the Name Buffer */ + + for(i=0; i < 8 && is_filechar(cmd); cmd++, i++) + apb.name[i] = toupper(*cmd); + + if(i == 0) { /* If no valid process name was */ + printf(MSG_BADSTOP); /* given then return with a */ + return; /* syntax error. */ + } + + vc_data(&vc_base, &vc_num, &pc_num); + + if(check_num(cmd, 1, vc_num, &apb.cns)) { + printf(MSG_BADSTOP); + return; + } + + apb.pd = 0; /* Zero Process Descriptor Field */ + apb.term = 0; /* Only Abort User Process's */ + apb.cns += vc_base - 1; /* Force console number base 0 */ + if(bdos(P_ABORT, &apb)) /* Abort the Process */ + printf(MSG_BADSTOP); +} + + +/* + * BANK [ON|OFF] + */ +GLOBAL VOID CDECL cmd_bank(cmd) +REG BYTE *cmd; +{ + setflag(cmd, MSG_BANK, (UWORD FAR *) &pd->P_PCMFLAG, PIDF_BANK); +} + +/* + * SUSPEND [ON|OFF] + */ +GLOBAL VOID CDECL cmd_suspend(cmd) +REG BYTE *cmd; +{ + setflag(cmd, MSG_SUSPEND, (UWORD FAR *) &pd->P_PCMFLAG, PIDF_SUSPEND); +} + +/* + * IDLE [ON|OFF] + */ +GLOBAL VOID CDECL cmd_idle(cmd) +REG BYTE *cmd; +{ + setflag(cmd, MSG_IDLE, (UWORD FAR *) &pd->P_PCMFLAG, PIDF_IDLE); +} + + +/* + * MEMSIZE [Memory Size (Kb)] + */ +GLOBAL VOID CDECL cmd_memsize(cmd) +REG BYTE *cmd; +{ + UWORD kb, mmp; /* number in kilobytes */ + + mmp = *SYSDATW(MMP)/64; /* Per Process Maximum in Kb */ + kb = (pd->P_PCMMEM + 0x0A)/64; /* Convert to number of Kb */ + + zap_spaces(cmd); + if(*cmd) { + if(check_num(cmd, 0, MAX_MEMSIZE, &kb)) + printf (INV_NUM); + else { + if(kb == 0 || kb > mmp) /* If MEMSIZE specified was */ + kb = mmp; /* out of range or was Zero */ + pd->P_PCMMEM = kb * 64 - 0x0A; /* then use the MMP */ + } + } + else + printf (MSG_MEMSIZE, kb); +} + +/* + * LIMSIZE [Memory Size (Kb)] + * + * This command sets the Maximum number of blocks to be allocated + * to a process using the LIM memory. The maximum field is fixed for + * Concurrent DOS XM to MAX_LIMSIZE but for Concurrent DOS 386 the + * LIMMAX field in the 386 data area is used. + */ +GLOBAL VOID CDECL cmd_limsize(cmd) +REG BYTE *cmd; +{ + UWORD kb, limmax; /* number in kilobytes */ + + kb = pd->P_LIMMEM * 16; /* get number of kilobytes */ + + if(*SYSDATW(V386_PTR)) { /* If this is Concurrent DOS 386 */ + if (*SYSDATW(*SYSDATW(V386_PTR) + 15)!=0xff) { + printf (MSG_LIMOFF); + return; + } + else + limmax = *SYSDATW(*SYSDATW(V386_PTR) + 18) * 16; + } + else + limmax = MAX_LIMSIZE; + + zap_spaces(cmd); + if(*cmd) { + if(check_num(cmd, 0, limmax, &kb)) + printf (INV_NUM); + else + pd->P_LIMMEM = (kb+15)/16; + } + else + printf (MSG_LIMSIZE, kb); +} + +/* + * NETDRIVE d: [/A|/R|/L] + * + * This command displays and modifies the current "network" status + * of all physical drives currently logged in. + * + * NETDRIVE d: /R Treat as Networked Media + * NETDRIVE d: /L Treat as Local Media + * NETDRIVE [d:|/A] Display Network Status + */ + +#define NETDRIVE_ALL (flags == 1) /* Display ALL */ +#define NETDRIVE_LOCAL (flags & 2) /* Treat as LOCAL media */ +#define NETDRIVE_REMOTE (flags & 4) /* Treat as REMOTE media*/ +#define CCBLIST 0x0c3e +#define CCB_NETVEC 0x0010 + +GLOBAL VOID CDECL cmd_netdrive(s) +REG BYTE *s; +{ + BYTE *cp; + UWORD login, network; /* Login Vector */ + WORD ret; /* General purpose variable */ + UWORD flags; /* Command Flags */ + UWORD ccbptr; /* address of CCB */ + UWORD netvec; /* address pseudo-net drive vec */ + + + /* We bodge flags to all "/Local" and "/Remote" by making "emotc" */ + /* into flags as well - we are only interested in the "alr" flags */ + + f_check (s, "alremotc", &flags, YES); + s = deblank(s); /* Deblank after the Flag Check */ + + + ccbptr = *SYSDATW(CCBLIST) + 2*pd->P_CNS; + netvec = *SYSDATW(ccbptr) + CCB_NETVEC; + + login = network = (UWORD) network_drvs(); + login |= (UWORD) physical_drvs(); /* Physical Drive Vector */ + network |= *SYSDATW(netvec); /* Logically Remote Drives */ + +/* + * if NETDRIVE_ALL then display the network status of all the currently + * logged in physical drives. + */ + if(NETDRIVE_ALL || !*s) { + for(ret = 0; ret < 16; ret++, login >>= 1, network >>=1) + if(login & 1L) { + printf("Netdrive %c: %s\n", ret + 'A', + network & 1 ? MSG_REMOTE : MSG_LOCAL); + } + return; + } + + if(nofiles(s, ATTR_ALL, NO, NO))/* Abort if an illegal drive is */ + return; /* selected. */ + + login &= ~((UWORD) network_drvs()); /* Invalidate Remote Drives */ + ret = 1 << ddrive; /* Generate Bit vector and then */ + if((login & ret) == 0) { /* check that this is a logged in */ + e_check(ED_DRIVE); /* physical drive */ + return; + } + + + if(NETDRIVE_LOCAL) { + *SYSDATW(netvec) &= ~ret; /* Local Drive */ + } + else if(NETDRIVE_REMOTE) { + *SYSDATW(netvec) |= ret; /* Remote Drive */ + } + else { + printf("Netdrive %c: %s\n", ddrive + 'A', + network & ret ? MSG_REMOTE : MSG_LOCAL); + } +} +#endif + +#if !defined(FINAL) && !defined(DOSPLUS) +/* + * DBG [ON|OFF] + */ +GLOBAL VOID CDECL cmd_dbg(cmd) +REG BYTE *cmd; +{ + setflag(cmd, MSG_DEBUG, (UWORD FAR *) &pd->P_SFLAG, PSF_DEBUG); +} +#endif + +#if defined(CPM) +/*.pa*/ +/* + * + */ +EXTERN UWORD user; /* Current User area */ + +GLOBAL VOID CDECL cmd_user(s) +REG BYTE *s; +{ + if(*s && check_num(s, 0, 15, &user)) /* If command line and its not */ + printf(INV_USER); /* a valid user area then invalid user */ + + printf(CUR_USER, user); +} +#endif diff --git a/COMMAND/CRIT.ASM b/COMMAND/CRIT.ASM new file mode 100644 index 0000000..b2b97bb --- /dev/null +++ b/COMMAND/CRIT.ASM @@ -0,0 +1,589 @@ +; File : $Workfile: CRIT.ASM$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; CRIT.ASM 1.11 94/12/01 10:05:21 +; Changed critical error message display so that the default message +; is 'I/O error' and that all share-related codes are converted to +; 'File sharing conflict' +; +; CRIT.ASM 1.9 93/09/10 15:56:08 +; Use device driver header at BP:SI instead of AH to determine if disk/char device +; That way we get "device NETWORK" rather than "drive D" on VLM critical errors +; ENDLOG +; +; 19/Sep/88 Move the messages into a separate module +; 15/Dec/88 Critical Error messages processed by STDERR +; 06/Apr/89 DR DOS version taken from PCMODE & put in COMMAND.COM +; 10/Aug/89 Issue INT 2F's so application can give it's own error message +; 08/Sep/89 'No FCBs' message +; 02/Nov/89 abort_char etc become ABS rather than CHAR (saves a few bytes) +; 13/Nov/89 Reduced number of external messages referenced to one +; (crit_top) to aid Dual Language Support. +; 12/Feb/90 Changed code to avoid problems with double byte character sets. +; 8/Mar/90 Remove extra pair of CR/LF's that were output after error +; 20/Apr/90 DLS data into R_TEXT for Watcom C v7.0 +; 9/May/90 Critical errors go to STDERR on command PSP, not current_psp + + include msdos.equ + include mserror.equ + include driver.equ +; +dataOFFSET equ offset DGROUP: + + +PSP_XFTPTR equ es:dword ptr 34h ; from i:PSP.DEF + +; Critical Error responses from the default INT 24 handler and +; the DO_INT24 routine. +; +ERR_IGNORE equ 0 ; Ignore Error +ERR_RETRY equ 1 ; Retry the Operation +ERR_ABORT equ 2 ; Terminate the Process +ERR_FAIL equ 3 ; Fail Function +; +OK_FAIL equ 00001000b ; Fail is a Valid Response +OK_RETRY equ 00010000b ; Retry is a Valid Response +OK_IGNORE equ 00100000b ; Ignore is a valid Response +OK_RIF equ 00111000b ; All Responsese are Valid +OK_RI equ 00110000b ; Retry and Ignore are Valid +OK_RF equ 00011000b ; Retry and Fail are Valid +; +; +; The following equates allow us to access the users registers +; and flags during normal system call emulation. +; +;NOTE:- The users INT21 structure is not normally available because of the +; stack switch which occurs on entry and only the general purpose +; registers are copied to the new stack. +; +dos_AX equ word ptr 0[bp] +dos_BX equ word ptr 2[bp] +dos_CX equ word ptr 4[bp] +dos_DX equ word ptr 6[bp] +dos_SI equ word ptr 8[bp] +dos_DI equ word ptr 10[bp] +dos_BP equ word ptr 12[bp] +dos_DS equ word ptr 14[bp] +dos_ES equ word ptr 16[bp] +; +; +; +ifdef CDOSTMP +DGROUP GROUP R_TEXT + +R_TEXT SEGMENT byte public 'CDOS_DATA' + +else + +DGROUP GROUP _DATA, R_TEXT, ED_TEXT + +R_TEXT SEGMENT byte public 'CDOS_DATA' +R_TEXT ENDS + +_DATA SEGMENT byte public 'DATA' + +endif + extrn _country:WORD + extrn __psp:WORD + +ifdef DLS +TEXT_LEN equ 320 ; it needs to be this size for Japanese + + Public _crit_msgs + + ; crit_table gives offset into crit_msgs table. + +crit_table db 0 ; (00) Write to Read Only Disk + db 2 ; (01) Unknown Unit + db 4 ; (02) Drive Not Ready + db 2 ; (03) Unknown Command + db 6 ; (04) Data Error (CRC) + db 2 ; (05) Bad Request Length Structure + db 8 ; (06) Seek Error + db 10 ; (07) Unknown Media Type + db 12 ; (08) Sector Not Found + db 14 ; (09) Printer Out Of Paper + db 2 ; (0A) Write Fault + db 2 ; (0B) Read Fault + db 2 ; (0C) General Failure + db 16 ; (0D) File Sharing Error + db 16 ; (0E) Locking Error + db 18 ; (0F) FCB Unavailable + +_crit_msgs dw TEXT_LEN ; size of this message buffer +crit_top dw 0,0,0,0,0,0,0,0,0,0 +msg_crlf dw 0 +readmsg dw 0 +writemsg dw 0 +drivemsg dw 0 +charmsg dw 0 +abort_char dw 0 +abort_msg dw 0 +retry_char dw 0 +retry_msg dw 0 +ignore_char dw 0 +ignore_msg dw 0 +fail_char dw 0 +fail_msg dw 0 +prompt_msg dw 0 + dw 0 ; end of list + +public _crit_text +_crit_text db TEXT_LEN dup(?) ; message text is placed here + +CRIT_LEN equ $-crit_top + + +else + + extrn msg0:byte, msg2:byte, msg3:byte, msg4:byte + extrn msg6:byte, msg7:byte, msg8:byte + extrn msg20:byte, msg21:byte, msg22:byte + +crit_top dw offset DGROUP:msg0 ; (00) Write to Read Only Disk + dw offset DGROUP:msg3 ; (01) Unknown Unit + dw offset DGROUP:msg2 ; (02) Drive Not Ready + dw offset DGROUP:msg3 ; (03) Unknown Command + dw offset DGROUP:msg4 ; (04) Data Error (CRC) + dw offset DGROUP:msg3 ; (05) Bad Request Length Structure + dw offset DGROUP:msg6 ; (06) Seek Error + dw offset DGROUP:msg7 ; (07) Unknown Media Type + dw offset DGROUP:msg8 ; (08) Sector Not Found + dw offset DGROUP:msg21 ; (09) Printer Out Of Paper + dw offset DGROUP:msg3 ; (0A) Write Fault + dw offset DGROUP:msg3 ; (0B) Read Fault + dw offset DGROUP:msg3 ; (0C) General Failure + dw offset DGROUP:msg20 ; (0D) File Sharing Error + dw offset DGROUP:msg20 ; (0E) Locking Error + dw offset DGROUP:msg22 ; (0F) FCB Unavailable + + + Extrn msg_crlf:byte + Extrn readmsg:byte, writemsg:byte, drivemsg:byte, charmsg:byte + Extrn abort_char:byte, abort_msg:byte + Extrn retry_char:byte, retry_msg:byte + Extrn ignore_char:byte, ignore_msg:byte + Extrn fail_char:byte, fail_msg:byte, prompt_msg:byte +endif +ifndef CDOSTMP +_DATA ends +ED_TEXT SEGMENT para public 'CDATA' +endif + + assume cs:DGROUP, ds:nothing, es:nothing, ss:nothing +; +; This is the default critical error handler which will prompt +; the user with an error message and wait for a response. This handler +; is usually replaced by the DOS application +; +; +++++++++++++++++++++++++++++++ +; Int 24 - Critical Error Handler +; +++++++++++++++++++++++++++++++ +; +; INT 24 Critical Error:- +; On Entry:- AH/7 0 = Disk Device +; AH/5 0 = IGNORE is an Invalid Response +; AH/4 0 = RETRY in an Invalid Response +; AH/3 0 = FAIL is an Invalid Response +; AH/2-1 00= DOS Area +; 01= File Allocation Table +; 10= Directory +; 11= Data +; AH/0 0 = Read, 1 = Write +; +; AL Failing Disk Drive if AH/7 == 0 +; BP:SI Device Header Control Block +; DI High Byte DRNET server (inverted, CDOS only) +; Low Byte Error Code +; +; On Exit:- AL 0 = IGNORE Error +; 1 = RETRY the Operation +; 2 = TERMINATE using INT 23 +; 3 = FAIL the current DOS function +; +; + + Public com_criterr +com_criterr: +; +; This is called by the int24 handler 'critical_error', in CSTART.ASM. +; + sti + cld + push es + push ds + push bp + push di + push si + push dx + push cx + push bx + push ax + + mov bp,sp + mov ah,MS_P_GETPSP + int DOS_INT ; Get PSP into DS + mov ds,cs:__psp + mov al,ds:byte ptr 1ah ; use COMMAND STDERR for Console INPUT + mov ah,al ; and OUTPUT + mov es,bx + lds bx,PSP_XFTPTR ; Get the handle table pointer + push word ptr [bx] ; Save the current Values + mov word ptr [bx],ax + + push cs + pop ds ; DS == CS + call i24_crlf ;output carriage return - line feed + + mov ah,MS_F_ERROR + xor bx,bx + int DOS_INT ; Get extended error code + mov cx,ax ; Get the Real Error Code (ie INT21/59) + mov bx,0Fh ; assume FCB unavailable + cmp al,-(ED_NOFCBS) ; if FCB exhausted/closed then generate + je int24_e10 ; a more appropriate error message + dec bx + dec bx + cmp al,-(ED_SHAREFAIL) ; check for sharing failure which + je int24_e10 ; is forced to be a DRIVE NOT READY + cmp al,-(ED_NOLOCKS) ; check for sharing buffer overflow + je int24_e10 + dec bx ; BX = 0Ch, default error + mov ax,dos_DI ; get the REAL error code + cmp ax,0Eh ; is it a sensible value ? + ja int24_e10 ; no, return GENERAL FAILURE + xchg ax,bx ; yes, use it +int24_e10: + call int24_errmsg ; print out the offending error msg + call i24_crlf ; Print CR/LF + +; +; This section of the Critical Error handler prints the correct +; prompt repeatedly until the user responds with a correct +; response. This value is returned to the PCMODE. +; +i24_query: +ifdef DLS + mov dx,abort_msg ; Print "Abort" as this is always +else + mov dx,dataOFFSET abort_msg ; Print "Abort" as this is always +endif + call i24_print ; a valid response + + test bh,OK_RETRY + jz i24_q10 ; Display ", Retry" if RETRY +ifdef DLS + mov dx,retry_msg ; is a Valid Response +else + mov dx,dataOFFSET retry_msg ; is a Valid Response +endif + call i24_print + +i24_q10: + test bh,OK_IGNORE + jz i24_q20 ; Display ", Ignore" if IGNORE +ifdef DLS + mov dx,ignore_msg ; is a valid response +else + mov dx,dataOFFSET ignore_msg ; is a valid response +endif + call i24_print + +i24_q20: + test bh,OK_FAIL + jz i24_q30 ; Display ", Fail" if FAIL is +ifdef DLS + mov dx,fail_msg ; a valid response +else + mov dx,dataOFFSET fail_msg ; a valid response +endif + call i24_print + +i24_q30: +ifdef DLS + mov dx,prompt_msg +else + mov dx,dataOFFSET prompt_msg +endif + call i24_print + + mov ah,MS_C_FLUSH ; Clear type ahead buffer + mov al,MS_C_READ ; and then get a character + int DOS_INT + +; In case we get double byte characters... +; If we had access to the dbcs_lead() routine (in the non-resident code) +; we could test for a double byte character and consume the second byte. +; Since we can't do this I have used the following code, which simply +; consumes and displays all bytes in type-ahead buffer. + push ax ; save first character received +dbcs_loop: + mov ah, MS_C_RAWIO ; char in type-ahead buffer? + mov dl, 0FFh + int DOS_INT + jz dbcs_exit ; no - exit loop + mov dl, al + mov ah, MS_C_WRITE ; yes - display char + int DOS_INT + jmp short dbcs_loop ; loop until type-ahead buffer empty +dbcs_exit: + pop ax ; restore the first character + +; Check that character lies in the range 'a' <= ch <= 'z' before anding it +; with 5Fh to uppercase it (incase the character is a DBCS lead byte). + + cmp al, 'a' ; ch < 'a' ? + jb uc_done ; yes - skip upper casing + cmp al, 'z' ; ch > 'z' ? + ja uc_intl ; yes - may be intl + and al, 5Fh ; uppercase ch + jmp short uc_done +uc_intl: + cmp al, 80h ; international char? + jb uc_done +; ch >= 80h -- call international routine +UCASE equ 18 ; offset of dword ptr to uppercase func + call dword ptr [_country+UCASE] +uc_done: + + push ax + call i24_crlf + pop dx + + mov ah,bh + xor al,al ; AL == 0 IGNORE Error +ifdef DLS + test ah,OK_IGNORE + jz i24_q40 ; Is it a valid response + mov bx,ignore_char + cmp dl,[bx] +else + test bh,OK_IGNORE + jz i24_q40 ; Is it a valid response + cmp dl,ignore_char +endif + jz i24_exit + +i24_q40: + inc ax ; AL == 1 RETRY Function +ifdef DLS + test ah,OK_RETRY + jz i24_q50 ; Is it a valid response + mov bx,retry_char + cmp dl,[bx] +else + test bh,OK_RETRY + jz i24_q50 ; Is it a valid response + cmp dl,retry_char +endif + jz i24_exit + +i24_q50: + inc ax ; AL == 2 ABORT Process +ifdef DLS + mov bx,abort_char + cmp dl,[bx] +else + cmp dl,abort_char +endif + jz i24_exit + + inc ax ; AL == 3 FAIL Function +ifdef DLS + test ah,OK_FAIL + jz i24_query_again ; Is it a valid response + mov bx,fail_char + cmp dl,[bx] + jz i24_exit +i24_query_again: + mov bh, ah ; restore valid response bit set + jmp i24_query +else + test bh,OK_FAIL + jz i24_query_again ; Is it a valid response + cmp dl,fail_char + jz i24_exit +i24_query_again: + jmp i24_query +endif + + +i24_exit: + mov dos_AX,ax + mov ah,MS_P_GETPSP + int DOS_INT ; Get PSP into DS + mov es,bx + lds bx,PSP_XFTPTR ; the handle table pointer + pop word ptr [bx] ; Restore the original handle Values + + pop ax + pop bx + pop cx + pop dx + pop si + pop di + pop bp + pop ds + pop es + + ret + +int24_errmsg: +; Print out an appropriate error message (eg. "Drive not ready") +; Call INT 2F functions in case system extentions (eg. CDROM) wish to +; give another error message. + push bx ; save error code + push cx + mov ax,500h + int 2fh ; query if user msg handler installed + cmp al,0ffh ; yes if FF returned + pop cx + pop bx + jne int24_errmsg10 + push bx + push cx +if 0 +; the DOS 3 way + mov ah,5 ; OK. now we ask for a message + mov al,cl ; with the error code in AL +else +; the DOS 5 way + mov ax,501h + mov bx,cx +endif + int 2fh ; ES:DI -> msg + pop cx + pop bx + jc int24_errmsg10 ; did they give us a msg ? + mov si,di ; ES:SI -> msg + mov ah,MS_C_WRITE ; write it out +int24_errmsg1: + lods es:byte ptr [si] ; get a character + test al,al ; until end of an ASCIIZ string + jz int24_errmsg2 + mov dl,al ; character into DL + int DOS_INT ; write it + jmp short int24_errmsg1 +int24_errmsg2: + mov bx,dos_AX ; get original AX for Abort/Retry etc + ret + +int24_errmsg10: +; No-one wants to supply a message - we'd better generate one ourselves +; + xor bh,bh +ifdef DLS + mov bl, crit_table[bx] +else + shl bx,1 +endif + mov dx, crit_top[bx] + call i24_print + + mov bx,dos_AX ; Get the Original AX + test bh,01h ; check to see if the error occured + jnz prwrite ; while reading or writing +ifdef DLS + mov dx,readmsg ; print 'reading' +else + mov dx,dataOFFSET readmsg ; print 'reading' +endif + jmp short prread +prwrite: +ifdef DLS + mov dx,writemsg ; print 'writing' +else + mov dx,dataOFFSET writemsg ; print 'writing' +endif +prread: + call i24_print ; appropriate string +;; test bh,80h + mov es,dos_BP ; ES:SI = driver header + test es:DH_ATTRIB[si],DA_CHARDEV + jz disk_error ; Was this a DISK error + +; +; For Character Device errors print the failing Device Name +; and then prompt the user for a valid response. +; +;character_error: +ifdef DLS + mov dx,charmsg +else + mov dx,dataOFFSET charmsg +endif + call i24_print + +;; mov es,dos_BP ; ES:SI = driver header + mov cx,8 ; Print the 8 Character device name +char_name: + mov dl,DH_NAME[si] ; Get the next character and + mov ah,MS_C_WRITE ; display on the console + int DOS_INT + inc si ; Increment the character pointer + loop char_name ; and Loop till complete name displayed + ret ; Now query the user + +; +; For DISK errors print the failing drive code and then +; prompt the user for a valid response. +; +disk_error: +ifdef DLS + mov dx,drivemsg ; +else + mov dx,dataOFFSET drivemsg ; +endif + call i24_print ; print 'drive d' + mov dl,bl ; Get the Drive Code + add dl,'A' ; convert drive to ascii + mov ah,MS_C_WRITE ; print the drive + int DOS_INT + ret + +i24_crlf: +ifdef DLS + mov dx,msg_crlf +else + mov dx,dataOFFSET msg_crlf +endif + +i24_print: + mov ah,MS_C_WRITESTR + int DOS_INT + ret + +ifdef CDOSTMP +R_TEXT ENDS +else +ED_TEXT ENDS +endif + end diff --git a/COMMAND/CSTART.ASM b/COMMAND/CSTART.ASM new file mode 100644 index 0000000..fb20a39 --- /dev/null +++ b/COMMAND/CSTART.ASM @@ -0,0 +1,3837 @@ +; File : $Workfile: CSTART.ASM$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; CSTART.ASM 1.2 97/03/21 15:01:01 +; Added /n option to disable critical error handler +; CSTART.ASM 1.38 94/12/21 10:45:05 +; Reduced Heap size to 860h just to be sure. +; CSTART.ASM 1.34 94/03/29 16:10:05 +; _docmd_int2f returns 1 or 0 depending on whether or not the command +; is accepted. +; CSTART.ASM 1.31 93/11/18 18:50:18 +; Fix HMA registration problem +; CSTART.ASM 1.30 93/11/09 00:00:14 +; Shorten _ge_config_env +; CSTART.ASM 1.28 93/11/05 00:54:25 +; move HMA registration code to where it's actually executed +; CSTART.ASM 1.27 93/11/04 23:39:11 +; Fix problem with resident data relocation code +; CSTART.ASM 1.26 93/11/04 20:06:09 +; int2E_far_entry now does CLI and STI the correct way round when loading +; SS and SP. +; CSTART.ASM 1.25 93/10/24 13:13:34 +; Added strategy 'best fit upper mem'' & link upper mem' +; put_resident_high() +; CSTART.ASM 1.24 93/09/10 15:56:46 +; CLS checks for ANSI using Int 2F/1A00 +; CSTART.ASM 1.23 93/08/26 09:40:50 +; Now use PSP for stack during func 4b exec. There's some debug +; code in case things screw up. +; CSTART.ASM 1.21 93/08/03 10:04:18 +; Stopped using memory above A000 for transient portion because the +; stack was disappearing when MEMMAX -V executed. +; CSTART.ASM 1.20 93/07/05 08:35:00 +; Now switch to a stack located at the top of conventional memory before +; calling INT 21 ah=4B. +; CSTART.ASM 1.19 93/05/24 11:38:22 +; alloc_com_memory now allocates copy buffer by allocating largest possible +; block then shrinking it to the correct size. This prevents the buffer +; being located in upper memory after a HILOAD. +; CSTART.ASM 1.16 93/02/24 17:42:01 +; int10_cls() no longer checks position of INT 29 vector. +; CSTART.ASM 1.12 92/11/17 14:26:40 +; Change to set_reload_file to allow switches on COMSPEC line. +; CSTART.ASM 1.10 92/09/17 11:31:43 +; INT 2e DS=SI=0 now works when we are relocated. +; CSTART.ASM 1.9 92/09/11 10:45:36 +; our_cmd_int2f altered so we can support multi-line macros in DOSKEY. +; CSTART.ASM 1.8 92/08/06 09:55:22 +; Correctly support INT 2F AH=AEh for EDOS. See _cmd_line_int2f. +; Int 2E DS=SI=0 causes batch processing to halt. +; CSTART.ASM 1.7 92/07/20 17:13:44 +; Added the following maintanence source code changes: +; 29 Apr 92 Now sets Novell error mode to 00 on entry, and restores +; ; original mode on exit. +; 18 May 92 Added routine get_original_envsize, to use as default if +; ; /E option not used +; ENDLOG + + page 62,132 + title COMMAND.COM Startup Routines and Resident Section +; +; 7 Nov 87 Force the initial PATH specification to the root of the +; boot drive. Also add a new variable TEMPDRV which is +; Concurrents Temporary Drive. +; +; 10 Dec 87 If DRNET has been loaded then add the DRNET=x.x string to +; the initial environment. +; 25 Feb 88 Run the 2nd Phase RSP's before spawning the remaining TMPs +; 1 Mar 88 Initialize the AUTOLOGON and NODE variables for diskless +; workstation support. Support the NODE environment variable +; 21 Mar 88 Allow for all registers to be corrupted on return from the +; DOS EXEC function call. +; 5 Apr 88 Correctly handle incorrect command line length passed by +; FrameWork Install Program +; 13 Apr 88 Move Memory allocation code to DOSIF and initialise the +; default console in PD for SunRiver. +; 10 May 88 Clean-Up the segment grouping and force the CGROUP to be +; linked after the data for everything but the TMP. Add the +; INT10_CLS function for DOSPLUS +; 12 May 88 Cater for DesqView passing an environment segment of 0000 +; 13 May 88 Alter FCB build to giver F & RED when /FRED typed in For FS.COM +; 19 May 88 Prevent CODE being moved to high memory if loaded as an .EXE +; or no initial environment is supplied +; 20 May 88 Move reload messages into the MESSAGE.C file. +; 24 May 88 Use the internal Critical Error handler and check for ABORT +; codes while in the Command Processor Code. +; 6 Jun 88 Move Command ReadLine down to resident code - so SK+ can +; overwrite the hi-mem portion. +; 16 Jun 88 VC_DATA now returns the Physical Console Number as well. +; 21 Jun 88 Add FARPTR routine which determines the correct segment to +; return to PRINTF based on the offset of a message. +; 22 Jun 88 remove environment & PSP setup & RSP spawning code +; for banked RSP support. Kludgey CDOS_EXEC code for banking +; 29 Jun 88 Modify MASTER_ENV so it can be called from C and change the +; exec code to use the internal FCB parsing. +; 30 Jun 88 Set the default PRINTER and AUX using the information in the +; INT17 and INT14 mapping arrays. +; 20 Jul 88 Increase HEAP Size to 0A00h for the TMP +; 9 Aug 88 Terminate the command line after a CR or LF for +; BitStream Fontware. +; 31 Aug 88 Make the READLINE function call from high memory so PolyTron +; PolyWindows can be invoked from the command line. +; 22 Sep 88 Always use INT_BREAK routine for Control Break Handling +; 03 Oct 88 Invalidate the Old Environment for Novell under CDOS. +; 09 Nov 88 Select the correct DR-DOS history Buffer. +; 15 Nov 88 Re-initilaise Interrupt handlers after an EXEC for Novell +; 21 Nov 88 Install Command Processor Backdoor but just terminate caller +; 13 Dec 88 Generate the FCBs for a DOS exec internally for compatibility +; with Novell Netware. +; 15 Dec 88 Force the default INT 22, 23, 24 and 2E handlers to be set +; relative to the PSP. Update PSP copies of interrupt 22, 23, 24 +; if this is the root DOS process. +; 25 Jan 89 If new DRDOS internal data layout get the PD a new way +; 27 Feb 89 fix MAKE_FCB, use SI from F_PARSE if possible +; 15 Apr 89 INT2E handler +; 17 Apr 89 int10_cls: don't return to 25 lines if in 43 or 50 line mode +; 31 May 89 DRDOS get PD using new f4458 backdoor +; 6 Jun 89 int2e: amend our copy of command, not users command +; 19 Jun 89 Remove "Alternative" methods of getting PD address +; 14 Jul 89 SideKick Plus checksum only done if STDERR is to CON +; (so when LAPLINK does CTTY COM1 it goes quicker) +; 6 Sep 89 Call INT21/5D09,5D08 in readline +; 30 Oct 89 Throw away startup code (put it in STACK segment) +; 13 Nov 89 Relocate DRDOS resident code over command line/fcbs in PSP +; 30 Jan 90 in_exec is now incremented and decremented to allow +; novell menu program to exit successfully. +; 30 Jan 90 Added batch_seg_ptr before first occurance of string +; 'A:\COMMAND.COM' (reload_file). Novell uses it during +; remote boot. +; 31 Jan 90 restore_term_addr puts back old Int22/23/24 ready for +; an EXIT command (DESQview bug) +; If no environment make reload_file in root of default drive +; 7 Feb 90 Turn off HILOAD on DRDOS +; Add d2cgroupptr support routine (see COM.C) +; 27 Mar 90 turn history buffers to command when in readline, so COPY CON +; etc will use application buffers +; 30 Mar 90 Stop cleanly when we can't reload transient portion rather +; than overwriting other peoples memory and crashing +; 4 Apr 90 dbcs_init moved from DOSIF, use system table, +; throw away init code +; 12 Apr 90 changed for no inherited environment +; 18 Apr 90 add JW's changes to int10_cls to support JW's new VGA card +; 9 May 90 Int2E doesn't trash Int24, returns with CY clear +; 17 May 90 CLI/STI round stack swap in INT2E exit routine. +; 5 Jun 90 Int21/4458 checks CY before fetching PD, so if running on DOS +; we carry on into the C code which gives version error +; 12 Jun 90 master_env now leaves MS_M_STARTEGY alone, because Novell +; gets confused if it ends up high +; 3/Jul/90 DLS data into R_TEXT for Watcom C v7.0 (again - I originally +; did this on 20/Apr/90, but someone screwed up with the +; archive version managment). +; 2-Aug-90 RG-00- define LOGIN procedures for Stellar security +; 1-Sep-90 _msgfarptr added for DLS +; 13-Sep-90 COMSPEC=A:\COMMAND.COM even when CDOS.COM +; 21-Sep-90 Increase TMP heap size so we can save initial state for +; subsequent login's. +; 26-Sep-90 We now switch to our own psp during an INT 2Eh. +; This fixes bug experienced with NOVELL MENU.EXE on top of +; DR DOS 5.0. +; 11-Oct-90 CDOSTMP exec stashes unlinked MD in PSP for TSR auto-load +; 03-Dec-90 Stop corruption of DMD chain when allocating high memory for +; transient portion of command processor +; 11 dec 90 CDOS.COM switches to TMP history buffer +; 13 dec 90 save ES around TMP P_EXEC (DRNET sometimes trashes it) +; 17 dec 90 exec of CMD call io_pckbd with cl=40h (must be 24 line) +; 26/Feb/91 Increased _rld_msgs maximum text size from 100 to 120. +; 11/Mar/91 Added show_help function. COMMAND.COM is now really +; an EXE file with the help messages tagged onto the end. +; 25/Apr/91 Most of the resident code/data is now relocatable to high +; memory. Some Novell critical data is left in low memory. +; 15/May/91 Added dummy code to force at least one relocation item in +; .exe header so loader doesn't think file is EXEPACKed. +; 12/Jun/91 Added dummy code to allow Software Carousel to run. +; See int22_entry. +; 19 jun 91 disable control break until handler initialised +; 24/Jun/91 Changed memory allocation procedure on return from func 4B to +; allow Novell Remote Boot to work. +; 2 jul 91 our_cmd_int2f only has single parameter +; 26 jul 91 Novell dummy pipe filenames zero terminated +; 29 jul 91 A 1K far buffer is now allocated by alloc_com_memory. It is +; used by type, batch_read, and printf. +; 5 Aug 91 Call Get Extended Error (int 21 ah=59) after exec. +; 14 Aug 91 Put pointers to _batch, _batchflg, and _echoflg in low memory +; stub. This is primarily for Software Carousel. +; 4 Dec 91 Fixed problem with full environment trashing next DMD. +; 29 Apr 92 Rearranged DGROUP so that constant code and data appear after +; the stack - So that Multitasker need not save it. +; 10 Jun 92 show_help function now copes with doubled % characters. +; +;------------------------------------------------------------------------------ + +.xlist +include msdos.equ +include mserror.equ +include char.def +.list + + +; This is the offset in segment FFFF to which we will relocate. +; It is set to E0 to allow for a PCNFS bug +HISEG_OFF equ 0E0h + + +FALSE equ 0h +TRUE equ not FALSE + +ThreeCOM equ TRUE + + +Copy_Buffer_Size equ 0C80h ; 50k of buffer space in paras + ; matches MAX_COPYBUF in COMCPY.C +RLSTACK_SIZE equ 256+256 ; Reserve for ReadLine stack + ; We need 260 bytes for possible + ; buffer, plus a little stack + ; If the stack overflows it isn't + ; a disaster - we will just re-load + ; COMMAND.COM + +ifdef CDOSTMP +C_HEAP_SIZE equ 1200h ; C routine Heap Size - TMP has +else ; extra to save ENV in +;C_HEAP_SIZE equ 0800h ; C routine Heap Size +;endif ; (observed sizes 500h-600h - IJ) +C_HEAP_SIZE equ 0860h ; C routine Heap Size +; For safety increased that value as UNC filenames require 128 byte buffers +; allocated dynamically on tha stack. With respect to the observed sizes +; above it might be dangerous to leave that value at 0800h. I would have +; increased the value to 0A00 but then it does no longer fit into HMA. (JBM) +endif + +ifdef DOSPLUS +include f52data.def +else +.xlist +include system.def +include pd.def +.list + +XIOS_HISTBUF equ 44 ; Get the History Buffer Address +XIOS_PCKBD equ 32 ; Set keyboard/screen modes + +NETMOD_BIT equ 040h ; Network Module in MODULE_MAP + +; Concurrent DOS System Data Page Format +XIOS_ENTRY equ ds:dword ptr 0028h ; XIOS function Entry +CCPMSEG equ es:word ptr 0040h ; OS Starting Paragraph +MODULE_MAP equ es:byte ptr 0046h ; Concurrent Module Map +NVCNS equ es:byte ptr 0047h ; Number of Virtual Consoles +MFL equ es:word ptr 005Ah ; Memory Free List +RLR equ es:word ptr 0068h ; Ready List Root +VERSION equ es:word ptr 0078h ; OS Version String Offset +MWDR equ es:word ptr 0098h ; Memory Window Decriptor +BOOTDRV equ es:byte ptr 009Dh ; System Boot Drive +ENVSIZE equ es:word ptr 00B8h ; Environment Size Bytes +DRNET_NODE equ es:byte ptr 00BAh ; DR-NET Node Number +DRNET_FLAG equ es:byte ptr 00BB ; DR-NET Flags +V386_PTR equ es:word ptr 00C8h ; 386 Data pointer + +CCBLIST equ es:word ptr 0C3Eh ; XIOS CCB$LIST +INT17_PTR equ es:word ptr 0C46h ; XIOS INT 17 Mapping Array +INT14_PTR equ es:word ptr 0C48h ; XIOS INT 14 Mapping Array + +CCB_OWNER equ es:word ptr 0 ; CCB Owning Process +CCB_PCNS equ es:byte ptr 10 ; CCB Physical Console Number +CCB_VCNS equ es:byte ptr 11 ; CCB Virtual Console Number + +MF_CODE equ 0004h ; MD flag bit +endif +; +; Standard definitions for PSP variable +; +PSP_TERM_IP equ es:word ptr 000Ah +PSP_PARENT equ es:word ptr 0016h +PSP_ENVIRON equ es:word ptr 002ch + + +ifndef DOSPLUS +; The following Macro takes one parameter which is the Concurrent DOS +; function number. + +bdos MACRO func +ifnb + mov cl,func +endif + int 224 + ENDM + +.xlist +include ccpm.equ +.list +endif + +swap MACRO reg1, reg2 + push reg1 + push reg2 + pop reg1 + pop reg2 + ENDM + + page +ifdef CDOSTMP +; +; For the Concurrent DOS TMP the CGROUP segments are defined +; first so that the CGROUP appears first in the .EXE file and +; can be converted to a .COM by "RELOC" or "EXE2BIN". This .COM +; file is then converted to a .CMD by the COM2CMD utility which +; uses the data embeded at the start of the code to generate the +; right groups. +; +HGROUP GROUP HEADER +HEADER SEGMENT para public 'HEADER' +HEADER ENDS + +DGROUP GROUP RSP_SEG,PD_SEG,UDA_SEG,NULL,EXEC_CODE,_DATA,DATA,CONST,FIXED,_BSS,HEAP,c_common,STACK,DYNAMIC + +RSP_SEG SEGMENT para public 'CDOS_DATA' +RSP_SEG ENDS +PD_SEG SEGMENT para public 'CDOS_DATA' +PD_SEG ENDS +UDA_SEG SEGMENT para public 'CDOS_DATA' +UDA_SEG ENDS +NULL SEGMENT para public 'BEGDATA' +NULL ENDS +EXEC_CODE SEGMENT byte public 'DATA' +EXEC_CODE ENDS +_DATA SEGMENT byte public 'DATA' +_DATA ENDS +DATA SEGMENT byte public 'DATA' +DATA ENDS +CONST SEGMENT byte public 'CONST' +CONST ENDS +FIXED SEGMENT para public 'FDATA' +FIXED ENDS +_BSS SEGMENT word public 'BSS' +_BSS ENDS +HEAP SEGMENT word public 'BSS' +HEAP ENDS +c_common SEGMENT byte public 'BSS' +c_common ENDS +STACK SEGMENT para public 'BSS' +STACK ENDS +DYNAMIC SEGMENT para public 'DDATA' +DYNAMIC ENDS +endif + +ifndef CDOSTMP +; The following declarations declare the presence and order of +; various data segments within the DATA Group of the command +; processor. +; +DGROUP GROUP R_TEXT, ED_TEXT, NULL, _DATA, DATA, CONST, FIXED, _BSS, HEAP, c_common, STACK, DYNAMIC + +R_TEXT SEGMENT para public 'CDOS_DATA' +R_TEXT ENDS +NULL SEGMENT byte public 'BEGDATA' +NULL ENDS +_DATA SEGMENT byte public 'DATA' +_DATA ENDS +DATA SEGMENT byte public 'DATA' +DATA ENDS +CONST SEGMENT byte public 'CONST' +CONST ENDS +FIXED SEGMENT byte public 'FDATA' +FIXED ENDS +_BSS SEGMENT byte public 'BSS' +_BSS ENDS +HEAP SEGMENT byte public 'BSS' +HEAP ENDS +c_common SEGMENT byte public 'BSS' +c_common ENDS +STACK SEGMENT word public 'STACK' +STACK ENDS +ED_TEXT SEGMENT para public 'CDATA' + Public ed_text_start +ed_text_start label byte +ED_TEXT ENDS +DYNAMIC SEGMENT para public 'DDATA' +DYNAMIC ENDS +endif + +CGROUP GROUP _TEXT, _MSG, _TEXTEND +_TEXT SEGMENT para public 'CODE' +ifdef DLS + extrn _my_dls_init:far +endif +_TEXT ENDS + +_MSG SEGMENT byte public 'CODE' +_MSG ENDS + +_TEXTEND SEGMENT para public 'CODE' +_TEXTEND ENDS + + +CEND GROUP ETEXT, ETEXTEND +ETEXT SEGMENT para public 'XEND' +ETEXT ENDS +ETEXTEND SEGMENT para public 'XEND' +ETEXTEND ENDS + + +codeOFFSET equ offset CGROUP: +dataOFFSET equ offset DGROUP: +endOFFSET equ offset CEND: + +code_length equ codeOFFSET rlstack ; Total Code Length +real_code equ code_length - RLSTACK_SIZE +static_length equ dataOFFSET FIXED ; Static Data Length +dynamic_length equ dataOFFSET ed_text_start +total_length equ dataOFFSET DYNAMIC ; Total Data Length +cgroup_length equ codeOFFSET _TEXTEND +cend_length equ endOFFSET ETEXTEND + +; help_length is an APPROXIMATE value, but it must be LARGER than the correct +; length of the help segment. +ifdef DLS +help_length equ 0A000h +else +help_length equ 05000h +endif + +page +public __acrtused ; trick to force in startup + __acrtused = 9876h ; funny value not easily matched in SYMDEB + +ifdef CDOSTMP +HEADER SEGMENT public 'HEADER' + dw 0EDCh ; Header Signature + dw offset HGROUP:CGROUP ; Code Group + dw real_code ; Real Code Size + dw offset HGROUP:DGROUP + dw total_length + dw static_length +HEADER ENDS + +; These Segments are forced into the correct order for a CDOS +; Resident System Process. First the RSP header which contains +; the regeneration information required by GENSYS. +; +RSP_SEG SEGMENT +sysdatseg dw 0 ; system data segment +sdatvar dw 0047h ; # of system consoles +defconsole db 0,0 ; console # | copy # + dw 0,0 + dw RSF_DYNAMIC+RSF_SPECIAL+RSF_ENVIRON + dw 0 + dw 0 + +RSP_SEG ENDS + +_DATA SEGMENT byte public 'DATA' + extrn _gp_far_buff:word +_DATA ENDS + +else +R_TEXT SEGMENT + assume cs:DGROUP, ds:nothing, es:nothing, ss:nothing + +ifdef WATCOMC + Public _small_code_ ; Watcom C requires this label to +_small_code_ label near ; be declared in the start-up module +else +ifdef MWC + Public _mwINIT ; MetaWare requires this label +_mwINIT label near ; to be declared in the start-up + ; module +else + Public __cstart +__cstart label near ; to be declared in the start-up + ; module +endif +endif + + extrn _gp_far_buff:word + +ifdef DOSPLUS + extrn com_criterr:near +endif + + +cstart: ; start address of all "C" programs + call near ptr getIP ; Push the IP register and Skip the +retIP: ; version control messages. + dw 0EDCh ; Digital Research Marker + dw code_length ; Length of the Code Group + ;dw static_length ; Length of the Fixed Data Group +ifdef DLS + dw total_length +else + dw dynamic_length ; length of dynamic data +endif + dw total_length ; Minimum Length of the Runtime + ; Data Group + +reloc_off dw 0 ; offset of relocated resident code/data +reloc_seg dw 0 ; segment of relocated resident code/data +reloc_size dw 0 ; size of relocated resident code/data + + public _batchptr_off + public _batchflg_off + public _echoflg_off +_batchptr_off dw 0 ; offset of _batch variable +_batchflg_off dw 0 ; offset of _batchflg variable +_echoflg_off dw 0 ; offset of _echoflg variable + +; These are the entry points for INT 23 and INT 24. They will have JMPF +; instructions poked into them. +control_break_entry db 5 dup(90h) +crit_error_entry db 5 dup(90h) + + +; The call to MS_X_EXEC must be made from the same segment as the PSP. +; msdos_exec does a far jump to here and then we far jump back. + +psp_dofunc4b: + mov ax,(MS_X_EXEC*256) + int DOS_INT + jmp i22_entry + +; Software Carousel Version 5.0 looks for the following three instructions +; and assumes it is an entry point to int 22 code. + mov bx,0ffffh + mov ah,48h + int 21h + clc +i22_entry: +int22_entry db 0eah + dw dataOFFSET func4b_return +func4b_seg dw 0 + +int2E_entry db 0eah + dw dataOFFSET int2E_far_entry +int2E_seg dw 0 + + +; IMPORTANT - batch_seg_ptr MUST be just before reload_file. - EJH +; +; ***** Do Not change the order of the following variables ***** +; + +batch_seg_ptr dw 0ffffh ; file filename. For novell remote + ; boot support. + +ifdef DOSPLUS +reload_file db 'A:\COMMAND.COM',0 +else +ifdef NETWARE +reload_file db 'A:\NETWARE.COM',0 +else +reload_file db 'A:\CDOS.COM',0 +endif +endif + db (80-15) dup ('n') ; Expanded LoadPath + +;cmdline db 128 dup ('c') ; Local Copy of Initial Command Line + +; dummy pipe filenames for NOVELL + +out_pipe db '_:/' , 0 , '_______.___',0 +in_pipe db '_:/' , 0 , '_______.___',0 + +; +; ***** Do Not change the order of the preceeding variables ***** +; + +; This next bit forces hi_seg_start to be on a paragraph boundary + org HISEG_OFF +hi_seg_start label byte + +; Himem Registration chain entry +himem_link_next dw 0 +himem_link_size dw 0 + db 5 + + public __psp +__psp dw 0 + + Public _batch_seg_ptr +_batch_seg_ptr dw dataOFFSET batch_seg_ptr + dw 0 ; segment will be set to low_seg + + Public _cbreak_ok + +_cbreak_ok db 0 ; set when ctrl-break handler initialised + + ; The following causes there to be at least one relocation item + ; in the .exe header so the loader does not think the file is + ; EXEPACKed. + mov ax,seg _batch_seg_ptr + +R_TEXT ENDS + +endif + +_TEXT SEGMENT +ifdef CDOSTMP + assume cs:CGROUP, ds:DGROUP, ss:DGROUP +; +; This entry point is used when the startup is executed as an +; RSP. CS is CGROUP and DS is DGROUP. From here on we initialise +; internal data structures etc. +; + +ifdef WATCOMC + Public _small_code_ ; Watcom C requires this label to +_small_code_ label near ; be declared in the start-up module +else +ifdef MWC + Public _mwINIT ; MetaWare requires this label +_mwINIT label near ; to be declared in the start-up + ; module +else + Public __cstart +__cstart label near ; to be declared in the start-up + ; module +endif +endif + +cstart: + call RSP_start ; Push the IP register and Skip the +retIP: ; version control messages. + dw 0EDCh ; Digital Research Marker + dw code_length ; Length of the Code Group + dw static_length ; Length of the Fixed Data Group + dw total_length ; Minimum Length of the Runtime + ; Data Group +else + extrn _int2e_handler:far +endif + extrn __main:far ; C main program + + +_TEXT ENDS + +_DATA SEGMENT +; +; Data held in this segment remains in the resident portion of +; the program image is is not overlayed by transient programs +; loaded by COMMAND.COM. The variables here are private to the +; startup module. +; +psp_save_area dw 6 dup (?) + +ifndef DOSPLUS + extrn _pd:dword ; Concurrent Process Descriptor + extrn _sysdat_seg:word ; Concurrent System Data Page +endif + + extrn _n_option:word +; +; The following is the offset and segment of the C routine MAIN +; which is moved up in memory in order to accomodate the +; Environment variables and Resident Data area. +; +C_code_entry label dword + Public code_seg,low_seg +code_off dw codeOFFSET __main ; Offset of MAIN +code_seg dw ? ; Segment of MAIN +data_seg dw ? ; DGROUP segment +alloc_seg dw ? ; the start of hi mem allocated +low_seg dw ? ; segment of low memory stub. + +ifdef CDOSTMP + + Public __psp +__psp dw 0 + +cmd_histbuf dw 0 ; Command Processor History Buffer +prog_histbuf dw 0 ; Program History Buffer + +mpb label word +mpb_start dw ? +mpb_min dw ? +mpb_max dw ? +mpb_pdadr dw ? +mpb_flags dw ? + +sysdat dw ? ; Concurrent System Data Page +uda dw ? ; Concurrent User Data Area +; +; The following buffer is used by the P_EXEC function. Used +; by CDOS_EXEC to load DOS and CP/M programs. +; +exec_block label byte +exec_pathoff dw ? ; Offset of ASCIIZ Load file +exec_pathseg dw ? ; Segment of ASCIIZ Load File +exec_filetype db ? ; File Type Index +exec_loadtype db ? ; EXEC or CHAIN to application +exec_clineoff dw ? ; ASCIIZ Command line Offset +exec_clineseg dw ? ; ASCIIZ Command Line Segment + +exec label dword ; FAR pointer to EXEC routine + dw dataOFFSET cdos_exec +exec_seg dw ? + +cmdline db 0 ; Blank Command Line + +EXEC_CODE SEGMENT + + Assume CS:DGROUP, DS:DGROUP, SS:DGROUP + +err_tbl db 0 ; 00 Success + db -101 ; 01 System Call Not Implemented + db -102 ; 02 Illegal System Call + db ED_MEMORY ; 03 Cannot Find Memory + db -104 ; 04 Illegal Flag Number + db -105 ; 05 Flag Overrun + db -106 ; 06 Flag Underrun + db -107 ; 07 No Unused Queue Descriptors + db -108 ; 08 No free Queue Buffer + db -109 ; 09 Cannot find Queue + db -110 ; 10 Queue in Use + db -111 ; 11 + db -112 ; 12 No Free Process Descriptors + db -113 ; 13 No Queue Access + db -114 ; 14 Empty Queue + db -115 ; 15 Full Queue + db -116 ; 16 CLI Queue missing + db -117 ; 17 No 8087 in system + db ED_DMD ; 18 No Unused Memory Descriptors + db -119 ; 19 Illegal Console Number + db -120 ; 20 No Process Descriptor Match + db -121 ; 21 No Console Match + db -122 ; 22 No CLI Process ?? + db -123 ; 23 Illegal Disk Number + db -124 ; 24 Illegal FileName + db -125 ; 25 Illegal FileType + db -126 ; 26 Character Not Ready + db ED_BLOCK ; 27 Illegal Memory Descriptor + db -128 ; 28 Bad Return from BDOS load + db ED_FAIL ; 29 Bad Return from BDOS read + db ED_ACCESS ; 30 Bad Return from BDOS Open + db -131 ; 31 Null Command + db ED_ENVIRON ; 32 Not owner of resource + db -133 ; 33 No Cseg in Load File + db -134 ; 34 PD exists on Thread Root + db -135 ; 35 Could Not Terminate Process + db -136 ; 36 Cannot ATTACH to Process + db -137 ; 37 Illegal List Device Number + db ED_PASSWORD ; 38 Illegal Password + db -139 ; 39 + db -140 ; 40 External Termination + db -141 ; 41 Fixup Error on Load + db -142 ; 42 Flag Set Ignored + db -143 ; 43 Illegal Aux Device Number + +cdos2dos PROC NEAR + cmp ax,0000 ; Check for Success + jz c2d10 ; and skip lookup + lea bx,err_tbl ; xlat the error code in AL + xlat err_tbl ; into a Negated DOS compatible + mov ah,0FFH ; error code +c2d10: + ret +cdos2dos ENDP + +; WORD FAR CDECL cdos_exec(BYTE *path, UWORD type, BYTE *line, BOOLEAN back); +; +; On Entry: +; back 10[bp] +; line 08[bp] +; type 06[bp] +; path 04[bp] +; +; ES = SYSDAT +; +; On Exit: +; AX = exit error code +; +cdos_exec PROC FAR + lea si,P_MEM[bx] ; SI -> root of MD's +ce_10: ; find our code segment + mov si,es:[si] ; get next memory descriptor + test si,si ; end of list? + jz ce_40 ; yes, we don't own any separate code + test es:word ptr 6[si],MF_CODE + jz ce_10 ; loop back if not code segment + mov si,es:8[si] ; get MPAD for code segment + lea di,P_MPAR[bx] ; get MPAD root +ce_20: + cmp si,es:[di] ; is this the predecessor? + je ce_30 + mov di,es:[di] ; else check next MPAD + jmp short ce_20 +ce_30: ; SI -> our MPAD, DI -> previous MPAD + xor ax,ax + xchg ax,es:[si] ; get next MPAD + mov es:[di],ax ; unlink our MPAD from list +ce_40: + push di + push si ; SI = 0 if no separate code alloc + + push ds + mov ds,es:P_PSP[bx] ; point to our PSP + mov ds:word ptr [5eh],si ; stash TMP mpad away in here + pop ds + + mov dx,198 ; Raise the priority of the TMP + bdos P_PRIORITY ; while we wait for the child + + mov dx,dataOFFSET exec_block + push es ; do a P_EXEC but save /restore + bdos P_EXEC ; ES around it since DRNET trashes + pop es ; it sometimes. + + mov ax,cx ; Get the Concurrent Error Code + call cdos2dos ; and convert to a standard DOS + push ax + ; Error Code for COMMAND.RSP + test ax,ax ; If any errors occured during the + jnz ce_60 ; exec or the child process is not + cmp word ptr 10[bp],0 ; inheriting the console the do not + jnz ce_60 ; execute a Console Attach function + bdos C_ATTACH ; process to terminate +ce_60: + mov dx,200 ; Return to the normal priority + bdos P_PRIORITY ; now that we have the console back + pop ax + pop si + pop di + test si,si ; separate code allocation? + jz ce_50 ; no, don't have to un-kludge! + push ax + mov ax,es:[di] ; get link of previous MPAD + mov es:[si],ax ; link it to our MPAD + mov es:[di],si ; link our MPAD to previous MPAD + mov dx,1 ; make sure code gets banked in + bdos P_DELAY ; this gets us off/on RLR + pop ax +ce_50: + ret +cdos_exec ENDP + +EXEC_CODE ENDS + +_TEXT SEGMENT + assume cs:CGROUP, ds:DGROUP, es:nothing, ss:nothing + public _exec ; EXEC routine + +; +; WORD CDECL exec(BYTE *path, UWORD type, BYTE *line, BOOLEAN back); +; +; On Entry: +; back 10[bp] ; This value is ignored for MSDOS_EXEC +; line 08[bp] +; type 06[bp] +; path 04[bp] +; +; On Exit: +; AX = exit error code +; +_exec: +;----- + push bp + mov bp,sp + push si + push di + mov ax,04[bp] ; Get the Full Command Name + mov exec_pathoff,ax + mov exec_pathseg,ds + + mov ax,08[bp] ; and the Command Line + mov exec_clineoff,ax + mov exec_clineseg,ds + + mov ax,06[bp] ; Get the Command Type (.CMD etc) + mov exec_filetype,al ; Save the Command type + mov exec_loadtype, 0 ; The default is to load the command + cmp word ptr 10[bp],0 ; and for the child to inherit the + jz exec_10 ; console + mov exec_loadtype,2 +exec_10: + + test al,al ; is command type a CMD + jnz exec20 ; no, skip XIOS call + mov ax,XIOS_PCKBD ; CMD's expect 24 lines + mov cl,40h ; so tell XIOS thats what we must have + mov dl,defconsole ; on this console + call xios +exec20: + + les bx,_pd ; Get the process Descriptor Address + mov cx,prog_histbuf ; and force the system to use the + mov es:P_SB_SEG[bx],cx ; Program Level History Buffer + + call exec ; do FAR call to cdos_exec + + les bx,_pd ; Get the process Descriptor Address + mov cx,cmd_histbuf ; and force the system to use the + mov es:P_SB_SEG[bx],cx ; Command Level History Buffer + + cmp exec_filetype,0 ; was it a CMD + jne exec30 + push ax + mov ax,XIOS_PCKBD ; we are in must-be-24 line + mov cl,0 ; mode, get back to default mode + mov dl,defconsole ; for console number + call xios + pop ax +exec30: + pop di + pop si + pop bp + ret + +_TEXT ENDS + + + Assume CS:DGROUP, DS:DGROUP, SS:DGROUP +else +; +; Novell 2.1 intercepts the DOSPLUS 4B00 return by updating the +; PSP USER_SS/SP and when it returns ALL registers except CS:IP +; have been corrupted. +; + extrn stack_min:word ; Minimum Stack Address + extrn heap_top:word + +readline label dword ; FAR pointer to READLINE routine + dw dataOFFSET msdos_readline +readline_seg dw ? + +critical dd ? ; Critical Error Handler Address +exec_sp dw ? +exec_ss dw ? + +exec_block label byte +exec_env dw ? ; Environment Segment +exec_clineoff dw ? ; ASCIIZ Command line Offset +exec_clineseg dw ? ; ASCIIZ Command Line Segment +exec_fcb1off dw dataOFFSET fcb1 ; FCB1 Contents Offset +exec_fcb1seg dw ? ; FCB1 Contents Segment +exec_fcb2off dw dataOFFSET fcb2 ; FCB2 Contents Offset +exec_fcb2seg dw ? ; FCB2 Contents Segment + +exec label dword ; FAR pointer to EXEC routine + dw dataOFFSET msdos_exec +exec_seg dw ? + +msdos_exec_ret label dword ; FAR pointer to exit EXEC routine + dw codeOFFSET _exec_ret +msdos_exec_ret_seg dw ? + +fcb1 db 16 dup (?) ; FCB1 Buffer +fcb2 db 16 dup (?) ; FCB2 Buffer +crc dw ? ; COMMAND.COM crc + +; For Dual Language Support... +ifdef DLS +;;ED_TEXT SEGMENT para public 'CDATA' + + Public _rld_msgs,_rld_text +_rld_msgs dw 120 ;RELOAD_LEN ; size of this message buffer +_reload_msgs dw 0 ; First part of Code reload prompt +_reload_msgf dw 0 ; Second part of Code reload prompt +_reload_msgm dw 0 ; Unlikely part of Code reload prompt + dw 0 ; end of list +_rld_text db 120 dup (?) ; message text is placed here +RELOAD_LEN equ $-_reload_msgs +;;ED_TEXT ENDS +else + extrn _reload_msgs:byte ; First part of Code reload prompt + extrn _reload_msgf:byte ; Second part of Code reload prompt + extrn _reload_msgm:byte ; No memory available message +endif + + +reload_flag db 0 ; Reloading Command Processor +in_exec db 0 +high_code dw TRUE ; Enable High Code +exe_file dw FALSE ; True if COMMAND.COM is really an EXE +return_code dw ? ; Exec return code +net_error_mode db ? + +; int2E data + +i2e_lock dw 0 ; mutex flag +i2e_user_ss dw 0 ; users ss, sp +i2e_user_sp dw 0 +i2e_stack dw 0 +i2e_cmd dw 0 ; offset of local copy of command line + +i2e_c_entry label dword +i2e_c_offs dw codeOFFSET _int2e_handler +i2e_c_seg dw ? + +i2e_i23vec label dword +i2e_i23off dw ? +i2e_i23seg dw ? + +i2e_i24vec label dword +i2e_i24off dw ? +i2e_i24seg dw ? + +endif +_DATA ENDS + +_BSS SEGMENT +Public _edata +_edata label BYTE ; end of data (start of bss) +_BSS ENDS + +ETEXT SEGMENT +; +; The RLSTACK segment holds the stack used by the READLINE routine. +; This must be in High memory for the PolyTron PolyWindows product. +; +; "ETEXT" also forces the linker to pad the CGROUP to at least +; real_code bytes. Otherwise the file length can be upto 15 bytes +; shorter then real_code + total_length. This obviously causes +; problems with CALC_CRC and the file reloading. +; + db RLSTACK_SIZE dup(0CCh) +rlstack label word + +ETEXT ENDS + +ifdef CDOSTMP +STACK SEGMENT + +Public _end +_end label BYTE ; end of bss (start of starup/stack) + + db (C_HEAP_SIZE - 6) dup (0DDh) ; C Heap Area +stack_top label word +stack_ip dw ? ; Initial Offset +stack_cs dw ? ; Initial Code Segment (Unknown) +stack_flags dw ? ; Initial Flags (Unknown) + +temp_buffer db 512 dup(0) ; temp far buffer for *gp_far_buff + +STACK ENDS +else + +STACK SEGMENT + +stack_start: +; HEAP_TOP is initialised to _end so the _RELOAD_FILE and CMDLINE +; variables are allocated on the HEAP. +; + +Public _end +_end label BYTE ; end of bss (start of startup/stack) + + + db 255,'3771146-XXXX-654321' + + page +; +; The CS register is now adjusted so that this startup +; can be used in the form of an .EXE or .COM. Whatever the +; execution format of this file DS still points at the PSP +; but must be careful when resizing the RAM. +; +getIP PROC FAR + cld ; be sure of DIR flag... + pop di ; Get the Program Counter + sub di,dataOFFSET retIP ; Correct for retIP + mov cl,4 ; Convert Offset values to Segments + mov ax,cs ; Get the current CS + shr di,cl ; Convert Initial IP to Segment + add ax,di ; add to CS and save for CALLF to MAIN + push ax ; Save the New CS and the offset to + mov ax,dataOFFSET gotCS ; the next instruction and then execute + push ax + ret ; a RETF instruction to correct CS. +getIP ENDP + +ifdef DOSPLUS + +; Most of the PSP (FCB's and command buffer) is unused - we reclaim this space +; by relocating the resident part of COMMAND.COM + +reloc_code: +;---------- +; On Entry: +; CS = DGROUP, DS = PSP, ES = nothing +; On Exit: +; CS = relocated DGROUP +; +; We build a "REP MOVSB ! RETF 6" on the stack. We also fiddle the near return +; address into a FAR. We then setup our registers appropriately and execute +; this code. +; +if 1 + ret +else + cmp ds:byte ptr 0080h,7fh ; discard garbage cmdline lengths + jb reloc_code10 + ret + +reloc_code10: + pop bx ; recover return offset + + mov ax,0 + push ax ; 0 (part of RETF 6) + mov ax,006cah + push ax ; RETF 6 on stack + + mov ax,0a4f3h + push ax ; REP MOVSB on stack + + mov al,ds:0080h ; Get the Command length + xor ah,ah + mov cl,4 ; convert AX to cmdline length + shr ax,cl ; in rounded down para's + add ax,9 ; keep at least this much + mov si,ds + add ax,si ; add in PSP + mov es,ax + mov cx,sp ; save address of code on stack + push ax + push bx ; new RETF address on stack + + push ss + push cx ; address of CODE on stack + + push cs + pop ds ; DS -> DGROUP + xor si,si ; setup DS:SI, ES:DI and CX + xor di,di ; ready to do REP MOVSB + mov cx,total_length ; DGROUP length + add cx,real_code ;+CGROUP length + + db 0cbh ; RETF to code on stack +endif +endif + +gotCS: + ;out 0fdh,al ; for debug purposes + + mov [__psp],ds ; Save our PSP in the local variable +ifdef DOSPLUS + mov ax,cs ; put our stack somewhere safe + mov ss,ax + mov sp,dataOFFSET rlstack + push ds + push di + call reloc_code ; relocate code over unused bit of PSP + pop di + pop ds +endif +ifdef DLS + call _my_dls_init +endif + + mov [code_seg],cs ; Initialise the DATA segment address + mov [data_seg],cs ; and calculate the current address + mov [exec_seg],cs ; of the Code Segment + mov [readline_seg],cs ; use it to fixup some JMPFs + mov [_batch_seg_ptr+2],cs + mov [low_seg],cs ; we may be relocated to upper or high + ; memory so remember the current segment + + mov bx,cs ; Path up the JMPF instructions + sub bx,[__psp] ; around the MSDOS EXEC code to + mov cl,4 + shl bx,cl + add cs:[exec_psp-2],bx + mov cs:[func4b_seg],cs + mov cs:[int2E_seg],cs + mov cs:[exec_psp],ds + + cmp di,0000h ; Disable Code Relocation if we have + jnz gotCS_10 ; been loaded as an .EXE file + ;;mov high_code,FALSE + + mov exe_file,TRUE ; Remember we are an EXE + +gotCS_10: + mov di,total_length + shr di,cl + add [code_seg],di + + push ds ; Initialise the Checksum so we can + mov ds,[code_seg] ; check the integrity of the high + mov si,2 ; high copy of the command processor + call calc_crc ; code + pop ds + mov [crc],ax + + mov ah,0ddh ; set Novell error mode + mov dl,0 ; to 00 - BAP + int 21h + mov net_error_mode,al ; save original error mode + + call get_ds ; Get DGROUP value in AX + cli ; turn off interrupts + mov ss,ax ; SS = DGROUP + mov sp,dynamic_length ; Initialise SP + ;mov sp,total_length + sti ; turn interrupts back on + + assume ss:DGROUP + + push ax + call handler_init ; Initialise the Control Break and + pop ax ; Critical Error Interrupt Vectors + + mov si,total_length ; Get the DGROUP length in bytes + add si,code_length ; Add in the Code Length + mov cl,4 ; and convert to a paragraphs + shr si,cl + mov bx,ax ; Get the Current DS + sub bx,__psp ; and calculate DS - PSP Seg + add bx,si ; DS + Data length in Para's + mov es,__psp + mov ah,MS_M_SETBLOCK + int DOS_INT + + call exec_name ; Get our Load Path from the environment + + cmp high_code,FALSE ; Skip Memory check if HIGH_CODE + jz cstart_10 ; support has been disabled + + mov high_code,FALSE ; Assume Failure. + + call alloc_com_memory ; Allocate high memory for command.com + jnc carry_on + + mov ax,cs ; if no memory and CS is nearing + cmp ax,8000h ; transient part abort and go home. + jb cstart_10 + + mov ah,4ch + int 21h + +carry_on: + mov high_code,TRUE ; Set HIGH_CODE flag TRUE + push es ; Relocate the command processor code + push ds ; into high memory + mov es,ax ; es-> destination segment + mov di,0 + mov si,0 + mov ds,code_seg ; ds-> code to be moved + mov cx,real_code ; convert bytes to words + shr cx,1 + rep movsw ; Move code up to high memory + mov code_seg,es ; update code_seg + + pop ds + pop es + +; Shrink memory containing low memory version of step aside code + mov si,total_length ; Get the DGROUP length in bytes + mov cl,4 ; and convert to a paragraphs + shr si,cl + call get_ds + mov bx,ax ; Get the Current DS + sub bx,__psp ; and calculate DS - PSP Seg + add bx,si ; DS + Data length in Para's + mov ah,MS_M_SETBLOCK + int DOS_INT + +cstart_10: +ifdef DOSPLUS + mov ax,4457h ; terminate HILOAD operation + mov dx,200h + int DOS_INT + call dbcs_init ; initialise the DBCS support +endif + call get_cs + push ax + mov ax,codeOFFSET memory_init + push ax + db 0CBh ; a RETF instruction to correct CS. + +page +; +; Build the full path and filename of this process using the +; loadpath attached to the environment. If no filename exists +; then prevent the Command Processor code from being located +; in high memory. +; +exec_name: + push es + mov es,__psp ; Get the PSP Segment Address + mov dx,PSP_ENVIRON ; Get the environment segment + cmp dx,0000 ; Have we got an environment ? + jz exec_n11 ; No prevent High Code Support + + mov es,dx ; Scan through the environment and + mov di,0 ; determine the Environment size and + mov al,0 ; the Load file name + mov cx,7FFFh +exec_n05: ; Scan through the Environment + repne scasb ; searching for the 00 00 terminator + jcxz exec_n10 ; Terminate On CX == 0000 + cmp es:byte ptr [di],al ; If the next byte is zero then this is + jnz exec_n05 ; then end of the environment + cmp es:word ptr 1[di],1 ; Are we pointing at the Control Word + jnz exec_n10 ; No then no Load Path exists + + push ds + mov ds,dx ; DS -> Environment Segment + ;call get_ds + ;mov es,ax ; ES -> Command Processor Data Seg + mov es,[low_seg] + lea si,03[di] ; Fully expand the filename so the + mov di,dataOFFSET reload_file ; user can SUBST drives + mov ah,60h + int DOS_INT +exec_n15: +if 0 + mov di,dataOFFSET reload_file ; this ASCIIZ string is on the heap + xor ax,ax ; so now we need to find out how + mov cx,-1 ; much space it takes up and reserve + repne scasb ; that amount of the heap + mov heap_top,di ; byte after the NUL is available +endif + pop ds + pop es + ret + +exec_n10: + mov high_code,FALSE +exec_n11: + mov ah,MS_DRV_GET + int DOS_INT ; get default drive + mov es,[low_seg] + add es:reload_file,al ; and use that for the comspec + push ds + ;call get_ds + ;mov es,ax ; ES -> Command Processor Data Seg + jmp exec_n15 + +ifdef DOSPLUS +DI_BUF_PTR equ dword ptr -4 ; pointer to DBCS lead byte table +DI_BUF_ID equ byte ptr -5 ; buffer id +DI_BUF equ byte ptr -5 ; buffer + +DI_LOCALS equ 5 ; No. bytes storage local to init_dbcs + +_DATA SEGMENT byte public 'DATA' + + Public dbcs_table_ptr + +dbcs_table_ptr label dword +dbcs_table_off dw dataOFFSET dummy_dbcs_table +dbcs_table_seg dw 0 + +dummy_dbcs_table dw 0 + +_DATA ENDS + +dbcs_init proc near +;-------- +; To initialise the double byte character set (DBCS) lead byte table. +; MUST be called before the first call to dbcs_lead() or dbcs_expected(). +; Entry +; none +; Exit +; none (side effect: DBCS table initialised) + + push bp + mov bp, sp + sub sp, DI_LOCALS ; allocate local variables + push ds + push es + push di + push si + + mov dbcs_table_seg, ds ; assume DBCS call will fail + + mov ax, 06507h ; Extended Country Info: get DBCS ptr + mov bx, 0FFFFh ; codepage number: -1 for global cp + mov cx, 00005h ; size of info. buffer + mov dx, 0FFFFh ; country code: -1 for current country + lea di, DI_BUF[bp] + push ss + pop es ; es:di -> DI_BUF + int 21h ; returns with DI_BUF filled in + jc di_exit ; just exit if function fails + + cmp DI_BUF_ID[bp], 7 ; is table for DBCS? + jne di_exit ; no - exit + les ax, DI_BUF_PTR[bp] ; es:ax -> system DBCS table + + mov dbcs_table_off,ax + mov dbcs_table_seg,es ; fixup pointer to system DBCS table + +di_exit: + pop si + pop di + pop es + pop ds + mov sp, bp + pop bp + ret +dbcs_init endp + +endif + +; I want to do +; db (C_HEAP_SIZE - 6 - ($ - stack_start)) dup (0DDh) +; but MASM requires dup's be absolute, so instead +rept C_HEAP_SIZE +if (offset $ - offset stack_start) LT (C_HEAP_SIZE - 6) + db 0ddh +endif + +endm + +stack_top label word +stack_ip dw ? ; Initial Offset +stack_cs dw ? ; Initial Code Segment (Unknown) +stack_flags dw ? ; Initial Flags (Unknown) +STACK ENDS + +ED_TEXT SEGMENT +; +; Return the CheckSum of All the C code and Static Data. DS:SI +; are initialised to point at the C_code_start. AX contains the +; CheckSum on return. +; +calc_crc: + mov cx,real_code ; Number of bytes to move is always + shr cx,1 ; even because of the segment def. + dec cx + mov bx,0EDCh ; Checksum Seed +cc_10: ; Sum the words of the image while + lodsw ; rotating the check value + add bx,ax + rol bx,1 + loop cc_10 + xchg ax,bx + ret + +page +; +; Return the code segment of the C main routine. +; +get_cs: + mov ax,cs:code_seg + ret + +; +; Return the Data segment of the C data area +; +get_ds: + mov ax,cs:data_seg + ret + + +; Get remaining memory size, subtract code size and allocate high memory for +; transient portion of command processor +; Exit AX=Segment of high memory +; CY set if none available +; +; This used to allocate only just enough space for the code at the top of +; memory and leave the reset free for use as copy buffers. +; But then came SideKick Plus - this assumes COMMAND.COM only uses the top +; 20K of it's hi-mem partion and overwrites the rest as it gets it's +; overlays. As we are bigger the 20K the result is the system crashes when +; you exit back to the command line. +; In order to minimise this possibility we reserve some space (currently 50K) +; for use as copy buffers and allocate all the rest to the hi-mem portion +; of COMMAND.COM. Since SK starts overwriting from the bottom of memory it +; doesn't usually reach the code. +; The real solution is of course to make sure we are smaller than 20K too... +; (Or transfer the ReadLine code into the resident portion and checksum the +; hi-mem before returning to the hi-mem code ???). +; --ij + +public alloc_com_memory +alloc_com_memory: + push es + mov bx,0FFFFh ; Allocate more paras than there are + mov ah,MS_M_ALLOC ; to find out how many there are. + int DOS_INT + mov ah,MS_M_ALLOC + int DOS_INT ; allocate it + + mov si,code_length ; then convert the CODE_LENGTH to + mov cl,4 ; paragraphs and check if enough memory + shr si,cl ; is available to copy the code high + add si,1 ; + para for a memory descriptor + sub bx,si ; Is there enough for the code ? + jc acm_10 ; if not exit with error + + + cmp bx,Copy_Buffer_Size ; allocate some memory for Copy Buffers + jb acm_5 + mov bx,Copy_Buffer_Size ; limit the maximum Copy Buffer size +acm_5: + mov es,ax + mov ah,MS_M_SETBLOCK + int DOS_INT ; shrink to fit + push es ; save buffer address + +; Now allocate remaining memory for step aside code + mov bx,0FFFFh ; allocate all memory + mov ah,MS_M_ALLOC ; to find out how much there is. + int DOS_INT + mov ah,MS_M_ALLOC ; block at the end of memory + int DOS_INT ; AX=Segment of new block of memory + mov alloc_seg,ax ; save address so we can free it +if ThreeCOM + cmp bx,1000h ; do we have at least 64k ? + jb acm_6 ; if so do 3-Com fix and start + mov si,1000h ; Transient portion 64k down +acm_6: +endif + add ax,bx ; go to top of memory we allocated + + cmp ax,0a000h ; dont use memory above A000 as this + jb acm_6a ; may disappear when user does + mov ax,0a000h ; MEMMAX -V +acm_6a: + + dec si + sub ax,si ; adjust address we run cmd proc at +; Deallocate intervening block of memory + pop es + push ax + mov ah,MS_M_FREE ; Now free it up + int DOS_INT + pop ax + mov cs:_gp_far_buff,real_code + mov cs:_gp_far_buff+2,ax ; save address of temp buffer + clc ; allocated OK +acm_10: + pop es + ret + +; called to free up the cmd processor's high memory +free_com_memory: + + push es + push ax + mov es,alloc_seg + mov ah,MS_M_FREE + int DOS_INT + pop ax + pop es + ret + + +;Control_Break: +; The Break handler makes the following checks taking the +; appropriate action after each test:- +; +; 1) Is COMMAND.COM the current process (Get PSP) if NO ABORT +; 2) Is the break_flag SET if YES jump to the C break handler +; "break_handler" after insuring that the segment registers +; have all be set correctly. +; + assume cs:DGROUP, ds:nothing, es:nothing + +; Set up the default Control Break Handler. +handler_init: +ifndef DOSPLUS + mov ax,4453h ; Get the address of the + int DOS_INT ; internal Critical Error + jc handler_i10 ; handler Ignore on Error + mov word ptr critical+0,ax ; Save the handler Offset (AX) + mov word ptr critical+2,bx ; and Segment (BX) +endif + mov al,24h ; Set the default Critical + mov dx,dataOFFSET critical_error ; Error Handler + mov bx,dataOFFSET crit_error_entry + call set_vector ; Setup correct ISR + +handler_i10: + mov al,23h ; Set the default Control + mov dx,dataOFFSET control_break ; Break Handler + mov bx,dataOFFSET control_break_entry +;; jmp set_vector ; Setup correct ISR +; +; Convert the address of the interrupt #AL service routine, whose +; address is CS:DX to be PSP:xxxx. Five NOP must be coded after the +; interrupt service routine for the JMPF instruction which corrects +; the code segment. +; +set_vector: + push ds + push es + mov es,[low_seg] + mov es:byte ptr 0[bx],0EAh ; JMPF opcode + mov es:word ptr 1[bx],dx ; Offset of Interrupt vector + mov es:word ptr 3[bx],cs ; Insert the correct code seg + mov dx,bx + mov bx,es + sub bx,__psp ; Calculate the correct offset for + mov cl,4 ; the interrupt handler if the segment + shl bx,cl ; must be that of our PSP + add dx,bx + mov ds,__psp + mov ah,MS_S_SETINT + int DOS_INT + pop es + pop ds + ret + + ;extrn _int_break:near ; C Break/Error handling routine + + assume cs:DGROUP, ds:DGROUP, es:nothing + +control_break PROC FAR + ;;db 5 dup(90h) ; Reserve space for JMPF CS:$+5 + push ax ; Save the Users registers + push bx + push ds + call get_ds ; Get our Local DS + mov ds,ax + cmp _cbreak_ok,0 ; is our handler initialised ? + je break_05 ; no, don't call it + cmp reload_flag,0 ; Are we part way through reloading + clc ; the command processor? + jnz break_05 ; if so do not abort. + + mov ah, MS_P_GETPSP ; Get the current PSP address + int DOS_INT + cmp bx,[__psp] ; Is this our address + stc ; Assume not and Set the carry flag + jz break_10 ; if internal, restart the command loop + ; if external, abort process +break_05: + pop ds + pop bx + pop ax + ret + +; +; This section of code corrects the stack and jumps to the +; C code Control Break Handler _int_break. Beware that the +; stack segment need not be the DS because the READ_LINE routine +; executes on a high stack and the CED programs will emulates +; a Control-Break on the wrong Stack. +; +break_10: + cli ; Swap to the correct stack not + mov ax,ds ; forgetting that we might be running + mov es,ax ; on old 8088 or 8086 so interrupts + mov ss,ax ; must be disabled + mov sp,stack_min ; Get the lowest possible stack address + add sp,12 ; Add a little to avoid problems with + sti ; the stack check code. + + mov ax,0100h ; Termination Code Control-C Abort + push ax ; Save on the Stack for C routine + push ax ; Force a dummy return address on the + ; stack (NOT USED) + call get_cs ; Put the Segment and Offset address + push ax ; of the C break Handler on the stack + mov ax,codeOFFSET _int_break; and execute a RETF to it. + push ax + ret +control_break ENDP + +critical_error PROC FAR + ;;db 5 dup(90h) ; Reserve space for JMPF CS:$+5 + push ds ; Save the Critical Error DS + push ax + call get_ds ; Get the Command Processor DS + mov ds,ax ; and call the original routine +ifdef DOSPLUS + mov ax, _n_option ; check for /n command line option + cmp ax, 0 + pop ax + jne skip_criterr + call com_criterr ; local criterr handler + jmp criterr_cont +skip_criterr: + mov al,3 ; /n option => always return fail +criterr_cont: +else + pop ax + pushf + call critical ; stored previous handler +endif + cmp al,02h ; Did the user request a Terminate + jne critical_e20 ; Yes so check if they are trying to + push ax ; terminate the command processor + push bx + + mov ah, MS_P_GETPSP ; Get the current PSP address + int DOS_INT + cmp bx,[__psp] ; Is this our address? + jne critical_e10 ; no so return with Abort code + + cmp in_exec,0 ; are we EXECing a program ? + jne critical_e10 ; then return the error + cmp reload_flag,0 ; then unless we are reloading command + je break_10 ; processor break here to prevent +critical_e10: ; higher levels generating repeated + pop bx ; critical errors (eg. when searching + pop ax ; a path) +critical_e20: + pop ds + iret + +critical_error ENDP + +; +; INT2E is a backdoor entry to the "Permanent" Command interpreter +; which will execute the command at DS:SI. +; + +int2E_far_entry proc far + db 5 dup(90h) ; Reserve space for JMPF CS:$+5 + +; ds:si -> command line preceded by byte count + +; check we're not re-entering + + mov ax, 1 + xchg cs:i2e_lock, ax + test ax, ax + jz i2e_10 + + iret + +i2e_10: + push bx + push cx + push dx + push si + push di + push bp + push ds + push es + + ; if ds = si = 0 then set batch_seg_ptr to zero and get out. + ; This is a clean way of halting batch processing. + mov ax,ds + cmp ax,0 + jne i2e_15 + cmp si,0 + jne i2e_15 + + mov si,cs:_batch_seg_ptr + mov ds,cs:_batch_seg_ptr+2 + mov [si],ax + jmp i2e_exit2 +i2e_15: + +; swap stack + + mov cs:i2e_user_ss, ss + mov cs:i2e_user_sp, sp + + cli + mov ss, cs:exec_ss + mov sp, cs:exec_sp + sti + +; allocate 128 bytes for command line, since the C code needs a 128 +; byte buffer anyway + + mov cx, 128 + +; save stack p + + mov cs:i2e_stack, sp + +; have we got enough room for command line + + mov ax, sp + sub ax, cx + sub ax, cs:heap_top + cmp ax, 256 + jge i2e_25 + jmp i2e_exit +i2e_25: + sub sp, cx + mov cs:i2e_cmd, sp + +; copy command line + + push ss + pop es + mov di, sp + lodsb ; get line count + and ax,7fh ; limit to 128 bytes + add ax,sp ; terminating NULL goes here + rep movsb ; copy the command line + xchg ax,di ; DI -> NUL posn + xor al,al + stosb ; replace CR with NUL + push cs + pop ds + +; reload non-resident code if necessary + + cmp high_code, TRUE + jnz i2e_30 + mov reload_flag, 1 + call reload_code + mov reload_flag, 0 + +i2e_30: +; install our own Break and Criterr handlers - e.g. if second copy +; of the command processor is running, install original handlers so +; that they are looking at the same data as we are. +; N.B. __psp is currently that of original command processor + + mov ax, (MS_S_GETINT*256) + 23h + int DOS_INT + mov i2e_i23seg, es + mov i2e_i23off, bx + + mov ax, (MS_S_GETINT*256) + 24h + int DOS_INT + mov i2e_i24seg, es + mov i2e_i24off, bx + + call handler_init + +; save the command processor's __psp variable, and then set it to the +; psp of the process that called us. This is so that the Break and +; Criterr abort code can correctly determine whether the int2e command +; was internal or external + + mov ah, MS_P_GETPSP + int DOS_INT + push bx ; save calling process's psp - EJH + mov bx, [__psp] + +; Set current PSP to our own - EJH + mov ah, MS_P_SETPSP + int DOS_INT + +; call C code + + mov ax, code_seg + mov i2e_c_seg, ax + + push i2e_cmd + call i2e_c_entry + pop ax ; clean up stack + +; Set current psp back to that of calling process - EJH + pop bx + mov ah, MS_P_SETPSP + int DOS_INT + + +; restore interrupt vecs + + push ds + lds dx, i2e_i23vec + mov ax, (MS_S_SETINT*256) + 23h + int DOS_INT + + lds dx, cs:i2e_i24vec + mov ax, (MS_S_SETINT*256) + 24h + int DOS_INT + pop ds + + cmp high_code, TRUE ; If not a .EXE then free + jnz i2e_ret ; any memory alocated by + call free_com_memory ; the Command Processor +i2e_ret: + +i2e_exit: +; swap back the stack + + cli + mov ss, i2e_user_ss + mov sp, i2e_user_sp + sti + +i2e_exit2: + pop es + pop ds + pop bp + pop di + pop si + pop dx + pop cx + pop bx + + sub ax, ax + + mov cs:i2e_lock, 0 + ret 2 + +int2E_far_entry endp + + +_TEXT SEGMENT + assume cs:CGROUP, ds:DGROUP, es:nothing, ss:nothing + public _exec ; EXEC routine + +; +; WORD CDECL exec(BYTE *path, UWORD type, BYTE *line, BOOLEAN back); +; +; back 10[bp] +; line 08[bp] +; type 06[bp] +; path 04[bp] +; +_exec: +;----- + push bp + mov bp,sp + push si + push di + push ds + push es + inc in_exec + cmp in_exec,1 + je _exec10 ; Menuing system + push exec_ss ; save old stack_save if we + push exec_sp ; are being re-entered +_exec10: + mov si,08[bp] ; the Command Line + mov exec_env,0000 + mov exec_clineoff,si + mov exec_clineseg,ds + mov exec_fcb1seg,ds + mov exec_fcb2seg,ds + + push ds + pop es +; +; Extract two valid filenames from the CR terminated +; string passed in DS:SI. The FCBs will be generated in FCB1 and FCB2. +; + inc si + mov di,dataOFFSET fcb1 ; Blank fill the first FCB + call zap_fcb + call make_fcb ; Build first FCB + + mov di,dataOFFSET fcb2 ; Blank fill the Second FCB + call zap_fcb + call make_fcb ; Build second FCB + + mov ax,cs + jmp exec ; do FAR jmp to msdos_exec as we can't +_exec_ret: ; trust the stack when CALLing + dec in_exec ; Has PCTOOLS un-installed itself ? + jz _exec20 ; No so the stack contents are valid + js _exec_bad ; Yes, so exit by Ctrl-Break + pop exec_sp ; old stack save back again + pop exec_ss ; in the case of re-entry +_exec20: + + pop es + pop ds + pop di + pop si + pop bp + mov ax,return_code + neg ax + ret +; +; We have returned from the EXEC function un-expectedly (because +; of PCTOOLS De-installation ?). Therefore the contents of the stack +; are invalid and we generate a Control-Break. +; +_exec_bad: + mov ax,0100h ; Termination Code Control-C Abort + push ax ; Save on the Stack for C routine + push ax ; Force a dummy return address on stack + mov in_exec,al ; zero in_exec count for next time + + extrn _int_break:near ; C Break/Error handling routine + jmp _int_break ; now treat as ctrl-break + +; +; Initialise the FCB entry a DX:DI and copy the Drive, FileName +; and extension form DS:SI when SI != 0FFFFh +; +zap_fcb: + mov ax,2000h ; Zero Fill first byte and last 4 + stosb ; Drive code 0 + xchg al,ah + mov cx,11 ; FileName and Ext to ' ' + rep stosb + xchg al,ah + mov cl,4 ; Last four bytes to 00 + rep stosb + sub di,16 + ret + +make_fcb: + call scan_filechar ; Get the Next File Character + push si + push di + push ax ; Save Character and Pointers + + mov ax,(MS_F_PARSE shl 8) + 1 ; Parse the command line + int DOS_INT + + pop ax + pop di ; Restore the Character and Pointer + + cmp ah,'/' ; Was the arg preceeded by a '/' + jne make_fcb10 ; If it was roll back the cmd line + pop si ; pointer and blank all but the 1st + inc si ; char in the FCB + + add di,2 ; Such that /FRED gives an FCB of 'F' + mov cx,10 ; and si points to the 'R' + mov al,' ' + rep stosb + ret + +make_fcb10: + pop ax ; discard original SI, skip name + jmp scan_sepchar ; skip until separator + +; +; SCAN_SEPCHAR will search through the command line DS:SI +; which contains CX characters and return with SI pointing +; to the next SEPARATOR character. +; +; On Entry: DS:SI Character String +; +; On Exit: DS:SI First Non Separator +; +scan_sepchar: + push di ; Save DI ES points at this segment + mov ah,0 ; Invalidate Separator Character + +scan_s10: + mov al,[si] ; Get the Character to Test + cmp al,CR + jz scan_s20 ; Have we reached the end of the string + mov cx,legal_length ; Scan the table of legal + mov di,dataOFFSET legal_table ; separators + repnz scasb ; Scan the List + jz scan_s20 ; Separator Located + inc si ; the character pointer + jmp SHORT scan_s10 + +scan_s20: + pop di + ret +; +; SCAN_FILECHAR will search through the command line DS:SI +; and return with SI pointing to the next NON_SEPARATOR character. +; +; On Entry: DS:SI Character String +; +; On Exit: DS:SI First Non Separator +; AH Last Valid Separator +; +scan_filechar: + push di ; Save DI ES points at this segment + mov ah,0 ; Invalidate Separator Character +scan_f10: + mov al,[si] ; Get the Character to Test + cmp al,CR + jz scan_f20 ; Have we reached the end of the string + mov cx,legal_length ; Scan the table of legal + mov di,dataOFFSET legal_table ; separators + repnz scasb ; Scan the List + jnz scan_f20 ; Non Separator Located + mov ah,al ; Save the Separator and increment + inc si ; the character pointer + jmp SHORT scan_f10 + +scan_f20: + pop di + ret + +_TEXT ENDS + +legal_table db ':.;,=+',9,' /<>|',22h,'[]' +legal_length equ 15 + + assume cs:DGROUP, ds:DGROUP, es:nothing, ss:nothing + + public msdos_exec ; so it shows in map file + +msdos_exec PROC FAR + push ax + cmp high_code,TRUE ; Check if the Command Processor Code + jnz msdos_e10 ; has been relocated to high memory + + call free_com_memory ; free cmd processor memory + +msdos_e10: + pop ax + mov bx,dataOFFSET exec_block + mov dx,04[bp] ; Get the Full Command Name + mov exec_ss,ss ; Save SS:SP in case somebody (NOVELL) + mov exec_sp,sp ; corrupts them + +; The following 2 JMPF are kludged so that the INT22 vector saved in +; the child's PSP has the segment of the comand processors PSP. +; This is vital for many TSR management utilities. +; + + ; swap stack to conventional memory + cli ; + mov ax,__psp ; + mov ss,ax ; + mov sp,0100h ; + sti ; + + db 0EAh ; JMPF Opcode + dw dataOFFSET psp_dofunc4b ; Corrected Offset +exec_psp dw 0 ; PSP Segment + + assume cs:DGROUP, ds:nothing, es:nothing, ss:nothing +func4b_return: + mov ss,exec_ss ; Restore the real SS:SP + mov sp,exec_sp ; Using a CS overide + jc msdos_e20 ; if no error + xor ax,ax ; then zero return code + jmp msdos_e21 +msdos_e20: + mov ah,59h ; get extended error code + sub bx,bx + int 21h +msdos_e21: + mov return_code,ax + call get_ds ; Point DS & ES to CSdata + mov ds,ax + mov es,ax + assume cs:DGROUP, ds:DGROUP, es:nothing, ss:nothing + + call handler_init ; Re-initialise Control-Break and + ; Critical error handlers for Novell + cmp high_code,TRUE ; Is the Command Code in High + jnz msdos_e30 ; memory ? + mov reload_flag,1 ; Reloading Command Processor + call reload_code ; Reload Command Processor Code + mov reload_flag,0 ; Command Processor Loaded +msdos_e30: + mov ax,code_seg ; Update the CS for the high code + mov msdos_exec_ret_seg,ax ; in case it has moved and return + jmp msdos_exec_ret + +msdos_exec ENDP + +_TEXT SEGMENT + assume cs:CGROUP, ds:DGROUP, es:nothing, ss:nothing + + Public _readline + +_readline: +;--------- + cld + push bp + mov bp,sp + push si + push di + push es +ifdef DOSPLUS + mov ax,4456h ; Swap to the Command process + mov dl,1 ; History Buffer in DR DOS + int DOS_INT +else + push ds + call get_history_buffers ; get history buffers + mov P_SB_SEG[bx],ax ; swap to command one + pop ds +endif + mov ax,5d09h + int DOS_INT ; close remote spool files + mov ax,5d08h + mov dl,1 + int DOS_INT ; Set truncate flag with redirected I/O + + mov ah,MS_P_GETPSP ; get the current PSP + int DOS_INT ; then compare the STDERR entry in the + mov es,bx ; XFT with the Magic Number for CON + cmp es:byte ptr [18h+STDERR],1 + mov dx,4[bp] ; get the buffer address and current + mov ax,cs ; AX = transient code segment + call readline ; do far call to msdos_readline +ifdef DOSPLUS + mov ax,4456h ; Swap to the Application process + mov dl,0 ; History Buffer in DR DOS + int DOS_INT +else + push ds + call get_history_buffers ; get history buffers + mov P_SB_SEG[bx],dx ; swap to application one + pop ds +endif + pop es + pop di + pop si + pop bp + ret + +ifdef CDOS +get_history_buffers proc near +; On Entry: +; None +; On Exit: +; AX = command history buffers +; DX = application history buffers +; DS:BX -> pd +; NB. both DS and ES are corrupted by this call +; + mov ds,_sysdat_seg ; DS points to SYSDAT and ES to the + mov bx,ds:word ptr [68h] ; current process's UDA + mov dl,P_CNS[bx] ; DL = console number + mov es,P_UDA[bx] + push bx + mov ax,XIOS_HISTBUF ; Get the History Buffer Address's + call XIOS_ENTRY ; by calling ths XIOS + pop bx + ret +get_history_buffers endp +endif + +_TEXT ENDS + + assume cs:DGROUP, ds:DGROUP, es:nothing + +; +; msdos_readline(BYTE *buffer); +; +; On Entry: +; flags - ZF set if we need to do Sidekick Plus check +; DS:DX -> buffer +; AX:0 -> Resident Section +; buffer +; +; The memory allocation for the hi-mem part of command.com has already been +; altered to minimise the chances of SideKick Plus overwriting the code. +; But it still can happen, say either on a machine with limited memory or +; other TSR's also loaded. In order to cater for this case we move the actual +; readline call into the resident portion and checksum things before returning +; to high memory - thus we can reload command.com if it get overwritten. +; +msdos_readline PROC FAR + pushf ; save the result for later + + mov bx,sp ; SP before swapping stacks. + cli ; to RLSTACK + mov ss,ax ; above the Code and Messages + mov sp,codeOFFSET rlstack + sti + + push bx ; save old SP + push ds + + sub sp,260 ; make room for buffer on stack + mov di,sp ; save the address + + push ds + push dx ; save real BUFFER for later... + push di ; and buffer on stack + + mov si,dx ; point DS:SI at real buffer + mov dx,di ; point DX at stack buffer + push ss ; now get all the seg regs + pop es ; pointing to himem + mov cx,256/2 + rep movsw ; copy resident buffer to stack + push ss ; DS:DX is stack buffer + pop ds + + mov ax,4810h ; give DOSKEY a chance + int 2Fh + or ax,ax ; zero means DOSKEY has done it + jz msdos_rl10 + + mov word ptr [di],21cdh ; poke INT 21 and + mov byte ptr 2[di],0cbh ; RETF instruction + push cs ; save an address for the + mov ax,dataOFFSET msdos_rl10; RETF to return to + push ax + + mov ah, MS_C_READSTR ; parameter for INT 21 readline + + push ds ; finally jump to the INT 21 + push di ; we have poked + ret + +msdos_rl10: + pop si ; source is readline buffer + pop di ; recover old address + pop es ; and seg of real buffer + + mov cl,ds:byte ptr [si] ; get MAX length + xor ch,ch ; make it a word + cld + rep movsb ; copy the string + + add sp,260 ; recover my readline buffer space + pop ds + pop bx ; recover old SP + + cli ; Now restore the normal C stack + call get_ds ; which is at DS:BX. + mov ss,ax + mov sp,bx + mov es,ax + sti + + popf ; recover result of STDERR test + jne msdos_r10 ; if not CON, then skip the check + cmp high_code,TRUE ; Is the Command Code in High + jnz msdos_r10 ; memory ? + mov reload_flag,1 ; Reloading Command Processor + call reload_code ; Reload Command Processor Code + mov reload_flag,0 ; Command Processor Loaded +msdos_r10: + mov ax,code_seg ; Update the CS for the high code + mov word ptr -08[bp],ax ; in case it has moved and return + ret +msdos_readline ENDP + +; Cmd processor is in high memory so check it out +reload_code: + cmp in_exec,1 ; If we landed here from an undefined area + je alloc_mem ; then free cmd processor memory + call free_com_memory + +alloc_mem: + call alloc_com_memory ; Allocate memory for the Command + jc alloc_mem_error ; processor code. + push ax + call check_crc ; see if code has been trashed + pop ax + je still_there + mov code_seg,ax + jmp load_com ; Read in command Processor Code + +still_there: + cmp ax,code_seg ; has the memory configuration changed? + je hasnt_moved ; (it will during Novell remote boot) + + push ds + push es + + mov cx,real_code + mov es,ax ; move the code to the new location + mov ds,code_seg ; + sub si,si ; ds:si -> old location + sub di,di ; es:di -> new location + + rep movsb ; do it + + mov cs:code_seg,es ; update code_seg with new location + + pop es + pop ds + + call check_crc ; recalculate the crc + jne load_com ; if its not valid we need to load + ; from disk + +hasnt_moved: + ret + +alloc_mem_error: +; We can't reload COMMAND.COM because we haven't any memory +ifdef DLS + mov dx,_reload_msgm +else + mov dx,dataOFFSET _reload_msgm +endif + call reload_err ; say we can't reload COMMAND.COM + jmp $ ; stop forever.... + +check_crc: +; return with ZF set if himem crc's correctly + push ds + mov ds,code_seg + mov si,2 + call calc_crc + pop ds ; Compare this crc with the one we got earlier + cmp crc,ax + ret + +; If checksum is wrong load a new copy into high memory and patch new RET addr + +open_err: +ifdef DLS + mov dx,_reload_msgf +else + mov dx,dataOFFSET _reload_msgf +endif + call reload_err ; prompt for COMMAND.COM + mov ah,MS_C_RAWIN ; Wait for the User to Press + int DOS_INT ; a key + +load_com: + push ds + mov ds,[low_seg] + mov dx,dataOFFSET reload_file + mov ax,(MS_X_OPEN*256)+40h ; Try to open COMMAND.COM + int DOS_INT ; al=40h means NONE DENIED share mode + pop ds + jc open_err + mov bx,ax + + xor dx,dx ; Take account of EXE header + cmp exe_file,FALSE ; if we were loaded as an EXE + je load_com_10 + add dx,200h ; Assume header is 200h bytes + +load_com_10: + xor cx,cx ; Now read the command processor code + add dx,total_length ; Seek to area of COMMAND.COM + mov ax,(MS_X_LSEEK*256)+0 ; containing code + int DOS_INT + jc read_err + + push ds + mov cx,real_code + mov ds,code_seg ; DS:DX - > High memory area + xor dx,dx + mov ah,MS_X_READ ; Read the code into memory + int DOS_INT + + pop ds +read_err: + mov ah,MS_X_CLOSE ; Close the file + int DOS_INT + + call check_crc ; try and see if we loaded OK + jne open_err ; if not complain and try again + + ret + +reload_err: +; On Entry: +; DX = offset of final part of error message +; + push dx ; save final part of message + mov bx,STDERR ; Display on standard Error +ifdef DLS + mov dx,_reload_msgs +else + mov dx,dataOFFSET _reload_msgs +endif + call reload_err10 + + push ds + mov ds,[low_seg] + mov dx,dataOFFSET reload_file ; Filename + call reload_err10 + pop ds + + pop dx ; recover msg offset +; +; Calculate the length of the message to be displayed and output using +; MS_X_WRITE. +; +; DS:DX String to Output +; BX Output Handle +; +reload_err10: + xor al,al ; String Terminator + push es + push ds ; look for terminating BYTE + pop es ; in string at DS:DX + mov di,dx ; and get length to display + mov cx,0ffffh + repnz scasb ; look for terminator + not cx ; see how far we had to look + dec cx ; forget about the terminator + mov ah,MS_X_WRITE + int DOS_INT + pop es + ret + +ED_TEXT ENDS +endif + + page +_TEXT SEGMENT + assume cs:CGROUP, ds:DGROUP, ss:DGROUP +ifdef CDOSTMP +RSP_start: + mov ax,ds + mov es,ax + cli ; Swap stacks with interrupts disabled + mov ss,ax ; just in case we're on an 8088/86 + mov sp,dataOFFSET stack_top + sti + mov insys,0 ; Reset the INSYS Flag + + mov _gp_far_buff,dataOFFSET temp_buffer + mov _gp_far_buff+2,ax ; save address of temp buffer + + mov dl,defconsole ; Set this process's Default Console + bdos C_SET + bdos C_ATTACH + + bdos P_PDADR ; Get the address of the current + mov sysdat,es ; PD and SYSDAT + + mov dl,BOOTDRV ; Get the BOOT Drive + mov es:P_DSK[bx],dl ; Update the running process + mov bx,dataOFFSET pd_seg ; Update the default drive field + mov P_DSK[bx],dl ; In the P_CREATE process descriptor + + mov bx,es:INT17_PTR ; Initialise the default printer + mov al,defconsole ; from the INT17 Mapping Array + mul es:byte ptr [bx] + add bx,ax + mov dl,es:1[bx] + bdos L_SET + + mov bx,es:INT14_PTR ; Initialise the default printer + mov al,defconsole ; from the INT14 Mapping Array + mul es:byte ptr [bx] + add bx,ax + mov dl,es:1[bx] + bdos A_SET + + mov [code_seg],cs ; Update the CODE_SEG and EXEC_SEG + mov [exec_seg],ds ; variables + + mov dl,0FFh ; Set the BDOS Error Mode to Return + bdos F_ERRMODE ; with No Display + + mov dx,ds ; Initialise the DMA Segment + bdos F_DMASEG ; Pointer to Our DS + + bdos P_PDADR ; Set ES:BX to the Process Descriptor + mov word ptr _pd,bx ; Save these values locally + mov word ptr _pd+2,es + mov _sysdat_seg,es + + or es:P_CONMODE[bx],PCM_FCTLC + mov es:P_PARENT[bx],0 ; Zero the Parent Pointer + mov ax,es:P_UDA[bx] ; Finally get our UDA and save it. + mov uda,ax + + + mov ax,es:P_PSP[bx] + mov [__psp],ax + + mov ax,XIOS_HISTBUF ; Get the History Buffer Address's + mov dl,defconsole ; for console number + call xios + mov cmd_histbuf,ax ; AX == Command Level History Buffer + mov prog_histbuf,dx ; DX == Program History Buffer + + les bx,_pd ; Get the Process descriptor address + mov es:P_SB_SEG[bx],ax ; and use the Command Line + ; History Buffer + +; File Ownership stuff + les bx,_pd ; Get our process descriptor address + mov al,es:P_CNS[bx] ; get the current VC No. + xor ah,ah + mov bx,CCBLIST ; XIOS CCB$LIST + add bx,ax + add bx,ax + mov bx,es:word ptr [bx] ; extract the correct + mov ah,CCB_PCNS[bx] ; Physical Console Number. + + mov ch,0 + mov cl,NVCNS ; now work through all consoles + mov bx,CCBLIST ; looking for 1st one with this PC +RSP_start10: + mov di,es:word ptr [bx] ; Get the CCB address + cmp ah,CCB_PCNS[di] ; Is this the same physical console + je RSP_start20 ; no, ignore this one + add bx,2 ; onto next CCB + loop RSP_start10 + jmp RSP_start60 ; impossible.... + +RSP_start20: + cmp al,CCB_VCNS[di] ; is it the same virtual console ? + je RSP_start40 ; yes, allocate new FA_ structure +RSP_start30: + push di + mov dx,5 + bdos P_DELAY ; wait a bit + pop di ; then see if it has been allocated + mov si,CCB_OWNER[di] ; si -> owning process + mov si,es:P_FILE_ACCESS[si] ; File Access structure + test es:FA_FLAGS[si],FAF_TMP_INIT ; is it the new one ? + jz RSP_start30 ; no, delay again + inc es:FA_COUNT[si] ; one more user for this structure + les bx,_pd + xchg si,es:P_FILE_ACCESS[bx] ; replace existing one + dec es:FA_COUNT[si] ; one less user for old one + jmp RSP_start60 + +RSP_start40: + push ax ; save PC/VC + cmp ah,0 ; is it the main box ? + je RSP_start45 + mov dx,5*50 ; delay PC Terminals 5 secs while + bdos P_DELAY ; main box starts up +RSP_start45: + mov DX,FA_LENGTH ; we need this much SYSDAT memory + bdos S_MEMORY ; for our file access structure + pop dx ; recover PC/VC + cmp ax,0FFFFh ; if no memory + je RSP_start50 ; then just keep root one + les di,_pd ; replace file access structure + xchg ax,es:P_FILE_ACCESS[di] + xchg ax,di + dec es:FA_COUNT[di] ; we have stopped using this structure + mov es:FA_USER[bx],0 ; user # is super user + mov es:FA_GROUP[bx],0 ; and group is super group + mov es:FA_DEF_ACCESS[bx],0 ; initialise the new structure + mov es:FA_COUNT[bx],1 +RSP_start50: + les bx,_pd + mov bx,es:P_FILE_ACCESS[bx] + mov es:FA_FLAGS[bx],FAF_TMP_INIT +RSP_start60: +; File Ownership stuff ends + + push ds + mov es,sysdat ; Get SYSDAT + mov dx,VERSION ; get OS label offset in SUP segment + mov ds,CCPMSEG ; get SUP segment for signon string + bdos C_WRITESTR ; print OS label on current console + pop ds +endif +; +; + assume cs:CGROUP, ds:DGROUP, es:DGROUP +; +; zero data areas (_BSS and c_common) +; +memory_init: + push ss + pop es + + cld ; set direction flag (up) + mov di,dataOFFSET _edata ; beginning of bss area + mov cx,dataOFFSET _end ; end of bss area + sub cx,di + xor ax,ax + rep stosb ; zero bss + +; C segmentation conventions set up here (DS=SS and CLD) + + push ss ; set up initial DS=ES=SS, CLD + pop ds + assume ds:DGROUP + +; do necessary initialization BEFORE command line processing ! + +ifndef CDOSTMP + push es + mov ax,4458h ; We now have an IOCTL function + int 21h ; to get our private data + jc mem_init10 +ifdef DOSPLUS + ;les ax,DRDOS_PD + ;les ax,es:dword ptr 0000h[bx] + ;mov word ptr _pd,ax + ;mov word ptr _pd+2,es + ;mov _sysdat_seg,es +else + mov es:byte ptr [bx],-1 ; say COMSPEC is loaded + mov cl,P_PDADR ; Set ES:BX to the Process Descriptor + mov ax,4459h ; use Int 21h so we don't crash if + int 21h ; under DOS and we will give an error + mov word ptr _pd,bx ; from COM.C init(). + mov word ptr _pd+2,es ; Save these values locally + mov _sysdat_seg,es +endif +mem_init10: + pop es +endif + xor bp,bp ; mark top stack frame for SYMDEB + +ifdef CDOSTMP + mov ax,dataOFFSET cmdline ; Pass a pointer to a NULL string +else + call get_cmdline ; Copy the command line to a local +endif + push ax ; buffer and pass the address to MAIN + call C_code_entry ; main ( cmd ) + add sp,2 ; Restore the Stack + mov ah,MS_X_EXIT ; use whatever is in ax after + int DOS_INT ; returning here from main + +page +; +; For TURBOC and METAWARE C the majority of the Command Processor +; messages are linked with the CGROUP in the MSG segment. When the +; compiler generates DGROUP relative references large offsets are +; produced. This occurs because the DGROUP is linked before the CGROUP +; and its MSG Segment. FARPTR converts a NEAR pointer into a FAR +; by checking the value of the offset against the DGROUP length. +; Offset greater than TOTAL_LENGTH must be in MSG so the pointer +; is converted to CS:x-TOTAL_LENGTH otherwise DS:x. +; + public _farptr +_farptr: + push bp + mov bp,sp + mov ax,04[bp] + mov dx,ds + cmp ax,total_length + jbe farptr_10 +ifndef WATCOMC + sub ax,total_length +endif + mov dx,cs +farptr_10: + mov bx,dx + pop bp + ret + +ifdef DLS + public _msgfarptr +_msgfarptr: + push bp + mov bp,sp + mov ax,04[bp] + add ax,offset CGROUP:_MSG + mov dx,cs + mov bx,dx + pop bp + ret +endif + +; We need some additional support for the CMD_LIST - it contains near pointers +; to other items in the CGROUP. This routine turns a NEAR pointer into a FAR +; pointer. + public _cgroupptr +_cgroupptr: + push bp + mov bp,sp + mov ax,04[bp] + mov dx,cs + mov bx,dx + pop bp + ret + +ifdef DLS + +;/* Get the address of the msg_language variable in the DR BDOS. */ +;GLOBAL BYTE FAR * CDECL get_msg_lang() + + public _get_msg_lang +_get_msg_lang: + mov ax, 4458h ; IOCTL func: get ptr private data + int 21h ; pointer returned in ES:BX + jc _get_msg_lang_err ; skip if invalid function + add bx, 9 ; DLS version byte at offset 9 + cmp es:byte ptr [bx], 1 ; correct version? + jne _get_msg_lang_err ; no - skip + inc bx ; DLS language byte at offset 10 + mov ax,bx + mov dx,es ; return pointer in DX:AX + ret + +_get_msg_lang_err: + mov ax,codeOFFSET dummy_lang + mov dx,cs + ret + +dummy_lang db 0 ; default to primary language + +endif + +page +ifndef CDOSTMP + +; +; This following routine copies the initial command line from the PSP +; into the CMDLINE data area. Processing any special switches and +; adding a terminating null character. The offset of the copy is +; returned in AX. +; + +get_cmdline: +if 0 + mov di,dataOFFSET cmdline +else + mov di,heap_top ; copy cmdline onto the heap +endif + push ds ; Preserve DS and point to PSP + mov ds,__psp ; Get the PSP address + xor cx,cx ; Now copy the command line + mov cl,ds:0080h ; Get the Command length + mov si,0081h ; and its start location + jcxz get_cmdl20 +get_cmdl10: + lodsb ; Terminate the copy after + cmp al,0Dh ; CX bytes or earlier if a + jz get_cmdl20 ; CR or LF character is found. + cmp al,0Ah ; FrameWork Install Program and + jz get_cmdl20 ; Bitstream FontWare + stosb + loop get_cmdl10 + +get_cmdl20: + xor al,al ; Zero Terminate the command + stosb ; line copy for C. + pop ds +if 0 + mov ax,dataOFFSET cmdline ; Return the command line +else + mov ax,di ; new bottom of heap + xchg ax,heap_top ; return old one = cmdline +endif + ret + +; +; This routine will install the DS relative dummy INT 2E handler with +; a PSP:XXXX entry in the interrupt vector table. A JMPF is coded +; after the handler entry point inorder to correct CS. +; + Public _install_perm +_install_perm: + push es + mov ax,__psp ; Modify the INT 22 and 2E + mov es,ax ; vectors if the current process + cmp ax,PSP_PARENT ; is the ROOT DOS process. ie + jnz inst_p10 ; PSP_PARENT == PSP + + mov al,2Eh ; Install the Command Processor + mov dx,dataOFFSET int2E_entry ; Backdoor entry + call inst_p30 + + mov al,22h ; Update the Command Processor + mov dx,dataOFFSET int22_entry ; Terminate address + call inst_p30 + + push ds ; When this is the ROOT process + push si ; then update the PSP copies of + push di ; interrupt vectors 22, 23, 24 + push ds ; because some TSR management + pop es ; programs examine these variables + lea di,psp_save_area ; ES:DI -> save area for PSP + mov ds,__psp + lea si,PSP_TERM_IP ; DS:SI -> data in PSP to save + mov cx,6 + rep movsw ; save the data for later EXIT + push ds + pop es + lea di,PSP_TERM_IP ; ES:DI -> PSP + mov ds,cx + mov si,022h * 4 ; DS:SI -> real interrupt vecs + mov cx,6 + rep movsw + pop di + pop si + pop ds + +inst_p10: + pop es + ret + +inst_p30: + push ds + mov bx,[low_seg] + sub bx,__psp ; Calculate the correct offset for + mov cl,4 ; the interrupt handler if the segment + shl bx,cl ; must be that of our PSP + add dx,bx + mov ds,__psp + mov ah,MS_S_SETINT + int DOS_INT + pop ds + ret + +page +; +; This routine will restore the Int 22 terminate address copy in +; the PSP in preperation for an EXIT (DeskView bug). +; + Public _restore_term_addr +_restore_term_addr: + push es + mov ax,__psp ; Restore the PSP we altered + mov es,ax ; if the current process + cmp ax,PSP_PARENT ; is the ROOT DOS process. ie + jne restore_ta10 ; PSP_PARENT == PSP + + push si + push di + lea si,psp_save_area + lea di,PSP_TERM_IP + mov cx,6 + rep movsw + pop di + pop si + +restore_ta10: + pop es + ret + +page +; +; This routine will restore the Novell error mode - BAP +; + Public _restore_error_mode +_restore_error_mode: + mov dl,net_error_mode + mov ah,0ddh ; set error mode to the value + int 21h ; it was when COMMAND was + ret ; executed + +page +; +; MASTER_ENV will create a Master Environment of 04[bp] bytes unless +; the environment is already larger in which case the environment +; is increased by 128 bytes. +; + Public _master_env +_master_env: + push bp + mov bp,sp + push si + push di + push es +ifdef DOSPLUS +; mov ax,(MS_M_STRATEGY*256)+1 +; mov bx,1 ; set memory strategy to best fit +; int DOS_INT +endif + mov bx,04[bp] ; Save the Specified Size + add bx,15 ; and force it to be an integer + and bx,not 15 ; multiple of 16 + mov es,__psp ; Get the PSP Segment Address + + mov cx,PSP_ENVIRON ; Get the environment segemnt + jcxz master_env10 ; Have we been loaded by DesQview ? + + mov es,cx ; Scan through the environment and + xor di,di ; determine the Environment size and + xor ax,ax ; the Load file name + mov cx,7FFFh + +master_env05: + repne scasb ; Scan for a ZERO byte + jcxz master_env10 ; Abort if maximum size exceeded + inc di ; Check if the next character was a 0 + cmp al,es:-1[di] ; if YES then this is the end of the + jnz master_env05 ; environment + mov cx,di ; Calculate the environment Size +; +; CX contains the current environment size in bytes. 0 for a DesQview +; system or an empty environment. +; +master_env10: + cmp bx,cx ; Is the current environment larger + jae master_env15 ; No allocate requested value + mov bx,128 + add bx,cx + +master_env15: + push cx ; Save current Environment Size + mov cl,4 ; convert request to paragraphs + shr bx,cl + mov ah,MS_M_ALLOC ; Allocate Memory + int DOS_INT + pop cx + jc master_env30 ; Abort Memory Allocation Failed + + mov es,__psp ; Copy the Environemt + xchg ax,PSP_ENVIRON ; Update the Environment Pointer + push ds + mov ds,ax ; DS -> Initial Environment + mov es,PSP_ENVIRON ; ES -> Master Environment + mov si,0 + mov di,si + jcxz master_env20 ; If this was a Desqview exec then + rep movsb ; skip the environment copy and + ; just initialize to 0000 + +if TRUE ; Invalidate the contents of the + not ds:word ptr 00h ; current environment so Novell +else ; Netware finds the correct Master + push es ; environment under Concurrent DOS. + mov es,ax ; + mov ah,MS_M_FREE ; A possible alternative is to free + int DOS_INT ; the old environment but this would + pop es ; change the memory allocations for +endif ; sub-sequent loads. + +master_env20: + pop ds + xor ax,ax + stosw + +master_env30: +ifdef DOSPLUS +; mov ax,(MS_M_STRATEGY*256)+1 +; xor bx,bx ; set memory strategy to first fit +; int DOS_INT +endif + pop es + pop di + pop si + pop bp + ret + +endif + page +ifndef DOSPLUS +; +; UWORD FAR *sysdat(WORD *); +; + Public _sysdat +_sysdat: + push bp + mov bp,sp + push es + BDOS S_SYSDAT ; Get the SYSDAT segment address + mov ax,word ptr 04[bp] ; and the SYSDAT byte offset + mov bx,es ; and return a FAR pointer to the + mov dx,bx ; data required. MSC uses DX:AX + pop es ; but cater for other compilers + pop bp ; just in case. + ret +endif + +ifdef DOSPLUS +; +; BOOLEAN CDECL int10_cls(); +; +; int10_cls will return TRUE if it issued an INT10 function to +; clear the screen. +; + Public _int10_cls +_int10_cls: + push bp + push si + push di + push es + mov ax,(MS_X_IOCTL*256)+0 ; Get the device attributes for + mov bx,STDOUT ; STDOUT + int DOS_INT + mov ax,0000 ; Assume that the test fails + jc int10_exit ; and return FALSE to the caller + and dl,092h ; Check that STDOUT is the Console + cmp dl,092h ; Out DEVICE and it supports INT29 + jnz int10_exit ; Fast output + + ;;mov es,ax ; Now check that the INT29 routine + ;;mov bx,es:word ptr (29h*4)+2; is below the INT20 service routine + ;;cmp bx,es:word ptr (20h*4)+2; ie that this is a BIOS device driver + ;; jae int10_exit ; No way Jose + ; So what if it isn't? + + mov ax,1A00h ; ANSI.SYS installation check + int 2Fh ; AL = FF on return if ANSI installed + cbw ; AX = FFFF if ANSI present + inc ax ; AX = 0 if ANSI present + jz int10_exit + + +; get number of lines + + call cginfo ; get screen resolution + push dx ; screen lines + + mov ah, 0fh ; get mode + int 10h + and al,7fh + mov ah, 0 ; set mode, clear screen (al bit 7 clear) + int 10h + + call cginfo ; has resolution changed? + pop ax ; restore screen lines + + cmp al, dl ; has # of screen lines changed? + je int10_done ; skip if still the same + + mov ax, 1112h ; character generator + mov bl, 0 ; set 8x8 double dot font + int 10h + + mov ax, 1103h ; set block specifier + mov bl, 0 + int 10h + +int10_done: + mov ax,1 ; All done + +int10_exit: + pop es + pop di + pop si + pop bp + ret + +cginfo: + mov dl, 24 ; assume default # for CGA/MDA + mov ax, 1130h ; character generator info + mov bh, 0 + int 10h + ret ; dl = nlines - 1 + +endif + +ifdef CDOSTMP + +xios: + push ds ; Save the entry segment registers + push es ; then call the XIOS correctly with + ; DS pointing to SYSDAT and ES to the + mov es,uda ; current process's UDA + mov ds,sysdat + call XIOS_ENTRY + pop es + pop ds + ret + +endif + +ifndef DOSPLUS +; +; _vc_data(&vc_base, &vc_num, &pc_num) +; +; VC_DATA returns the first Virtual Console attached to the current +; physical console, the number of virtual consoles attached and the +; physical console. +; + Public _vc_data +_vc_data: + push bp + mov bp,sp + push es + push si + push di + mov si,04[bp] ; SI == &VC_BASE + mov word ptr [si],0000 ; *vc_base = 0 + + les bx,_pd ; Get our process descriptor address + mov ah,0 + mov al,NVCNS + mov cx,ax + mov al,es:P_CNS[bx] ; get the current VC No. + mov bx,CCBLIST ; XIOS CCB$LIST + mov di,ax ; Calculate the correct entry in + shl di,1 ; the CCB$LIST which points to our + mov di,es:word ptr [di+bx] ; CCB and then extract the correct + mov al,CCB_PCNS[di] ; Physical Console Number. + mov di,08[bp] ; Get the address of the PC_NUM + mov word ptr [di],ax ; and save the Physical Console Number + mov di,0000 ; From CCB 0 + +vc_d10: + push di + mov di,es:word ptr [di+bx] ; Get the CCB ad…ress + cmp al,CCB_PCNS[di] ; Is this theY$ame physical console + pop di ; Restore the original DI + jz vc_d30 ; Yes then save info +vc_d20: + inc word ptr [si] ; *VC_BASE++ + inc di ; Point to the next entry in + inc di ; the CCB$LIST and try again + loop vc_d10 + jmp vc_exit + +vc_d30: + mov si,06[bp] ; VC_NUM + mov word ptr [si],0000 ; *VC_NUM = 0 +vc_d40: + push di + mov di,es:word ptr [di+bx] ; Get the CCB address + cmp al,CCB_PCNS[di] ; Is this the same physical console + pop di ; Yes then increment the count + jnz vc_exit ; and continue. + inc word ptr [si] ; *VC_NUM++ + inc di ; Point to the next entry in + inc di ; the CCB$LIST and try again + loop vc_d40 + +vc_exit: + pop di + pop si + pop es + pop bp + ret +endif + +_TEXT ENDS + page +ifdef CDOSTMP + +RSF_DYNAMIC equ 0001h ; create at boot time +RSF_NONBANK equ 0002h ; allocate non-banked +RSF_SPECIAL equ 0004h ; requires separate code +RSF_ENVIRON equ 0008h ; requires large environment + +PD_SEG SEGMENT +; +; This is the standard process descriptor for a TMP. During +; the Concurrent P_CREATE function the contents of this process +; descriptor are copied to a full size descriptor inside SYSDAT. +; + dw 0,0 ; link fields + db PS_RUN ; status + db 200 ; priority + dw PF_SYS+PF_KEEP+PF_SPECIAL; flags + db 'Tmp ' ; Process Name + dw 40h/10h ; uda seg + db 0,0 ; disk,user + db 0,0 ; ldisk,luser + dw 0FFFFh ; mem (Shared Code) + dw 0,0 ; dvract,wait + db 0,0 ; org,net + dw 0 ; parent +cns db 0,0 ; cns,abort + db 0,0 ; cin,cout + db 0,0 ; lst,sf3 + db 0,0 ; sf4,sf5 + dw 0,0 ; reserved + dw 0,0 ; pret,scratch +PD_SEG ENDS + +UDA_SEG SEGMENT +uda_size dw ULEN,80h,0,0 ;0-7 + dw 0,0,0,0 ;8-fh + dw 0,0,0,0 ;10-17 + dw 0,0,0,0 ;18-1f + dw 0,0,0,0 ;20-27 + dw 0,0,0,0 ;28-2f + dw 0,0 ;30-33 +uda_SP dw dataOFFSET uda_stack,0 ;34-37 + dw 0,0,0,0 ;38-3f + dw 0,0,0,0 ;40-47 + dw 0,0,0,0 ;48-4f +uda_CS dw 0 ;50-51 +uda_DS dw 0 ;52-53 +uda_ES dw 0 ;54-55 +uda_SS dw 0 ;56-57 + dw 0,0,0,0 ;58-5f +insys db 1,0 ;60-61 + dw 0,0,0 ;62-67 + db (ULEN-6Eh)dup(0CCH) ; Initialise System Stack +uda_stack dw codeOFFSET RSP_start ; Initial Offset + dw ? ; Initial Segment (Unknown) + dw ? ; Initial Flags (Unknown) +UDA_SEG ENDS + +endif + +ifdef DOSPLUS +_TEXT SEGMENT + public _show_help + public _put_resident_high + public _get_config_env + public _get_original_envsize ; BAP added this + +_show_help PROC NEAR +; +; VOID show_help(index) +; WORD index +; + ;out 0fdh,al + + push bp + mov bp,sp + sub sp,4 ; require 2 WORD local variables + + mov ah,MS_M_ALLOC ; allocate memory for the help text + mov bx,help_length ; bx = no. paragraphs + mov cl,4 + shr bx,cl + int DOS_INT ; do it + jnc show_help_05 + jmp show_help_err0 ; exit on error +show_help_05: + mov -2[bp],ax ; save segment of allocated memory + + push ds + mov ds,[low_seg] + mov dx,dataOFFSET reload_file + mov ax,(MS_X_OPEN*256)+0 ; Open the COMMAND.COM file + int DOS_INT ; do it + pop ds + jc show_help_err1 ; exit on error + mov bx,ax ; bx = file handle + mov -4[bp],ax ; save handle for later + + xor cx,cx + xor dx,dx + cmp exe_file,TRUE ; if command.com is an EXE file take + jne show_help_10 ; account of the EXE header + add dx,200h +show_help_10: + add dx,total_length + add dx,cgroup_length + add dx,cend_length ; dx = file offset of help text + mov ax,(MS_X_LSEEK*256)+0 ; seek to the right location + int DOS_INT ; do it + jc show_help_err2 ; exit on error + + push ds + mov ds,-2[bp] ; ds = help text segment + xor dx,dx ; dx = 0; + mov ah,MS_X_READ ; read from COMMAND.COM file + mov cx,help_length ; cx = no. bytes required + int DOS_INT ; do it + pop ds + jc show_help_err2 ; exit on error + cmp ax,0 ; zero bytes read means there's no + je show_help_err2 ; help seg tagged to file. + +ifdef DLS + call _get_msg_lang ; get a far pointer to msg_language var + mov es,dx ; dx:ax = far pointer on return + mov bx,ax ; + mov bx,es:[bx] ; bx = msg_language + shl bx,1 ; multiply bx by 2 +else + xor bx,bx ; bx = 0 +endif + mov es,-2[bp] ; ds = help text segment + mov bx,es:[bx] ; bx -> help message offset table + mov ax,4[bp] ; ax = message index + shl ax,1 ; multiply by 2 + add bx,ax ; bx -> offset of required message + mov bx,es:[bx] ; bx -> message + + call write_string ; display the message + +show_help_err2: + mov ah,MS_X_CLOSE ; close the file + mov bx,-4[bp] ; bx = file handle + int DOS_INT ; do it + +show_help_err1: + mov ah,MS_M_FREE ; free the memory + push es + mov es,-2[bp] ; es = segment to free + int DOS_INT ; do it + pop es + +show_help_err0: + add sp,4 + pop bp + ret + + +write_string: + ;extrn _str:byte + + ; es -> help segment + ; bx -> message in help segment + +write_string_00: + ;mov di,dataOFFSET _str ; di -> local buffer + mov di,[heap_top] +write_string_05: + mov al,es:[bx] ; get a character + cmp al,0ah ; check for NEWLINE... + jnz write_string_10 ; ...jump if its not + + mov al,0dh ; replace LF with CR LF + mov [di],al ; + inc di ; + mov al,0ah ; + mov [di],al ; + inc di ; + mov al,0 ; + mov [di],al ; terminate string + call flush_buff ; display it + inc bx ; + jmp write_string_00 ; start again + +write_string_10: + cmp al,0 ; check for NULL... + jnz write_string_20 ; ...jump if its not + + mov [di],al ; store char + call flush_buff ; display string + jmp write_string_90 ; exit + +write_string_20: + cmp al,'%' ; messages have doubled %'s because + jnz write_string_30 ; were intended for printf originally. + inc bx ; => skip next character. +write_string_30: + mov [di],al ; store char + inc di ; + inc bx ; + jmp write_string_05 ; loop + +write_string_90: + ret + +flush_buff: + extrn strlen_:near + extrn c_write_:near + + ;mov ax,dataOFFSET _str ; watcom C requites first param in AX + mov ax,[heap_top] + call strlen_ ; get length of string + mov dx,ax ; watcom C requires second param in DX + ;mov ax,dataOFFSET _str ; watcom C requires first param in AX + mov ax,[heap_top] + call c_write_ ; display the string + ret + +_show_help ENDP + + + +try_high_memory PROC NEAR +; This function attempts to allocate some high memory at FFFF:E0 by modifying +; the HIMEM FREE CHAIN maintained by the BDOS. +; on entry: bx = no. paras required (preserved) +; on exit: Carry Set = unsuccessful +; otherwise +; ax = FFFF = segment of allocated memory +; HIMEM Free Chain is modified. + + + push ds + push es + push bx + + mov cl,4 ; multiplying bx by 4... + shl bx,cl ; ...gives memory required in bytes + mov dx,bx ; put it in dx because bx is used for + ; somthing else + + + add dx,HISEG_OFF + + mov ax,4458h ; get private data area + int DOS_INT ; do it + mov si,es:10h[bx] ; ax = start of HIMEM Free Chain + test si,si ; zero means there's no chain so... + je thm_unsuccessful; ...return unsuccessful + + mov ax,0FFFFh ; + mov ds,ax ; ds:si -> first free himem area + + cmp si,HISEG_OFF ; check if area starts at or below HISEG_OFF + ja thm_unsuccessful; ...return unsuccessful + mov cx,2[si] ; CX = length of free area + cmp cx,dx ; check if length >= that required + jb thm_unsuccessful; ...return unsuccessful + + mov ax,[si] ; assume we will use the entire block + mov es:10h[bx],ax ; so unlink it from the chain + + mov di,HISEG_OFF ; generate HIMEM REGISTRATION link and + mov ax,di ; update root in private data area + xchg ax,es:14h[bx] + mov [di],ax + mov 2[di],dx ; remember how much we have used + +; JBM commented this line out, I put it back in. (BAP) + sub 2[di],di +; see above comment (JBM) + + sub cx,dx ; subtract amount used from actual size + cmp cx,256 ; if less than 256 bytes are left + jb thm_success ; then just forget about them + + mov si,di ; there is enough to be worth recyling + add si,dx ; SI -> free block following allocation + mov 2[si],cx ; it's this long + mov ax,si + xchg ax,es:10h[bx] ; put at head of HMA free chain + mov [si],ax +thm_success: + mov ax,0ffffh ; return success + clc ; + jmp thm_exit ; + +thm_unsuccessful: + stc ; return failure +thm_exit: + pop bx + pop es + pop ds + ret + +try_high_memory ENDP + + +_put_resident_high PROC NEAR +; +; VOID put_resident_high(param) +; WORD param; +; +; param = 0 Try HIGH memory, then UPPER memory +; param = 1 Only try HIGH memory +; param = 2 Only try UPPER memory +; + +PRH_PARAM equ word ptr 4[bp] + + push bp + mov bp,sp + push si + push di + + + mov ax,(MS_M_STRATEGY*256)+2 + int DOS_INT ; get existing HMA link + mov ah,0 + push ax ; save it + mov bx,total_length ; get size of resident code/data + sub bx,(dataOFFSET hi_seg_start)-15 + mov cl,4 ; subtract size of low memory stub + shr bx,cl ; bx = block size in paras. + + cmp PRH_PARAM,2 ; skip the next bit if we're only + je prh_upper ; looking at UPPER memory + + call try_high_memory ; first try to allocate high memory + ; ie seg FFFF + jnc prh_success ; jump if successful + + cmp PRH_PARAM,0 ; if we're only looking at HIGH memory + jne prh_exit ; then we exit now + +prh_upper: + push bx ; save length + mov ax,(MS_M_STRATEGY*256)+1 + mov bx,41h ; set memory strategy to best fit + int DOS_INT ; upper only + mov ax,(MS_M_STRATEGY*256)+3 + mov bx,1 ; try to link in upper memory + int DOS_INT + pop bx ; recover length + jc prh_exit ; no upper memory, stop now + + mov ah,MS_M_ALLOC ; allocate some memory + int DOS_INT ; do it + jc prh_exit ; no upper memory, stop now + + sub ax,HISEG_OFF/16 ; bias segment appropriately + +prh_success: +; AX = segment to relocate to +; + mov es,ax ; es = new block + + mov si,dataOFFSET hi_seg_start ; start at R_TEXT segment + mov di,si + + mov cx,total_length ; get size of resident code/data + sub cx,si ; subtract size of low memory stub + + mov [reloc_seg],ax ; These values in the low memory + mov [reloc_off],di ; stub are used by TaskMAX to find + mov [reloc_size],cx ; the relocated code/data + + + mov [data_seg],ax ; update data_seg variable + mov [exec_seg],ax ; and some others... + mov [readline_seg],ax + mov [func4b_seg],ax + mov [int2E_seg],ax + mov ds:word ptr [control_break_entry+3],ax + mov ds:word ptr [crit_error_entry+3],ax + + add si,4 ; take account of HIMEM + add di,4 ; REGISTRATION link + sub cx,4 + + rep movsb ; move'em + + mov bx,ds + sub bx,[__psp] ; ax = difference between psp and data + add bx,HISEG_OFF/16 ; add size of bit we leave behind + + mov es,[__psp] ; es -> old location + + mov ds,ax ; this is the new data seg + mov ss,ax ; and also the new stack seg + + mov ah,MS_M_SETBLOCK ; modify old segment size + int DOS_INT ; do it + +prh_exit: + pop bx ; recover upper memory link + mov ax,(MS_M_STRATEGY*256)+3 + int DOS_INT ; restore to original state + + mov ax,(MS_M_STRATEGY*256)+1 + xor bx,bx ; set memory strategy to first fit + int DOS_INT + + + pop di + pop si + pop bp + + ret + +_put_resident_high ENDP + + +_get_config_env PROC NEAR + + ; BYTE FAR *get_config_env(); + ; This function returns a pointer to the start of the config.sys + ; environment. + + mov ax,4458h ; get pointer to private data + int DOS_INT ; do it + mov ax,0 ; es:bx -> private data + jc get_cfg_env10 + xchg ax,es:18[bx] ; ax = segment of config environment +get_cfg_env10: + mov bx,ax ; return FARNULL (0000:0000) + mov dx,ax + xor ax,ax + ret + +_get_config_env ENDP + + +; BAP - This routine finds the orignal COMMAND.COM's environment size. +; This may not be the best way of doing it .. ! +; It finds the PSP of the original COMMAND.COM by checking the PSP seg +; against the parent PSP seg. If they are not the same, it repeats for +; the parent. When they are the same, it has found the original COMMAND +; and finds the environment size. + +_get_original_envsize PROC NEAR + push bp + mov bp,sp + push si + push di + push es + push cx + mov ah,51h + int DOS_INT ; get current PSP seg +try_next: + mov es,bx + mov cx,bx ; move into CX + mov bx,0 + mov ax,es:16h[bx] ; get parent PSP seg in ax + cmp ax,cx ; are they the same ? + je got_org_psp ; yes - found COMMAND.COM PSP + mov bx,ax ; else make this current seg and + jmp try_next ; try again + +got_org_psp: + mov es,ax ; ES = COMMAND.COM PSP seg + mov bx,0 + mov ax,es:2ch[bx] ; get env seg in ax + cmp ax,0 ; seg = 0000 ? + je bomb_out ; yes - forget it + dec ax ; AX:0000 points to memory descriptor + mov es,ax + mov ax,es:3[bx] ; find length of seg ( in paras) + mov cl,4 + shl ax,cl ; convert to bytes +bomb_out: + mov bx,ax + mov dx,ax + pop cx + pop es + pop di + pop si + pop bp + ret +_get_original_envsize ENDP + + +_TEXT ENDS +endif + +ifndef CDOSTMP + +R_TEXT SEGMENT + extrn _out_pipe:byte + extrn _kbdbuf:byte +R_TEXT ENDS + +_TEXT SEGMENT + + public _get_reload_file +_get_reload_file: + +; copy reload_file to heap + + push ds + push es + push si + push di + + ;mov ax,0e40h + ;int 10h + + mov ax,ds + mov es,ax + mov ds,[low_seg] + mov di,[heap_top] + mov si,offset reload_file + cld +grf_loop: + lodsb + stosb + cmp al,0 + jnz grf_loop + + pop di + pop si + pop es + pop ds + ret + + public _set_reload_file +_set_reload_file: + +; copy string on heap to reload file + + push es + push si + push di + + ;mov ax,0e40h + ;int 10h + + mov es,[low_seg] + mov si,[heap_top] + mov di,offset reload_file + cld +srf_loop: + lodsb + stosb + + cmp al,20h ; BAP from here + jne srf_brian ; if AL = 20h, poke a 00 + xor al,al ; in instead, to terminate + dec di ; the file. COMSPEC can then have + stosb ; switches, but reload_file is +srf_brian: ; just the file name. + + cmp al,0 + jnz srf_loop + + pop di + pop si + pop es + ret + + public _get_out_pipe +_get_out_pipe: + +; copy out_pipe filename from low_seg to data seg + + push ds + push es + push si + push di + + ;mov ax,0e40h + ;int 10h + + mov ax,ds + mov es,ax + mov di,offset DGROUP:_out_pipe + + mov ds,[low_seg] + mov si,offset out_pipe + + mov cx,8 + cld + rep movsb + + pop di + pop si + pop es + pop ds + ret + + public _docmd_int2f +; +; BOOLEAN docmd_int2f(BYTE *cmdline, BYTE *cmd, UWORD count); +; +; cmdline db max, actual, 'COMMAND LINE', CR +; cmd db length, 'COMMAND', CR +; count db remaining length of tail, FF/00 internal/external flag +; +; + +_docmd_int2f: + + push bp + mov bp,sp + push bx + push si + + mov bx,4[bp] ; bx -> original command line + mov si,6[bp] ; si -> upper cased command + mov cx,8[bp] + mov dx,0ffffh + + mov ax,0AE00h + int 2fh + + test al,al + jz docmd_int2f_exit + + mov bx,4[bp] + mov si,6[bp] + mov cx,8[bp] + mov dx,0ffffh + + mov ax,0AE01h + int 2fh + mov al,1 +docmd_int2f_exit: + cbw ; return true if handled + pop si + pop bx + pop bp + mov bx,ax + mov dx,ax + ret + +_TEXT ENDS + +endif + + end ; start address diff --git a/COMMAND/CSUP.ASM b/COMMAND/CSUP.ASM new file mode 100644 index 0000000..66769f2 --- /dev/null +++ b/COMMAND/CSUP.ASM @@ -0,0 +1,756 @@ +; File : $Workfile: CSUP.ASM$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; ENDLOG +; +; 28 Jan 88 Change the validation check for the environment. Now we look +; for a valid DOS Memory Descriptor which is owned by the +; Command Processor. +; 12 May 88 Handle Empty environments correctly (Thanks DesqView) +; 26 May 88 ach _stack is only defined for MSC +; 16 Jun 88 Support TURBO C Stack checking and enable CHKSTK for +; MSC only. +; 26 Aug 88 Make the Minimum Stack Address Public +; 14 Apr 89 Make heap_top public +; 14 Jul 89 Move findeof to assembler +; 09 Oct 90 Write heap_size() to return remaining bytes on heap at +; any given instance +; + +_DLS_INCLS_ equ 1 +include message.def + +CGROUP GROUP _TEXT +DGROUP GROUP _DATA + +codeOFFSET equ offset CGROUP: +dataOFFSET equ offset DGROUP: +STACKSLOP equ 128 ; Minimum Stack Size + +jmps macro label ; Define a Macro to generate the + jmp SHORT label ; Short Jmp instruction + endm + + +_TEXT SEGMENT byte public 'CODE' +ifdef MWC + extrn longjmp:near ; MetaWare does not preceed library +LONGJUMP equ longjmp ; functions with an UNDERSCORE +else +ifdef WATCOMC + extrn longjmp_:near +LONGJUMP equ longjmp_ +else + extrn _longjmp:near +LONGJUMP equ _longjmp +endif +endif + + assume cs:CGROUP, ds:DGROUP, es:nothing + + public _debug +_debug proc near + + out 0fdh,al + ret + +_debug endp + + +; Environment manipulation routines +; ================================= +; +;BOOLEAN env_entry(BYTE *buf, WORD entry); +; +; Copy entry number ENTRY into the buffer BUF. Return FAILURE +; if ENTRY cannot be found. +; + assume cs:CGROUP, ds:DGROUP, es:nothing + + public _env_entry +_env_entry PROC near + cld + push bp + mov bp,sp + push ds + push si + push es + push di + call get_env ; Get the environment segment + mov es,bx ; Initialise ES + mov cx,ax ; Check the environment size - 1 + dec cx ; and FFFF bytes if no env header + xor di,di ; Offset to start scaning for data + xor ax,ax +env_e10: + cmp es:byte ptr [di],al ; Is this a Null string + jz env_fail ; Then hit the end of the search + cmp word ptr 06[bp],0 ; Is this the entry required + jz env_e20 + repnz scasb ; Scan for the next zero byte + jcxz env_fail ; and abort if out of space + dec word ptr 06[bp] ; Decrement the string count + jmps env_e10 +env_e20: ; Found the correct entry now copy + mov si,di ; Get the correct source offset + push ds + push es + pop ds + pop es + mov di,04[bp] +env_e30: + lodsb + stosb ; Copy byte through AL + or al,al + jnz env_e30 ; and check for end of string + jmps env_exit +_env_entry ENDP + +;BOOLEAN env_scan(BYTE *key, BYTE *buf); +; +; Scan through the environment searching for the string KEY then copy +; the result into buffer. + + Public _env_scan +_env_scan PROC near + cld + push bp + mov bp,sp + push ds + push si + push es + push di + call get_env ; Get the environment segment + call get_key ; Find the key + jz env_fail ; Abort if an error occurs + add di,dx ; Add the Key length and just copy + mov si,di ; The key definition into the + push ds ; Buffer + push es + pop ds + pop es + mov di,06[bp] +env_s10: + lodsb + stosb ; Copy byte through AL + or al,al + jnz env_s10 ; and check for end of string + jmps env_exit +_env_scan ENDP + +; +; Environment handling exit routines + +env_err: ; Invalid Environment descriptor + mov ax,-1 ; return with -1 + jmps env_ret + +env_fail: ; Environment fail the operation + mov ax,1 ; requested has failed. + jmps env_ret + +env_exit: + xor ax,ax + +env_ret PROC near + pop di + pop es + pop si + pop ds + pop bp + ret +env_ret ENDP + +; +;BOOLEAN env_del(BYTE *key); +; Delete the entry matching KEY from the environment and return +; success or failure +; + public _env_del +_env_del PROC near + cld + push bp + mov bp,sp + push ds + push si + push es + push di + call get_env ; Get the environment segment + jz env_err ; Stop if not the real thing + call get_key ; Find the key + jz env_fail ; Abort if an error occurs + mov ds,bx ; Point DS at the environment + mov si,di ; save the destination offset + add di,dx ; and search for the end of this string + xor ax,ax + mov cx,-1 + repnz scasb ; Now search for the end of string + xchg si,di ; Swap the source and destination +env_d10: + cmp al,[si] ; Is this the end of the environment + jz env_d20 ; Yes so terminate +env_d15: + lodsb + stosb ; Copy through AL checking for the end + or al,al + jnz env_d15 ; of the environment after each + jmps env_d10 ; end of string. +env_d20: + stosw ; Force 0 word to be placed here to + jmps env_exit ; terminate the string +_env_del ENDP + +;BOOLEAN env_ins(BYTE *str); +; Insert the string at the end of the current environment +; checking if there is enough room to save the string. +; + public _env_ins +_env_ins PROC near + cld + push bp + mov bp,sp + push ds + push si + push es + push di + call get_env ; Get the environment segment + jz env_err ; and its segment + sub ax,2 ; Decrement the size of the env + mov cx,ax ; to make sure we can store a 0 + xor ax,ax ; word terminator + mov es,bx ; Find the end of the current env + xor di,di +env_i10: + repnz scasb + jcxz env_fail + cmp al,es:byte ptr [di] + jnz env_i10 + cmp di,1 ; Is this an empty Environment + jnz env_i25 ; No. If yes then start from offset 0 + dec di +env_i25: + mov bx,di ; Save the starting address of string + mov si,04[bp] ; Get the source string offset +env_i20: + lodsb + stosb ; Copy the String until a zero byte + or al,al ; then add the environment terminator + loopnz env_i20 + mov es:word ptr [di],0 + jz env_exit ; Exit with no error if the string is + mov es:byte ptr [bx],00 ; terminated correctly otherwise remove + jmps env_fail ; all traces of this string and exit +_env_ins ENDP +; + page +; +; Returns environment size in Bytes in AX or zero if error +; and BX is the Environment segment. +; +get_env PROC near + push es + mov dx,__psp ; Get the Current PSP in DX + mov es,dx ; and point ES at Our PSP + xor ax,ax ; and assume an error condition + mov bx,es:002Ch ; get environment segment + dec bx ; Check for memory descriptor + mov es,bx + inc bx + cmp es:byte ptr 00h,'M' ; Byte 0 must contains either an + jz get_e10 ; M or Z and the DMD be owned by + cmp es:byte ptr 00h,'Z' ; the Command Processor + jnz get_e20 +get_e10: +if 0 + cmp dx,es:word ptr 1h ; Is this "OUR" PSP if not then + jnz get_e20 ; complain bitterly. +endif + mov ax,es:word ptr 3h ; Get the memory size in paragraphs + shl ax,1 ; convert to size in bytes and exit. + shl ax,1 + shl ax,1 + shl ax,1 +get_e20: + pop es + or ax,ax + ret +get_env ENDP + +; +; enter this search function with BX == ENVIRONMENT SEGMENT +; 04[bp] == Key string offset +; On exit AX == 0 Failure +; else DX is Key string Length +; DI is Offset +; +get_key PROC near + push ds + pop es ; Calculate the length of the + mov di,04[bp] ; key by scaning the string for + mov al,0 ; a zero byte. + mov cx,-1 + repnz scasb + neg cx ; CX is the length of the sting + 2 + sub cx,2 + mov dx,cx ; Save the count in dx + + xor ax,ax + mov es,bx ; Point ES at the environment + xor di,di ; and start from the begining +get_k10: + push di ; Save incase this is a match + mov cx,dx ; Get the string length + mov si,04[bp] ; and offset and check for a match + repz cmpsb + jnz get_k20 ; No match so get the next string + pop di ; This is the starting offset + or ax,-1 ; All ok + ret +get_k20: + pop cx ; Throw away the old DI + mov cx,-1 ; Set the count to maximum + repnz scasb ; and search for the end of the string + cmp al,es:[di] ; exit with error if this is the end + jnz get_k10 ; of the environment + ret +get_key ENDP + + page + assume cs:CGROUP, ds:DGROUP, es:nothing +ifdef MSC +; +; +; STACK(WORD) allocates memory from the C STACK if at any stage +; the stack grows to within STACKSLOP of the top of the heap this +; function executes a LONGJUMP using the BREAK_ENV buffer. This will +; terminate any internal function. +; +PUBLIC _stack +_stack: + pop bx ; Get the return address + pop cx ; and the number of bytes required + add cx,1 ; Force CX to be a even value to + and cx,not 1 ; ensure the stack is word aligned + mov ax,sp ; Get the Stack + sub ax,STACKSLOP ; Include STACKSLOP + sub ax,cx ; Subtract requested buffer + jc heap_error ; Exit with error if Carry + cmp ax,heap_top ; Are we still above the heap + jc heap_error ; No + pop ax ; Get possible saved SI + pop dx ; Get possible saved DI + push dx ; Restore the stack to its + push ax ; origibnal format + sub sp,cx ; All OK so update SP + push dx ; Save possible saved DI + push ax ; Save possible saved SI + mov ax,sp ; Return pointer + add ax,4 ; Adjust pointer for saved SI/DI + push cx ; Restore the entry parameter + jmp bx ; and return to the caller +endif +; +; HEAP_GET(WORD) allocates memory from the C HEAP if at any stage +; the heap grows to within STACKSLOP of the base of the stack this +; function executes a LONGJUMP using the BREAK_ENV buffer. This will +; terminate any internal function. +; +PUBLIC _heap_get +_heap_get: + push bp + mov bp,sp + mov ax,heap_top + add ax,04[bp] ; Add in the requested value + jc heap_error ; Exit with error if Carry + sub bp,STACKSLOP ; now check that the stack + cmp bp,ax ; is still well above the + jc heap_error ; heap. + mov stack_min,ax ; Update the Stack Minimum Variable + add stack_min,STACKSLOP ; for the CHKSTK routine + + xchg ax,heap_top ; Return the existing heap top + pop bp ; and update the local variable + ret ; with the new value. + +heap_error: + mov dx,3 ; Return the Heap Overflow error + push dx + mov ax,dataOFFSET _break_env ; using the JMP_BUF + push ax + call LONGJUMP ; We are never coming back + +; +; HEAP_SIZE returns the size remaining on the C HEAP +; +PUBLIC _heap_size +_heap_size: + push bp + mov bp,sp + mov ax,heap_top + add ax,STACKSLOP + sub bp,ax + jnc noprobs + xor bp,bp +noprobs: + mov ax,sp + pop bp + ret + +; +; HEAP() can only return a pointer to the top of the C Heap +; and is identical in function to HEAP_GET(0) except that no +; overflow checking is required and the calling overhead is +; minimal. +; +PUBLIC _heap +_heap: + mov ax,heap_top +ifndef FINAL +ifdef WATCOMC + add ax,STACKSLOP ; we'd better do some stack checking + cmp ax,sp ; 'cause the C isn't doing it now + jae heap_error + sub ax,STACKSLOP +endif +endif + ret + +; +; VOID HEAP_SET(BYTE *) forces the heap to a specified value +; +PUBLIC _heap_set +_heap_set: + push bp + mov bp,sp + mov ax,04[bp] ; Get the new value for the HEAP + cmp ax,dataOFFSET _end ; base and check against the + jnb heap_s10 ; absolute base. If below then force + mov ax,dataOFFSET _end ; the heap to the absolute base +heap_s10: + mov heap_top,ax + mov stack_min,ax + add stack_min,STACKSLOP + pop bp + ret + + page +ifdef MSC +; +; This is our own Stack Check routine which is called on +; entry to every C routine. AX contains the number of bytes +; to be reseved on the stack. +; +PUBLIC __chkstk +__chkstk: + pop cx ; Get the Return Address + + mov bx,sp ; Calculate the new SP value + sub bx,ax ; AX contains the number of bytes + jc OVERFLOW@ ; to reserve. + + cmp bx,stack_min ; Check we are still above the heap + jc OVERFLOW@ ; No !!! Help + mov sp,bx ; Update the Stack pointer + jmp cx ; Its Ok lets go back +endif + +ifdef WATCOMC + Public __STK +__STK: + cmp ax,sp + jnb OVERFLOW@ + sub ax,sp + neg ax + cmp ax,stack_min + jbe OVERFLOW@ + ret +endif + +ifdef TURBOC + Public OVERFLOW@ ; Public TURBOC Stack Error Handler +endif +OVERFLOW@: + mov dx,2 ; Return the STACK Overflow error + push dx + mov ax,dataOFFSET _break_env ; using the JMP_BUF + push ax + call LONGJUMP ; We are never coming back + +; MLOCAL UWORD CDECL findeof(s, count) /* find ^Z in buffer */ +; BYTE FAR *s; /* buffer to search */ +; UWORD count; /* # of bytes in buffer */ +; { +; REG UWORD i; +; +; i = count; +; while(i) { /* Scan through the data */ +; if(*s++ == (BYTE) 0x1A) /* looking for a Control-Z */ +; break; +; i--; +; } +; +; return (count - i); +; } + +PUBLIC _findeof +_findeof: + push bp ; establish a stack frame + mov bp,sp ; s dword 04[bp] + push es ; count word 08[bp] + push di ; save important registers + cld + les di,4[bp] ; load up the pointer + mov cx,8[bp] ; and the count + mov al,26 ; looking for EOF mark in the buffer + repne scasb ; scan until we find one + jne findeof10 ; if we do find one + inc cx ; then include it in the count +findeof10: + mov ax,8[bp] ; we wanted this many + sub ax,cx ; subtract any past EOF + pop di + pop es + pop bp + ret + + +ifdef DLS +public _my_dls_init +; void my_dls_init() + + ;extrn _dls_init:near + ;extrn _dls_get_table:near + +_my_dls_init proc far + + push ds + + push cs + pop ds + + call _dls_init + mov ax,1 + push ax + call _dls_get_table + pop ax + + pop ds + ret + +_my_dls_init endp + +public _copy_crit_msgs +_copy_crit_msgs proc near + + extrn _crit_msgs:word + extrn _crit_text:byte + + push ds + push es + push di + push si + + push ds + pop es + push cs + pop ds + + mov si,_dls_table + add si,msg0 + mov si,[si] + + mov di,offset DGROUP:_crit_text + add di,2 + mov bx,offset DGROUP:_crit_msgs + add bx,2 + + mov cx,24 +ccm_loop1: + mov es:[bx],di + add bx,2 +ccm_loop2: + lodsb + stosb + cmp al,'$' + jne ccm_loop2 + loop ccm_loop1 + + pop si + pop di + pop es + pop ds + ret + +_copy_crit_msgs endp + +public _copy_rld_msgs +_copy_rld_msgs proc near + + extrn _rld_msgs:word + extrn _rld_text:byte + + push ds + push es + push di + push si + + push ds + pop es + push cs + pop ds + + mov si,_dls_table + add si,reload_msgs + mov si,[si] + + mov di,offset DGROUP:_rld_text + add di,2 + mov bx,offset DGROUP:_rld_msgs + add bx,2 + + mov cx,3 +crm_loop1: + mov es:[bx],di + add bx,2 +crm_loop2: + lodsb + stosb + cmp al,0 + jne crm_loop2 + loop crm_loop1 + + pop si + pop di + pop es + pop ds + ret + +_copy_rld_msgs endp + +public _dls_msg1 +; char *dls_msg1(int) + +_dls_msg1: + push bp + mov bp,sp + push bx + + mov ax,4[bp] + shl ax,1 + mov bx,cs:_dls_table + add bx,ax + mov ax,cs:[bx] + + pop bx + pop bp + ret + +endif ; ifdef DLS + +public _dos_parse_filename +_dos_parse_filename proc near + + push bp + mov bp,sp + sub sp,30h + push es + + push ds + pop es + + lea di,-30h[bp] + mov si,4[bp] + + mov ax,2901h + int 21h + + mov ah,0 + pop es + add sp,30h + pop bp + ret + +_dos_parse_filename endp + +public _flush_cache +_flush_cache proc near + + push si + push di + push bp + + mov ax,4a10h + mov bx,0 + mov cx,0edch + int 2fh + + cmp ax,6756h ; NWCACHE + je do_flush + cmp ax,0BABEh ; SmartDrive + jne skip_flush + +do_flush: + mov ax,4a10h + mov bx,1 + mov cx,0edch + int 2fh + +skip_flush: + pop bp + pop di + pop si + ret + + + +_flush_cache endp + + +_TEXT ENDS + + page +_DATA SEGMENT byte public 'DATA' + extrn __psp:word + extrn _end:byte + extrn _break_env:word + extrn low_seg:word + + public stack_min + public heap_top +ifdef TURBOC + public ___brklvl ; Turbo C does an inline check against +___brklvl label word ; ___brklvl and id SP < ___brklvl then +endif ; it calls OVERFLOW@ +stack_min dw dataOFFSET _end + STACKSLOP +heap_top dw dataOFFSET _end ; Current Top of Heap + +_DATA ENDS + END diff --git a/COMMAND/DEFINES.H b/COMMAND/DEFINES.H new file mode 100644 index 0000000..89f8f8c --- /dev/null +++ b/COMMAND/DEFINES.H @@ -0,0 +1,38 @@ +/* +; File : $Workfile$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +*/ + +#define DOSPLUS 1 +#define BETA 1 diff --git a/COMMAND/DOS.H b/COMMAND/DOS.H new file mode 100644 index 0000000..a6df8c3 --- /dev/null +++ b/COMMAND/DOS.H @@ -0,0 +1,116 @@ +/* +; File : $Workfile$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +*/ + + +#define MS_P_TERMCPM 0x00 +#define MS_C_READ 0x01 +#define MS_C_WRITE 0x02 +#define MS_A_READ 0x03 +#define MS_A_WRITE 0x04 +#define MS_L_WRITE 0x05 +#define MS_C_RAWIO 0x06 +#define MS_C_RAWIN 0x07 +#define MS_C_NOECHO 0x08 +#define MS_C_WRITESTR 0x09 +#define MS_C_READSTR 0x0a +#define MS_C_STAT 0x0b +#define MS_C_FLUSH 0x0c +#define MS_DRV_ALLRESET 0x0d +#define MS_DRV_SET 0x0e +#define MS_F_OPEN 0x0f +#define MS_F_CLOSE 0x10 +#define MS_F_SFIRST 0x11 +#define MS_F_SNEXT 0x12 +#define MS_F_DELETE 0x13 +#define MS_F_READ 0x14 +#define MS_F_WRITE 0x15 +#define MS_F_MAKE 0x16 +#define MS_F_RENAME 0x17 +#define MS_DRV_GET 0x19 +#define MS_F_DMAOFF 0x1a +#define MS_DRV_ALLOC 0x1b +#define MS_DRV_ALLOCSPEC 0x1c +#define MS_F_READRAND 0x21 +#define MS_F_WRITERAND 0x22 +#define MS_F_SIZE 0x23 +#define MS_F_RANDREC 0x24 +#define MS_S_SETINT 0x25 +#define MS_P_MKPSP 0x26 +#define MS_F_READBLK 0x27 +#define MS_F_WRITEBLK 0x28 +#define MS_F_PARSE 0x29 +#define MS_T_GETDATE 0x2a +#define MS_T_SETDATE 0x2b +#define MS_T_GETTIME 0x2c +#define MS_T_SETTIME 0x2d +#define MS_F_VERIFY 0x2e +#define MS_F_DMAGET 0x2f +#define MS_S_BDOSVER 0x30 +#define MS_P_TERMKEEP 0x31 +#define MS_S_BREAK 0x33 +#define MS_S_GETINT 0x35 +#define MS_DRV_SPACE 0x36 +#define MS_S_COUNTRY 0x38 +#define MS_X_MKDIR 0x39 +#define MS_X_RMDIR 0x3a +#define MS_X_CHDIR 0x3b +#define MS_X_CREAT 0x3c +#define MS_X_OPEN 0x3d +#define MS_X_CLOSE 0x3e +#define MS_X_READ 0x3f +#define MS_X_WRITE 0x40 +#define MS_X_UNLINK 0x41 +#define MS_X_LSEEK 0x42 +#define MS_X_CHMOD 0x43 +#define MS_X_IOCTL 0x44 +#define MS_X_DUP 0x45 +#define MS_X_DUP2 0x46 +#define MS_X_CURDIR 0x47 +#define MS_M_ALLOC 0x48 +#define MS_M_FREE 0x49 +#define MS_M_SETBLOCK 0x4a +#define MS_X_EXEC 0x4b +#define MS_X_EXIT 0x4c +#define MS_X_WAIT 0x4d +#define MS_X_FIRST 0x4e +#define MS_X_NEXT 0x4f +#define MS_F_GETVERIFY 0x54 +#define MS_F_DATETIME 0x56 +#define MS_F_ERROR 0x59 +#define MS_X_MKTEMP 0x5a +#define MS_X_MKNEW 0x5b +#define MS_F_LOCK 0x5c +#define MS_P_GETPSP 0x62 diff --git a/COMMAND/DOSIF.ASM b/COMMAND/DOSIF.ASM new file mode 100644 index 0000000..5a2deef --- /dev/null +++ b/COMMAND/DOSIF.ASM @@ -0,0 +1,2907 @@ +; File : $Workfile: DOSIF.ASM$ +; +; Description : +; +; Original Author : +; +; Last Edited By : $Author: RGROSS$ +; +; Copyright : (C) 1992 Digital Research (UK), Ltd. +; Charnham Park +; Hungerford, Berks. +; U.K. +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log: $ +; DOSIF.ASM 1.1 94/06/28 16:01:14 RGROSS +; Initial PUT +; DOSIF.ASM 1.16 94/06/28 16:01:28 IJACK +; ms_x_expand returns error codes (for benefit of TRUENAME) +; DOSIF.ASM 1.15 93/11/29 19:57:24 IJACK +; +; -------- +; +; DOSIF.ASM 1.13 93/09/09 10:24:50 RFREEBOR +; call_novell() now returns all allowed error codes. +; +; DOSIF.ASM 1.12 93/02/24 17:42:49 EHILL +; _get_scr_width() function added. +; +; DOSIF.ASM 1.11 93/01/21 16:19:31 EHILL +; +; DOSIF.ASM 1.10 93/01/21 14:32:32 EHILL +; +; DOSIF.ASM 1.8 92/09/11 10:46:28 EHILL +; +; DOSIF.ASM 1.7 92/08/06 09:56:07 EHILL +; Added DOS 5 calls to get and set memory allocation strategy and +; upper memory link. +; +; DOSIF.ASM 1.6 92/07/10 17:47:13 EHILL +; No comment +; +; ENDLOG +; +; This file provides all the assembler level interfaces to the +; underlying operating system that are required by COMMAND.COM. +; The type of functions calls that will be made is controlled +; by a Assemble time flag. +; +; Currently the Operating System Interfaces that are supported +; are MS-DOS and Concurrent DOS 6.0. +; +; +; Command Line Flags +; ================== +; +; MSDOS If defined then USE MSDOS function Calls +; CDOS If defined then Use Concurrent DOS Calls +; +; +; 2/Sep/87 jc Convert the Concurrent IOCTL function to use the FDOS +; command. +; 19/Oct/87 jc Handle Fail on Get current directory correctly +; 23/Feb/88 jc Use Text substitution function to get the path assigned +; to floating drives (ms_x_subst). +; 3/Mar/88 jc Support Server Password Error +; 9/Mar/88 jc Return a NULL terminated string when an error occurs on the +; ms_x_subst function. +; 15/Mar/88 jc Correct ms_x_subst register corruption bug +; 13/Apr/88 jc Support the FAR_READ and FAR_WRITE routines as well as external +; copy buffer allocation via MEM_ALLOC and MEM_FREE +; 20/May/88 jc Return the current country code to the calling application +; 25/May/88 jc Missing dataOFFSET causing garbage offset to be passed +; ms_x_subst. +; 18/Jul/88 jc Modify LOGICAL_DRV test to detect substituted physical drives +; 17/Aug/88 jc Return the current Break Status using DL not AL +; 22/Sep/88 jc Replace MS_X_SUBST with more general MS_X_EXPAND routine +; 25/Jan/89 ij If new DRDOS internal data layout get DPHTBL the new way +; 07/Feb/89 jc Add the Get and Set Global Codepage MS_X_GETCP/MS_X_SETCP +; 25/Jan/89 ij Get DPHTBL using DRDOS_DPHTBL_OFFSET equate +; 14/Apr/89 jjs Add ms_x_setdev +; 31/May/89 ij Get SYSDAT for DPHTBL using new f4458 function +; 19/May/89 jc Remove "Alternative" techniques of getting SYSDAT:DPHTABLE +; 20/Jun/89 js ms_f_parse, ms_f_delete, for DEL cmd +; 30/Aug/89 js ms_idle_ptr +; 6/Sep/89 ij network_drvs really does something on DRDOS +; 16/Oct/89 ach Added double byte character set support routines: dbcs_init, +; dbcs_expected and dbcs_lead. +; 18/Jan/90 ij HILOAD interfaces added +; 4/Apr/90 ij dbcs_init moved to cstart, use system table, then we can throw +; away the init code +; 24-May-90 ij ms_x_expand sets up ES.... +; 17 Sep 90 ij TMP Control Break kludge echo's ^C to console +; 4 Oct 90 ij Use P_CAT, not P_HDS +; 15 Mar 91 jc DRDOS_DPHTBL is now called SYSDAT_DPHTBL cos thats where it lives +; 28 May 91 ejh No longer use SYSDAT to determine if drives are physical, +; logical or networked. See _physical_drive, _logical_drive and +; _network_drive. +; 23 Jun 91 ejh SUBST and ASSIGN are now external commands, so the following +; are no longer required: +; _physical_drvs, _logical_drvs, _network_drvs +; _physical_drive,_logical_drive,_network_drive +; 3 jul 91 ij except for NETDRIVE in MDOS +; +; 18 Jun 92 ejh Added get_lines_page() function. +; 24 Jun 92 ejh Added novell_copy() function. + +CGROUP group _TEXT +DGROUP group _DATA + +codeOFFSET equ offset CGROUP: +dataOFFSET equ offset DGROUP: + +EXT_SUBST equ 1 ; External Subst and Assign commands + +CRET MACRO num + ret + ENDM + +ifndef ??Version ;; Turbo Assembler always knows RETF +ifndef retf ;; some versions of MASM do as well +retf macro ;; define far return macro for others + db 0cbh + endm +endif +endif + + +ifndef CDOSTMP +include msdos.equ +endif + +ifndef DOSPLUS +include system.def +include pd.def +include ccpm.equ +;include udaa.def +include net.def +include mserror.equ +else +include f52data.def +endif +; +ifdef CDOSTMP +OK_RIF equ 00111000b ; All Responsese are Valid +OK_RI equ 00110000b ; Retry and Ignore are Valid +OK_RF equ 00011000b ; Retry and Fail are Valid +; +; Structure of DOS DPB +; -------------------- +; The layout of this structure is a guess based on +; examples. It is returned by PC MODE on functions 1Fh and +; 32h and is required by various disk-related utilities +; like disk editors and CHKDSK. + +DDSC_UNIT equ es:byte ptr 0 ; absolute drive number +DDSC_RUNIT equ es:byte ptr 1 ; relative unit number +DDSC_SECSIZE equ es:word ptr 2 ; sector size in bytes +DDSC_CLMSK equ es:byte ptr 4 ; sectors/cluster - 1 +DDSC_CLSHF equ es:byte ptr 5 ; log2 (sectors/cluster) +DDSC_FATADDR equ es:word ptr 6 ; sector address of FAT +DDSC_NFATS equ es:byte ptr 8 ; # of FAT copies +DDSC_DIRENT equ es:word ptr 9 ; size of root directory +DDSC_DATADDR equ es:word ptr 11 ; sector address of cluster #2 +DDSC_NCLSTRS equ es:word ptr 13 ; # of clusters on disk +DDSC_NFATRECS equ es:byte ptr 15 ; # of sectors per FAT +DDSC_DIRADDR equ es:word ptr 16 ; sector address of root dir +DDSC_DEVHEAD equ es:dword ptr 18 ; device driver header +DDSC_MEDIA equ es:byte ptr 22 ; current media byte +DDSC_FIRST equ es:byte ptr 23 ; "drive never accessed" flag +DDSC_LINK equ es:dword ptr 24 ; next drive's DDSC +DDSC_BLOCK equ es:word ptr 28 ; next block to allocate +DDSC_FREE equ es:word ptr 30 ; total free clusters on drive +DDSC_MAP equ es:word ptr 32 ; free blocks/FAT sector +endif + +BDOS_INT equ 224 ; ##jc## + + +_DATA SEGMENT byte public 'DATA' + extrn __psp:word +ifndef DOSPLUS + extrn _pd:dword ; Process Descriptor Pointer +endif + extrn _country:WORD + +ifdef DOSPLUS + extrn dbcs_table_ptr:dword ; points to system DBCS table +endif + +ifdef CDOSTMP +; +; The following buffer is used by the P_PATH function. +; FINDFILE uses the first three fields to get the full path and +; filename of the command. +; +exec_block label byte +exec_pathoff dw ? ; Offset of ASCIIZ Load file +exec_pathseg dw ? ; Segment of ASCIIZ Load File +exec_filetype db ? ; File Type Index + +fdos_data dw 7 dup(0) ; FDOS parameter Block + +mpb_start dw ? ; Memory parameter Block +mpb_min dw ? +mpb_max dw ? +mpb_pdadr dw ? +mpb_flags dw ? + +mfpb_start dw ? ; Memory Free Parameter Block +mfpb_res dw ? + +country_data label word ; GET country data +cd_country dw ? ; Requested Country Code +cd_codepage dw ? ; Requested Code Page +cd_table dw ? ; Table Number +cd_offset dw ? ; Buffer Offset +cd_segment dw ? ; Buffer Segment + +valid dw 0 ; Valid Error Responses +retry_ip dw 0 ; Critical Error Retry IP +retry_sp dw 0 ; Critical Error Retry SP +crit_flg db FALSE ; Critical Section of Error Handler + +include fdos.def +endif + +ifdef NETWARE +ipx label dword +ipx_offset dw 0 +ipx_segment dw 0 +; +; Socket Allocation by Novell +; +; Socket Nos 4000 and 4001 appear to be used by the IPX internally +; and these are NOT closed by the NET_WARE routine. All other USER +; sockets are closed. +; +; List of sockets to be closed on shutdown +; Start Count +socket label word +;; dw 0001h, 0BB8h + dw 4002h, 3FFFh - 2 ; User Socket Numbers + dw 0, 0 + +aes label byte ; Event Control Block +aes_link label dword ; Link Field +aes_linkoff dw 0 +aes_linkseg dw 0 +aes_esr label dword ; Service Routine Address +aes_esroff dw codeOFFSET aes_retf +aes_esrseg dw 0000 +aes_inuse db 0 ; Flag Field +aes_workspc db 5 dup(?) ; AES WorkSpace +endif +_DATA ENDS + +_TEXT SEGMENT byte public 'CODE' + assume cs:CGROUP, ds:DGROUP, es:DGROUP + +extrn _int_break:near ; Control-C Break Handler + +ifdef CDOSTMP +ifdef MWC +extrn _critical_error:near ; Default Critical Error Handler +CRITICAL_ERR equ _critical_error +else +extrn CRITICAL_ERROR:near ; Default Critical Error Handler +CRITICAL_ERR equ CRITICAL_ERROR +endif +endif + +; +; UWORD psp_poke(WORD handle, BYTE ifn); +; + Public _psp_poke +_psp_poke: + push bp + mov bp,sp + push es + +ifdef CDOSTMP + mov es,__psp ; ES:0 -> our PSP +else + mov ah,MS_P_GETPSP + int DOS_INT ; for software carousel + mov es,bx +endif + les bx,es:[0034h] ; ES:BX -> external file table + add bx,4[bp] ; ES:BX -> XFT entry for our handle + mov al,6[bp] ; get new value to use + xchg al,es:[bx] ; get old value, set new value + xor ah,ah + + pop es + pop bp + ret + +ifndef CDOSTMP + + + Public _ms_drv_set +;----------- +_ms_drv_set: +;----------- + push bp + mov bp,sp + mov dl,04[bp] + mov ah,MS_DRV_SET ; Select the Specified Disk Drive + int DOS_INT ; Nothing Returned to caller + pop bp + ret + + Public _ms_drv_get +;----------- +_ms_drv_get: +;----------- + mov ah,MS_DRV_GET ; Return the Currently selected + int DOS_INT ; disk drive + cbw + ret + + Public _ms_drv_space +;------------ +_ms_drv_space: +;------------ +; +; ret = _ms_drv_space (drive, &free, &secsiz, &nclust); +; where: drive = 0, 1-16 is drive to use +; free = free cluster count +; secsiz = bytes/sector +; nclust = clusters/disk +; ret = sectors/cluster -or- (0xFFFFh) + + push bp + mov bp,sp + mov dx,4[bp] + mov ah,MS_DRV_SPACE + int DOS_INT + push bx + mov bx,6[bp] ; get free cluster count + pop word ptr [bx] + mov bx,8[bp] + mov [bx],cx ; bytes/sector + mov bx,10[bp] + mov [bx],dx ; clusters/disk + cbw + pop bp + ret + + Public _ms_s_country +;------------ +_ms_s_country: +;------------ + push bp + mov bp,sp + mov ax,MS_S_COUNTRY shl 8 ; Get the curremt country information + mov dx,4[bp] ; and return the current country code + int DOS_INT ; to the calling application. + mov ax,bx + pop bp + ret + + + Public _ms_x_mkdir +;---------- +_ms_x_mkdir: +;---------- + mov ah,MS_X_MKDIR + jmp ms_dx_call + + + Public _ms_x_rmdir +;---------- +_ms_x_rmdir: +;---------- + mov ah,MS_X_RMDIR + jmp ms_dx_call + + + Public _ms_x_chdir +;---------- +_ms_x_chdir: +;---------- + mov ah,MS_X_CHDIR + jmp ms_dx_call + + Public _ms_x_creat +;---------- +_ms_x_creat: +;---------- + mov ah,MS_X_CREAT + jmp ms_open_creat + + + Public _ms_x_open +;--------- +_ms_x_open: +;--------- + mov ah,MS_X_OPEN +ms_open_creat: + push bp + mov bp,sp + mov dx,4[bp] + mov cx,6[bp] ; get mode for new file (CREAT) + mov al,cl ; or open mode (OPEN) + int DOS_INT + jnc ms_open_ret ; AX = handle if no error + neg ax ; else mark as error code +ms_open_ret: + pop bp + ret + + Public _ms_x_close +;---------- +_ms_x_close: +;---------- + push bp + mov bp,sp + mov bx,4[bp] ; get the open handle + mov ah,MS_X_CLOSE ; get the function + jmp ms_call_dos ; call DOS, handle errors + + Public _ms_x_unique +;---------- +_ms_x_unique: +;---------- + mov ah,MS_X_MKTEMP + jmp ms_open_creat + + Public _ms_x_fdup +;---------- +_ms_x_fdup: +;---------- + push bp + mov bp,sp + mov cx,4[bp] ; get the destination handle + mov bx,6[bp] ; Get the current handle + mov ah,MS_X_DUP2 ; get the function + jmp ms_call_dos ; call DOS, handle errors + + + Public _far_read +;--------- +_far_read: +;--------- + mov ah,MS_X_READ + jmp far_read_write + + Public _far_write +;---------- +_far_write: +;---------- + mov ah,MS_X_WRITE +far_read_write: + push bp + mov bp,sp + push ds + mov bx,4[bp] ; get file handle + lds dx,dword ptr 6[bp] ; get buffer address + mov cx,10[bp] ; get byte count + int DOS_INT ; call the DOS + jnc far_rw_ok ; skip if no error + neg ax ; else make it negative error code +far_rw_ok: + pop ds + pop bp + ret + + + Public _ms_x_read +;--------- +_ms_x_read: +;--------- + mov ah,MS_X_READ + jmp ms_read_write + + Public _ms_x_write +;---------- +_ms_x_write: +;---------- + mov ah,MS_X_WRITE +ms_read_write: + push bp + mov bp,sp + mov bx,4[bp] ; get file handle + mov dx,6[bp] ; get buffer address + mov cx,8[bp] ; get byte count + int DOS_INT ; call the DOS + jnc ms_rw_ok ; skip if no error + neg ax ; else make it negative error code +ms_rw_ok: + pop bp + ret + + Public _ms_x_unlink +;----------- +_ms_x_unlink: +;----------- + mov ah,MS_X_UNLINK + jmp ms_dx_call + + + Public _ms_x_lseek +;---------- +_ms_x_lseek: +;---------- + push bp + mov bp,sp + mov ah,MS_X_LSEEK ; get the function + mov bx,4[bp] ; get the file handle + mov dx,6[bp] ; get the offset + mov cx,8[bp] + mov al,10[bp] ; get the seek mode + int DOS_INT + jnc ms_lseek_ok ; skip if no errors + neg ax ; make error code negative + cwd ; sign extend to long +ms_lseek_ok: + mov bx,dx ; AX:BX = DRC long return + pop bp + ret + + Public _ms_x_ioctl +;---------- +_ms_x_ioctl: +;---------- + push bp + mov bp,sp + mov bx,4[bp] ; get our handle + mov ah,MS_X_IOCTL ; get IO Control function + mov al,0 ; get file/device status + int DOS_INT ; do INT 21h + jnc ms_x_i10 + neg ax +ms_x_i10: + pop bp ; + ret + + Public _ms_x_setdev +;------------ +_ms_x_setdev: +;------------ + push bp + mov bp, sp + mov bx, 4[bp] ; handle + mov dx, 6[bp] ; byte value to set + sub dh, dh + mov ah, MS_X_IOCTL + mov al, 1 + int DOS_INT + jnc ms_x_sd10 + neg ax +ms_x_sd10: + pop bp + ret + + Public _ms_x_chmod +;---------- +_ms_x_chmod: +;---------- + push bp + mov bp,sp + mov ah,MS_X_CHMOD + mov dx,4[bp] + mov cx,6[bp] + mov al,8[bp] + int DOS_INT + jnc ms_chmod_ok + neg ax ; make error code negative + jmp ms_chmod_ret +ms_chmod_ok: + sub ax,ax ; assume no error + cmp byte ptr 8[bp],0 ; getting attributes + jne ms_chmod_ret ; return ax = 0 if setting & no error + xchg ax,cx ; return ax = attrib otherwise +ms_chmod_ret: + pop bp + ret + + + Public _ms_x_curdir +;----------- +_ms_x_curdir: +;----------- + push bp + mov bp,sp + push si + mov si,6[bp] ; Get the buffer address and + mov byte ptr [si],0 ; put a zero in the first byte in + mov ah,MS_X_CURDIR ; the command is FAILED + push word ptr 4[bp] + call ms_dx_call + pop dx + pop si + pop bp + ret + + Public _ms_x_exit +;--------- +_ms_x_exit: +;--------- + push bp + mov bp,sp + +ifdef NETWARE + push es ; If this is Novell Netware and + mov ax,__psp ; the command processor is terminating + mov es,ax ; ie PSP_PARENT == PSP then do the + cmp ax,es:word ptr 16h ; special Novell Close down sequence + pop es + jnz ms_x_exit10 + + mov ax,7A00h ; Check for IPX being present using + int 2Fh ; the Multi-Plex Interrupt. + cmp al,0FFh + jz net_ware + +ms_x_exit10: +endif + mov al,04[bp] ; Get the Return Code + mov ah,MS_X_EXIT ; terminate process function + int DOS_INT ; call the DOS + pop bp + ret + +ifdef NETWARE +; +; The following routine attempts to clean-up after a Novell +; session. It does so in the following manner:- +; +; 1) Close all file handles (May be Networked !!) +; 2) Close all User Sockets +; 3) Remove all User Events from Internal lists +; 4) Use CDOS terminate function +; +net_ware: + mov ipx_offset,di + mov ipx_segment,es + + mov cx,20 ; Close all the possible handles + mov bx,0 ; used by the command processor +net_w05: ; in case any have been redirected + mov ah,MS_X_CLOSE ; accross the Network + int DOS_INT + inc bx + loop net_w05 + + mov si,dataOFFSET socket +net_w10: + mov cx,word ptr 02[si] ; Get the number of sockets to close + mov dx,word ptr 00[si] ; starting at Socket No. + jcxz net_w30 ; Terminate on a 0 Count + push si +net_w20: + push cx + push dx ; Save Count and Socket No. + xchg dl,dh ; Swap socket no to High/Low + mov bx,1 ; Close Socket Function + call ipx ; Close Socket. + pop dx + pop cx + inc dx ; Increment Socket No + loop net_w20 ; and Loop + pop si + add si,4 ; Point to next entry in the array + jmp net_w10 ; and repeat till count is 0 + +net_w30: ; All sockets have been closed + mov aes_esrseg,cs + mov ax,0FFFFh ; Create Special event with the + mov bx,7 ; maximum time delay + push ds + pop es ; Pass the address of the Special + mov si,dataOFFSET aes ; Event control block call the IPX + call ipx + +net_w40: + les si,aes_link ; Remove all entries from the Link + ; Which are not owned by the IPX +net_w50: + mov bx,es ; get the AES segment + cmp bx,ipx_segment ; and check for a match + jnz net_w60 ; Remove this entry + les si,es:dword ptr [si] ; get the next entry and try again + jmp short net_w50 + +net_w60: + or bx,si ; End of List + jz net_w70 ; Yes terminate our entry + mov bx,0006h ; Cancel this event + call ipx + jmp short net_w40 + +net_w70: + mov bx,0006h ; Cancel our event + push ds + pop es + mov si,dataOFFSET aes + call ipx + +net_exit: + mov dh,0 ; Standard Exit + mov dl,04[bp] ; With the supplied ExitCode + mov cx,P_EXITCODE ; Set the ExitCode for the Parent + int BDOS_INT + mov cx,P_TERMCPM ; Use a Concurrent Terminate Call + int BDOS_INT ; because Novell has taken over 4Ch + +aes_retf: ; Dummy AES routine + retf +endif + +; +; ms_x_expand(dstbuf, srcbuf) returns the full path of SRCBUF +; + Public _ms_x_expand +;----------- +_ms_x_expand: +;----------- + push bp + mov bp,sp + push si + push di + mov si,06[bp] ; Get the source String Address + mov di,04[bp] ; Get the destination string + mov byte ptr [di],0 ; address and force it to be a NULL + push ds + pop es ; ES:DI -> destination + mov ah,60h ; terminated string in case of errors + int DOS_INT + jc ms_exp_ret ; skip if error + xor ax,ax ; signal no errors +ms_exp_ret: + neg ax ; make error negative, 0 = 0 + pop di + pop si + pop bp + CRET 4 + + Public _ms_x_wait +;--------- +_ms_x_wait: ; retrieve child return code +;--------- + mov ah,MS_X_WAIT ; Top byte is abort code ie ^C + int DOS_INT ; Bottom byte is return code + ret + + Public _ms_x_first +;---------- +_ms_x_first: +;---------- + push bp + mov bp,sp + mov dx,8[bp] ; get DMA buffer address + mov ah,MS_F_DMAOFF + int DOS_INT + mov dx,4[bp] ; get ASCII string + mov cx,6[bp] ; get attribute + mov ah,MS_X_FIRST ; get search function + jmp ms_call_dos ; call DOS, check for errors + + Public _ms_x_next +;--------- +_ms_x_next: +;--------- + push bp + mov bp,sp + mov dx,4[bp] ; get DMA buffer address + mov ah,MS_F_DMAOFF + int DOS_INT + mov ah,MS_X_NEXT ; get the function + jmp ms_call_dos ; get DX, call DOS, handle errors + +ms_dx_call: ; call DOS with parameter in DX + push bp + mov bp,sp + mov dx,4[bp] +ms_call_dos: + int DOS_INT + jnc ms_dos_ok ; no carry = no error + neg ax ; else make it negative + jmp ms_dos_ret ; and return with error +ms_dos_ok: + sub ax,ax ; return 0 if no error +ms_dos_ret: + pop bp ; return 0 or negative error code + ret + + + Public _ms_x_rename +;----------- +_ms_x_rename: +;----------- + push bp + mov bp,sp + push di + push ds + pop es + mov ah,MS_X_RENAME + mov di,6[bp] ; ES:DI = new name + push word ptr 4[bp] ; make it look like DRC call + call ms_dx_call ; DX = 4[bp], call DOS, handle errors + pop di ; remove parameter + pop di + pop bp + ret + + Public _ms_x_datetime +; ret = _ms_x_datetime (gsflag, h, &time, &date); +;------------- +_ms_x_datetime: +;------------- + push bp + mov bp,sp + mov ah,MS_X_DATETIME ; set/get time stamp function + mov al,4[bp] ; get/set subfunction (0/1) + mov bx,8[bp] ; get address of time + mov cx,[bx] ; get time + mov bx,10[bp] ; get address of date + mov dx,[bx] ; get date + mov bx,6[bp] ; get handle + int DOS_INT ; call the DOS + jc ms_dt_ret ; skip if error + sub ax,ax ; signal no errors + cmp byte ptr 4[bp],0 ; geting time/date? + jne ms_dt_ret ; skip if setting + mov bx,8[bp] ; get time address + mov [bx],cx ; update time + mov bx,10[bp] ; get date address + mov [bx],dx ; update date +ms_dt_ret: + neg ax ; make error negative, 0 = 0 + pop bp + ret + + +; +; The following routines allow COMMAND.COM to manipulate +; the system time and date. Four functions are provided and +; these are MS_GETDATE, MS_SETDATE, MS_GETTIME and MS_SETTIME +; +; Date information is passed and return in a structure which +; has the following format. +; +; WORD Year (1980 - 2099) +; BYTE Month +; BYTE Day +; BYTE Day of the Week (Ignored on SET DATE) + + Public _ms_getdate +_ms_getdate: + push bp + mov bp,sp + mov ah,MS_T_GETDATE ; get the current date from DOS + int DOS_INT + mov bx,4[bp] ; and get the structure address + mov [bx],cx ; save the year + xchg dh,dl ; swap month and day + mov 2[bx],dx ; and save + mov 4[bx],al ; and finally save the day number + pop bp ; and exit + ret + + Public _ms_setdate +_ms_setdate: + push bp + mov bp,sp + mov bx,4[bp] ; and get the structure address + mov cx,0[bx] ; det the year + mov dx,2[bx] ; get the month and day + xchg dh,dl ; swap month and day + mov ah,MS_T_SETDATE ; set the current date + int DOS_INT + cbw ; 0000 = Ok and FFFF = Bad + pop bp ; and exit + ret + + +; Time information is passed and return in a structure which +; has the following format. +; +; BYTE Hours (0 - 23) +; BYTE Minutes (0 - 59) +; BYTE Seconds (0 - 59) +; BYTE Hundredths of a second (0 - 99) + + Public _ms_gettime +_ms_gettime: + push bp + mov bp,sp + mov ah,MS_T_GETTIME ; get the current date from DOS + int DOS_INT + mov bx,4[bp] ; and get the structure address + xchg cl,ch + mov [bx],cx ; save the hours and minutes + xchg dh,dl + mov 2[bx],dx ; save seconds and hundredths + pop bp ; and exit + ret + + Public _ms_settime +_ms_settime: + push bp + mov bp,sp + mov bx,4[bp] ; and get the structure address + mov cx,[bx] ; get the hours and minutes + xchg cl,ch + mov dx,2[bx] ; get seconds and hundredths + xchg dh,dl + mov ah,MS_T_SETTIME ; get the current date from DOS + int DOS_INT + cbw ; 0000 = Ok and FFFF = Bad + pop bp ; and exit + ret + + Public _ms_idle_ptr +;------------ +_ms_idle_ptr: +;------------ + push es + push si + push di + mov ax, 4458h + int DOS_INT ; ptr in ES:AX + mov dx, es + pop di + pop si + pop es + ret + + Public _ms_switchar +;----------- +_ms_switchar: +;----------- + mov ax,3700h + int DOS_INT + sub ah,ah + mov al,dl + ret +if 0 + Public _ms_p_getpsp +;----------- +_ms_p_getpsp: +;----------- + mov ah,51h ; Note: SeCRET DOS 2.x entry + int DOS_INT + xchg ax,bx + ret +endif + Public _ms_f_verify +;----------- +_ms_f_verify: +;----------- + push bp + mov bp,sp + mov ah,MS_F_VERIFY + mov al,4[bp] ;get 0/1 al parameter + int DOS_INT + pop bp + ret + + Public _ms_f_getverify +;-------------- +_ms_f_getverify: +;-------------- + mov ah,MS_F_GETVERIFY + int DOS_INT + cbw + ret + +ifndef CDOSTMP + Public _ms_f_parse +;----------- +_ms_f_parse: +;----------- + push bp + mov bp, sp + push es + push si + push di + + push ds + pop es + mov di, 4[bp] ; fcb + mov si, 6[bp] ; filename + mov al, 8[bp] ; flags + mov ah, MS_F_PARSE + int DOS_INT + + cbw ; return code in ax + pop di + pop si + pop es + pop bp + ret + + Public _ms_f_delete +;------------ +_ms_f_delete: +;------------ + push bp + mov bp, sp + mov dx, 4[bp] ; fcb + mov ah, MS_F_DELETE + int DOS_INT + + cbw ; return code + pop bp + ret +endif +; +; The SET BREAK function returns the previous Break Flag Status +; + Public _ms_set_break +;------------ +_ms_set_break: +;------------ + push bp + mov bp,sp + mov dl,04[bp] + mov ax,(MS_S_BREAK SHL 8) + 2 + int DOS_INT + pop bp + mov al,dl + cbw + ret + +if 0 + Public _ms_get_break +;------------ +_ms_get_break: +;------------ + mov ax,MS_S_BREAK SHL 8 + int DOS_INT + mov al,dl + cbw + ret +endif + +; +; mem_alloc(BYTE FAR * NEAR * bufaddr, UWORD * bufsize, UWORD min, UWORD max); +; +; max 10[bp] +; min 08[bp] +; bufsize 06[bp] +; buffadr 04[bp] +; + Public _mem_alloc +;--------- +_mem_alloc: +;--------- + push bp + mov bp,sp + mov bx,10[bp] ; Start with request maximum size +mem_all10: + mov ah,MS_M_ALLOC ; Attempt to allocate the maximum + int DOS_INT ; memory requested by the user. + jnc mem_all20 ; Allocation OK + cmp bx,08[bp] ; Is this less than the requested + jae mem_all10 ; No then allocate this amount + xor ax,ax ; Force the Buffer address and Buffer + mov bx,ax ; Size to Zero + +mem_all20: + mov cx,bx ; Save the Buffer Size + mov bx,04[bp] ; Update the Buffer Address + mov word ptr 00[bx],0 ; Offset 0 + mov word ptr 02[bx],ax ; Segment AX + mov bx,06[bp] ; Now Update the Buffer Size + mov word ptr 00[bx],cx ; and return to the caller + pop bp + ret +; +; mem_free(BYTE FAR * NEAR * bufaddr); +; +; buffadr 04[bp] +; + Public _mem_free +;--------- +_mem_free: +;--------- + push bp + mov bp,sp + xor ax,ax + mov bx,04[bp] ; Get the Buffer Pointer address + xchg ax,word ptr 02[bx] ; and from this the segment of the + cmp ax,0 ; allocated memory. If the memory + jz mem_free10 ; has already been freed the quit + push es ; Otherwise Free the Memory + mov es,ax + mov ah,MS_M_FREE + int DOS_INT + pop es +mem_free10: + pop bp + ret + + Public _msdos +;------- +_msdos: +;------- + push bp + mov bp,sp + push si + push di + + mov ah,4[bp] + mov dx,6[bp] + int DOS_INT + + pop di + pop si + pop bp + ret + + Public _ioctl_ver +;--------- +_ioctl_ver: +;--------- +ifdef DOSPLUS + mov ax,4452h ; Get DOS Plus BDOS version Number +else + mov ax,4451h ; Get Concurrent BDOS Version +endif + int DOS_INT ; Real DOS returns with Carry Set + jc cdos_v10 + and ax,not 0200h ; Reset the Networking Bit + ret +cdos_v10: + xor ax,ax + ret + +ifdef DOSPLUS +; +; Get CodePage information form the system. Return both the currently +; active CodePage and the System CodePage. +; +; ms_x_getcp(&globalcp, &systemcp); +; + Public _ms_x_getcp +;----------- +_ms_x_getcp: +;----------- + push bp + mov bp,sp + mov ax,MS_X_GETCP ; Get the CodePage Information + int DOS_INT ; and return an error if not + jc ms_x_getcp10 ; supported. + mov ax,bx ; Now update the callers + mov bx,04[bp] ; Global and System Codepage + mov word ptr [bx],ax ; variables + mov bx,06[bp] + mov word ptr [bx],dx + xor ax,ax + +ms_x_getcp10: + neg ax ; Negate the error code has + pop bp ; no effect on 0 + ret +; +; Change the current CodePage +; +; ms_x_setcp(globalcp); +; + Public _ms_x_setcp +;----------- +_ms_x_setcp: +;----------- + push bp + mov bp,sp + mov bx,04[bp] ; Get the requested CodePage + mov ax,MS_X_SETCP ; and make this the default + int DOS_INT + jc ms_x_getcp10 + xor ax,ax + pop bp + ret +endif +endif + +ifdef CDOSTMP + + + Public _ms_drv_set +;----------- +_ms_drv_set: +;----------- + push bp + mov bp,sp + mov dl,04[bp] ; Get the Specified drive + or dl,80h ; Prevent any Select Errors + mov cl,DRV_SET ; and go select the bugger + int BDOS_INT + pop bp + ret + + Public _ms_drv_get +;----------- +_ms_drv_get: +;----------- + mov cl,DRV_GET ; Return the Currently selected + int BDOS_INT ; disk drive + cbw + ret + + Public _ms_drv_space +;------------ +_ms_drv_space: +;------------ +; +; ret = _ms_drv_space (drive, &free, &secsiz, &nclust); +; where: drive = 0, 1-16 is drive to use +; free = free cluster count +; secsiz = bytes/sector +; nclust = clusters/disk +; ret = sectors/cluster -or- (0xFFFFh) + + push bp + mov bp,sp + mov al,OK_RF ; Retry or Fail + call fdos_retry + mov FD_FUNC, FD_DISKINFO + mov ax,04[bp] + mov FD_DRIVE,ax + call fdos_entry + or ax,ax ; Check for Errors + mov ax,0FFFFh + jnz ms_drv_exit ; Error Exit + + push es ; Save ES + push di + les di,FD_DPB ; Get the DPB Address + + mov ax,es:DDSC_FREE[di] ; Get the number of free + mov bx,06[bp] ; clusters on the drive + mov [bx],ax + + mov ax,es:DDSC_SECSIZE[di] ; Get the Physical Sector Size + mov bx,08[bp] ; in bytes + mov [bx],ax + + mov ax,es:DDSC_NCLSTRS[di] ; Get the disk size in + mov bx,10[bp] ; clusters and save in DX + mov [bx],ax + + mov al,es:DDSC_CLMSK[di] ; Get the sectors per Cluster -1 + cbw ; and save in AX + inc ax + pop di + pop es + +ms_drv_exit: + pop bp + CRET 8 + + Public _ms_s_country +;------------ +_ms_s_country: +;------------ + push bp + mov bp,sp + mov ax,04[bp] ; Get the data Block Offset + + mov cd_country,0 ; Get the Current Country + mov cd_codepage,0 ; Current CodePage + mov cd_table,0 ; Country Information + mov cd_offset,ax ; Save the Buffer Offset + mov cd_segment,ds ; and the Buffer Segment + + mov dx,dataOFFSET country_data + mov cl,S_GETCOUNTRY ; Get the country information + int BDOS_INT ; and return the current country + pop bp ; code to the caller + CRET 2 + + Public _ms_x_mkdir +;---------- +_ms_x_mkdir: +;---------- + push bp + mov bp,sp + mov al,OK_RIF ; Retry, Ignore or Fail + call fdos_retry + mov FD_FUNC,FD_MKDIR ; Make Directory + +mkdir_10: + mov ax,04[bp] + mov FD_NAMEOFF,ax + mov FD_NAMESEG,ds + call fdos_entry + pop bp + CRET 2 + + Public _ms_x_rmdir +;---------- +_ms_x_rmdir: +;---------- + push bp + mov bp,sp + mov al,OK_RIF ; Retry, Ignore or Fail + call fdos_retry + mov FD_FUNC,FD_RMDIR + jmp mkdir_10 + + Public _ms_x_chdir +;---------- +_ms_x_chdir: +;---------- + push bp + mov bp,sp + mov al,OK_RF ; Retry or Fail + call fdos_retry + mov FD_FUNC,FD_CHDIR + jmp mkdir_10 + + Public _ms_x_creat +;---------- +_ms_x_creat: +;---------- + push bp + mov bp,sp + mov al,OK_RF ; Retry or Fail + call fdos_retry + mov FD_FUNC,FD_CREAT + jmp ms_open_creat + + + Public _ms_x_open +;--------- +_ms_x_open: +;--------- + push bp + mov bp,sp + mov al,OK_RF ; Retry or Fail + call fdos_retry + mov FD_FUNC,FD_OPEN +ms_open_creat: + mov ax,4[bp] + mov FD_NAMEOFF,ax + mov FD_NAMESEG,ds + mov ax,6[bp] ; get mode for new file (CREAT) + mov FD_MODE,ax ; or the OPEN mode + call fdos_entry ; Call the FDOS and return either + pop bp ; a handle or error code + CRET 4 + + Public _ms_x_close +;---------- +_ms_x_close: +;---------- + push bp + mov bp,sp + mov al,OK_RIF ; Retry, Ignore or Fail + call fdos_retry + mov ax,4[bp] ; get the open handle + mov FD_FUNC,FD_CLOSE + mov FD_HANDLE,ax + call fdos_entry + pop bp + CRET 2 + + Public _ms_x_unique +;---------- +_ms_x_unique: +;---------- + push bp + mov bp,sp + mov al,OK_RF ; Retry or Fail + call fdos_retry + mov FD_FUNC,FD_MKTEMP + jmp ms_open_creat + + Public _ms_x_fdup +;---------- +_ms_x_fdup: +;---------- + push bp + mov bp,sp + mov al,OK_RIF ; Retry, Ignore or Fail + call fdos_retry + mov FD_FUNC,FD_FDUP + mov ax,4[bp] ; get the destination handle + mov FD_NEWHND,ax + mov ax,6[bp] ; Get the current handle + mov FD_HANDLE,ax + call fdos_entry + pop bp + CRET 4 + + Public _far_read +;--------- +_far_read: +;--------- + push bp + mov bp,sp + mov al,OK_RF ; Retry or Fail + call fdos_retry + mov FD_FUNC,FD_READ + jmp far_read_write + + Public _far_write +;---------- +_far_write: +;---------- + push bp + mov bp,sp + mov al,OK_RIF ; Retry, Ignore or Fail + call fdos_retry + mov FD_FUNC,FD_WRITE + +far_read_write: + mov ax,4[bp] ; get file handle + mov FD_HANDLE,ax + mov ax,6[bp] ; get buffer offset address + mov FD_BUFOFF,ax + mov ax,8[bp] ; get buffer Segment address + mov FD_BUFSEG,ax + mov ax,10[bp] ; get byte count + mov FD_COUNT,ax + call fdos_entry + or ax,ax + jnz far_rw_fail + mov ax,FD_COUNT ; Get the Byte Count +far_rw_fail: + pop bp + CRET 6 + + Public _ms_x_read +;--------- +_ms_x_read: +;--------- + push bp + mov bp,sp + mov al,OK_RF ; Retry or Fail + call fdos_retry + mov FD_FUNC,FD_READ + jmp ms_read_write + + Public _ms_x_write +;---------- +_ms_x_write: +;---------- + push bp + mov bp,sp + mov al,OK_RIF ; Retry, Ignore or Fail + call fdos_retry + mov FD_FUNC,FD_WRITE + +ms_read_write: + mov ax,4[bp] ; get file handle + mov FD_HANDLE,ax + mov ax,6[bp] ; get buffer address + mov FD_BUFOFF,ax + mov FD_BUFSEG,ds + mov ax,8[bp] ; get byte count + mov FD_COUNT,ax + call fdos_entry + or ax,ax + jnz ms_rw_fail + mov ax,FD_COUNT ; Get the Byte Count +ms_rw_fail: + pop bp + CRET 6 + + Public _ms_x_unlink +;----------- +_ms_x_unlink: +;----------- + push bp + mov bp,sp + mov al,OK_RIF ; Retry, Ignore or Fail + call fdos_retry + mov FD_FUNC,FD_UNLINK + jmp mkdir_10 + + + Public _ms_x_lseek +;---------- +_ms_x_lseek: +;---------- + push bp + mov bp,sp + mov al,OK_RIF ; Retry, Ignore or Fail + call fdos_retry + mov FD_FUNC,FD_LSEEK ; get the function + mov ax,4[bp] ; get the file handle + mov FD_HANDLE,ax + mov ax,6[bp] ; get the offset + mov word ptr FD_OFFSET+0,ax + mov ax,8[bp] + mov word ptr FD_OFFSET+2,ax + mov ax,10[bp] ; get the seek mode + mov FD_METHOD,ax + call fdos_entry + cwd + or ax,ax + jnz ms_lseek_fail ; skip if errors + mov ax,word ptr FD_OFFSET+0 ; Return the New Location + mov dx,word ptr FD_OFFSET+2 +ms_lseek_fail: + mov bx,dx ; AX:BX = DRC long return + pop bp + CRET 8 + + + Public _ms_x_ioctl +;---------- +_ms_x_ioctl: +;---------- + push bp + mov bp,sp + mov al,OK_RF ; Retry or Fail + call fdos_retry + mov ax,4[bp] ; get Enquiry Handle + mov FD_FUNC,FD_IOCTL ; Use the IOCTL function + mov FD_HANDLE,ax ; For Handle AX + mov FD_CTLFUNC,0000 ; Get the Handle Status + mov FD_CTLSTAT,0 ; Invalidate CTLSTAT + call fdos_entry ; Call the FDOS + mov ax,FD_CTLSTAT ; and return the STATUS + pop bp + CRET 2 + + Public _ms_x_setdev +;------------ +_ms_x_setdev: +;------------ + push bp + mov bp,sp + mov al,OK_RF ; Retry or Fail + call fdos_retry + mov ax,4[bp] ; get Handle + mov FD_HANDLE,ax + mov FD_FUNC,FD_IOCTL ; Use the IOCTL function + mov FD_CTLFUNC,1 ; Set device info + mov ax, 6[bp] ; status to set + sub ah, ah + mov FD_CTLSTAT,ax + call fdos_entry ; Call the FDOS + mov ax,FD_CTLSTAT ; and return the STATUS + pop bp + CRET 2 + + Public _ms_x_chmod +;---------- +_ms_x_chmod: ; ms_x_chmod(path, attrib, get/set) +;---------- + push bp + mov bp,sp + mov al,OK_RIF ; Retry, Ignore or Fail + call fdos_retry + mov FD_FUNC,FD_CHMOD + mov ax,4[bp] ; Get the FileName + mov FD_NAMEOFF,ax + mov FD_NAMESEG,ds + mov ax,6[bp] ; Get the Required Attributes + mov FD_ATTRIB,ax + mov ax,8[bp] ; Finally Get the GET/SET flag + mov FD_FLAG,ax + call fdos_entry ; Returns with AX equal to the + or ax,ax ; error code or with the file + js chmod10 ; attributes. + mov ax,FD_ATTRIB +chmod10: + pop bp + CRET 6 + + + Public _ms_x_curdir +;----------- +_ms_x_curdir: +;----------- + push bp + mov bp,sp + mov al,OK_RF ; Retry or Fail + call fdos_retry + mov FD_FUNC,FD_GETDIR + mov ax,04[bp] ; Get the drive + mov FD_DRIVE,ax + mov bx,06[bp] ; and then the path + mov byte ptr [bx],0 ; Put a Zero byte in the buffer in + mov FD_PATHOFF,bx ; case the command fails and the + mov FD_PATHSEG,ds ; user selects the FAIL Option + call fdos_entry + pop bp + CRET 4 + +; +; ms_x_expand(dstbuf, srcbuf) returns the full path of SRCBUF +; + Public _ms_x_expand +;----------- +_ms_x_expand: +;----------- + push bp + mov bp,sp + mov al,OK_RF ; Retry or Fail + call fdos_retry + mov FD_FUNC,FD_EXPAND + mov ax,06[bp] ; Get Source Buffer Offset + mov FD_ONAMEOFF,ax + mov FD_ONAMESEG,ds + mov bx,04[bp] ; Get the destination string + mov byte ptr [bx],0 ; address and force it to be a NULL + mov FD_NNAMEOFF,bx ; terminated string in case of errors + mov FD_NNAMESEG,ds + call fdos_entry + pop bp + CRET 4 + + Public _ms_x_wait +;--------- +_ms_x_wait: ; retrieve child return code +;--------- + mov cl,P_EXITCODE ; Return the Exit Code + mov dx,0FFFFh ; Get the Exit Code + int BDOS_INT + CRET 0 + + Public _ms_x_first +;---------- +_ms_x_first: +;---------- + push bp + mov bp,sp + + mov dx,8[bp] ; get DMA buffer address + mov cl,F_DMAOFF + call bdos_entry + + mov dx,ds ;##jc## + mov cl,F_DMASEG ;##jc## + call bdos_entry ;##jc## + + mov al,OK_RF ; Retry or Fail + call fdos_retry + + mov FD_FUNC,FD_FFIRST ; Search First + mov ax,04[bp] ; Get the FileName + mov FD_NAMEOFF,ax + mov FD_NAMESEG,ds + mov ax,06[bp] ; Get the Attributes + mov FD_ATTRIB,ax + mov FD_COUNT, 0 ; Search for a File at a time + call fdos_entry + cmp ax,1 ; Did we match 1 entry + jnz ms_x_f10 ; No so return Error Code + mov ax,0 ; Return Zero on sucess +ms_x_f10: + pop bp + CRET 6 + + Public _ms_x_next +;--------- +_ms_x_next: +;--------- + push bp + mov bp,sp + + mov dx,4[bp] ; get DMA buffer address + mov cl,F_DMAOFF + call bdos_entry + + mov dx,ds ;##jc## + mov cl,F_DMASEG ;##jc## + call bdos_entry ;##jc## + + mov al,OK_RF ; Retry or Fail + call fdos_retry + + mov FD_FUNC,FD_FNEXT ; Search Next + mov FD_NEXTCNT, 0 ; Search for a File at a time + call fdos_entry + cmp ax,1 ; Did we match 1 entry + jnz ms_x_n0 ; No so return Error Code + mov ax,0 ; Return Zero on sucess +ms_x_n0: + pop bp + CRET 2 + + + Public _ms_x_rename +;----------- +_ms_x_rename: +;----------- + push bp + mov bp,sp + mov al,OK_RIF ; Retry, Ignore or Fail + call fdos_retry + mov FD_FUNC,FD_RENAME + mov ax,04[bp] ; Get the Old Name + mov FD_ONAMEOFF,ax + mov FD_ONAMESEG,ds + mov ax,06[bp] ; Get the New Name + mov FD_NNAMEOFF,ax + mov FD_NNAMESEG,ds + call fdos_entry + pop bp + CRET 4 + + Public _ms_x_datetime +;------------- +_ms_x_datetime: ; ms_x_datetime (gsflag, h, &time, &date); +;------------- + push bp + mov bp,sp + mov al,OK_RIF ; Retry, Ignore or Fail + call fdos_retry + mov FD_FUNC,FD_DATETIME ; set/get Time Stamp + mov ax,4[bp] ; get/set subfunction (0/1) + mov FD_SFLAG,ax + mov ax,6[bp] ; get handle + mov FD_HANDLE,ax + mov bx,8[bp] ; get address of time + mov ax,[bx] ; get time + mov FD_TIME,ax ; and Save + mov bx,10[bp] ; get address of date + mov ax,[bx] ; get date + mov FD_DATE,ax + call fdos_entry + or ax,ax ; Skip if Failed + jnz ms_dt_ret + mov ax,FD_TIME + mov bx,8[bp] ; get time address + mov [bx],ax ; update time + mov ax,FD_DATE + mov bx,10[bp] ; get date address + mov [bx],ax ; update date + xor ax,ax +ms_dt_ret: + pop bp + CRET 8 + + +; +; The following routines allow COMMAND.COM to manipulate +; the system time and date. Four functions are provided and +; these are GETDATE, SETDATE, GETTIME and SETTIME +; +; Date information is passed and return in a structure which +; has the following format. +; +; WORD Year (1980 - 2099) +; BYTE Month +; BYTE Day +; BYTE Day of the Week (Ignored on SET DATE) + + Public _ms_getdate +;----------- +_ms_getdate: +;----------- + push bp + mov bp,sp + mov dx,04[bp] ; Get the structure address + mov cl,T_GETDATE ; and call the BDOS + call bdos_entry + pop bp + CRET 2 + + Public _ms_setdate +;---------- +_ms_setdate: +;---------- + push bp + mov bp,sp + mov dx,4[bp] ; and get the structure address + mov cl,T_SETDATE ; and call the BDOS to do the work + call bdos_entry ; Return 0 Good and FFFF Bad + pop bp + CRET 2 + + +; Time information is passed and return in a structure which +; has the following format. +; +; BYTE Hours (0 - 23) +; BYTE Minutes (0 - 59) +; BYTE Seconds (0 - 59) +; BYTE Hundredths of a second (0 - 99) + + Public _ms_gettime +;---------- +_ms_gettime: +;---------- + push bp + mov bp,sp + mov dx,04[bp] ; Get the Time Structure address + mov cl,T_GETTIME ; and call the OS + call bdos_entry + pop bp + CRET 2 + + Public _ms_settime +;---------- +_ms_settime: +;---------- + push bp + mov bp,sp + mov dx,4[bp] ; and get the structure address + mov cl,T_SETTIME ; and call the BDOS SET Time Function + call bdos_entry ; Return 0 Good and FFFF Bad + pop bp + CRET 2 + + Public _ms_f_verify +;----------- +_ms_f_verify: +;----------- + push bp + mov bp,sp + push es + mov ax,04[bp] ; Get the required state + les bx,_pd ; Update the Verify flag in + and es:P_SFLAG[bx],not PSF_VERIFY ; current PD + or ax,ax ; Set the Flag + jz ms_fv10 ; No + or es:P_SFLAG[bx],PSF_VERIFY ; Flag set in PD +ms_fv10: + pop es + pop bp + ret + + Public _ms_f_getverify +;-------------- +_ms_f_getverify: +;-------------- + push es + xor ax,ax ; Assume the flag is RESET + les bx,_pd ; now test the state of the + test es:P_SFLAG[bx],PSF_VERIFY ; flag in the current PD + jz ms_fgv10 ; Verify = OFF + inc ax ; Verify = ON +ms_fgv10: + pop es + ret + +; +; mem_alloc(BYTE FAR * NEAR * bufaddr, UWORD * bufsize, UWORD min, UWORD max); +; +; max 10[bp] +; min 08[bp] +; bufsize 06[bp] +; buffadr 04[bp] +; + Public _mem_alloc +;--------- +_mem_alloc: +;--------- + push bp + mov bp,sp + + mov mpb_start,0 + mov ax,08[bp] ; Get the Minimum and Maximum values + mov mpb_min,ax ; and fill in the parameter block + mov ax,10[bp] + mov mpb_max,ax + mov mpb_pdadr,0 + mov mpb_flags,0 + + mov cx,M_ALLOC ; Call the Concurrent Allocate function + mov dx,dataOFFSET mpb_start ; + call bdos_entry + xor cx,cx ; Assume that the function fails + mov dx,cx ; and zero the start and size fields + cmp ax,0 + jnz mem_all10 + mov cx,mpb_min ; Get the Allocation Size + mov dx,mpb_start ; and the starting segment + +mem_all10: + mov bx,04[bp] ; Update the Buffer Address + mov word ptr 00[bx],0 ; Offset 0 + mov word ptr 02[bx],dx ; Segment DX + mov bx,06[bp] ; Now Update the Buffer Size + mov word ptr 00[bx],cx ; and return to the caller + pop bp + ret +; +; mem_free(BYTE FAR * NEAR * bufaddr); +; +; buffadr 04[bp] +; + Public _mem_free +;--------- +_mem_free: +;--------- + push bp + mov bp,sp + xor ax,ax + mov bx,04[bp] ; Get the Buffer Pointer address + xchg ax,word ptr 02[bx] ; and from this the segment of the + cmp ax,0 ; allocated memory. If the memory + jz mem_free10 ; has already been freed the quit + mov mfpb_start,ax ; Otherwise Free the Memory + mov mfpb_res,0 + mov cx,M_FREE + mov dx,dataOFFSET mfpb_start + call bdos_entry + +mem_free10: + pop bp + ret +; +; findfile(BYTE *loadpath, UWORD *loadtype) +; + Public _findfile +_findfile: + push bp + mov bp,sp + mov al,OK_RF ; Retry, Ignore or Fail + call fdos_retry + mov ax,word ptr 04[bp] + mov exec_pathoff,ax + mov exec_pathseg,ds + mov cx,P_PATH + mov dx,dataOFFSET exec_block + call ppath_entry + or ax,ax + jnz ff_error + mov al,exec_filetype + cbw + mov bx,word ptr 06[bp] + mov word ptr [bx],ax + xor ax,ax +ff_error: + pop bp + ret + +; +fdos_retry: + xor ah,ah + mov valid,ax ; Save the Valid Error responses + pop retry_ip ; Get the return Address + mov retry_sp,sp ; and Stack Pointer + jmp retry_ip +; +; FDOS_ENTRY is an internal function entry point which makes the +; F_DOS function call. As the F_DOS data area used by COMMAND.COM +; is always FDOS_DATA. +; +; WORD PASCAL critical_error(error, valid, drive, mode, server); +; +; critical_error will return an WORD response which (R,I,A,F) +; after displaying the appropriate error message and get the +; correct response from the user. +; +fdos_entry: + mov cl,F_DOS + mov dx,dataOFFSET fdos_data +ppath_entry: + call bdos_entry + cmp ax,ED_LASTERROR ; Did an Error Occur + jb fdos_exit ; No So Exit OK + cmp crit_flg,TRUE ; Already in handler + jz fdos_exit ; Yes Skip Critical Error + cmp ax,ED_PROTECT ; Is this a Physical Error + jg fdos_exit ; if so then simulate a + cmp ax,ED_GENFAIL ; Critical Error by calling + jge fdos_e05 ; the COMMAND routine Critical + ; error + cmp ax,ED_NETPWD ; Now check for DR-NET errors + jg fdos_exit ; if so then simulate a + cmp ax,ED_NETLOG ; Critical Error by calling + jge fdos_e05 ; the COMMAND routine Critical + ; error +fdos_exit: + ret + +fdos_e05: + push retry_ip ; Save Retry IP and SP and valid + push retry_sp ; responses + push valid + mov crit_flg,TRUE ; Start Critical Section + mov cx,es ; Save the Segment Regsiter + push ax ; Save the Error Code + push valid ; Save the Valid Responses (R,I,F) + les bx,_pd ; Get the PD address + mov es,es:P_UDA[bx] ; and then the UDA address + xor ah,ah ; Zero the top byte of AX and + mov al,es:byte ptr 15h ;;U_ERR_DRV ; Get the Failing Drive + push ax ; Save on the Stack + mov al,es:byte ptr 14h ;;U_ERR_RW ; Get the Error Mode + push ax ; and Save + + mov ax,00FFH ; Default Server NO is (INVALID) + les bx,_pd ; Get the PD address Again + mov bx,es:P_NDA[bx] ; and then the NDA address + cmp bx,0 ; Are we attached to DR-NET + jz fdos_e08 ; NO + mov es,bx ; ES -> DR-Net NDA + mov al,es:byte ptr 0Ch ;; NDA_CXRTN + +fdos_e08: + push ax ; Pass the DR-NET Server No. + mov es,cx ; Restore ES + call CRITICAL_ERR ; Handle the Critical Error. Parameters + ; are removed by the CALLEE + mov crit_flg,FALSE ; Critical Section complete + pop valid ; Restore our original RETRY IP + pop retry_sp ; and SP values which have been + pop retry_ip ; corrupted by the "CRITICAL_ERROR" + ; routine during message printing + cmp ax,0 ; Ignore the Error + jz fdos_exit ; Then Exit with no Error + + cmp ax,1 ; Retry the Operation + jnz fdos_e10 ; using information saved by FDOS_RETRY + mov sp,retry_sp ; Reset the Stack Pointer + jmp retry_ip ; and retry the Operation + +fdos_e10: + cmp ax,3 ; FAIL this function + mov ax,ED_FAIL ; Fail the function + jz fdos_exit ; Yes otherwise ABORT + + call _int_break ; Simulate a Control C to terminate + ; We are never coming back +; +; BDOS_ENTRY is the usual method of calling the Operating System. +; In order to provide a DOS compatible environment this function. +; does Control-C checking on function exit. +; +bdos_entry: + int BDOS_INT + push es + les bx,_pd ; Get our process descriptor address + test es:P_SFLAG[bx],PSF_CTLC ; Check if a Control-C has been typed + jnz bdos_e10 ; Jump to Abort Handler + mov bx,ax ; Restore BX and Return. + pop es + ret + +bdos_e10: + and es:P_SFLAG[bx],not PSF_CTLC + pop es +bdos_e20: + mov cl,C_RAWIO ; Flush the Character buffer until + mov dl,0FFh ; Return the character or 00 if queue + int BDOS_INT ; is empty. Repeat till the Keyboard + or al,al ; Buffer has been flushed + jnz bdos_e20 + push ds + push cs + pop ds + mov cl,C_WRITESTR + mov dx,offset break_str ; echo ^C to screen + int BDOS_INT + pop ds + call _int_break ; Place the Control Break Code on the + ; Stack and the call the error handler + ; ** We will never return ** + +break_str db '^C$' + +endif + +ifndef DOSPLUS + Public __BDOS +;------- +__BDOS: +;------- + push bp + mov bp,sp + push si + push di + mov cl,4[bp] + mov dx,6[bp] + int BDOS_INT + pop di + pop si + pop bp + ret +; +endif + +ifdef DOSPLUS +ifndef EXT_SUBST + Public _physical_drvs ; Physical Drives returns a LONG +_physical_drvs: ; Vector with bits set for every drive + mov ax,0 ; start with drive A: + mov cx,16 ; check the first 16 drives + mov bx,0 +p_d10: + push ax ; pass drive no. to _physical_drive + call _physical_drive ; call it + cmp ax,0 ; check return value + pop ax ; restore ax + jz p_d20 ; if zero skip setting the bit in + or bx,1 ; the bitmap +p_d20: + ror bx,1 ; shift bitmap right + inc ax ; next drive + loop p_d10 ; Loop 16 Times + mov cx,10 ; Finally check the last 10 drives + mov dx,0 +p_d30: + push ax ; pass drive no. to _physical_drive + call _physical_drive ; call it + cmp ax,0 ; check return val + pop ax ; restore ax + jz p_d40 ; id zero skip setting the bit in + or dx,1 ; the bitmap +p_d40: + ror dx,1 ; shift bitmap right + inc ax ; next drive + loop p_d30 ; Loop 10 Times + + mov cl,6 ; Now rotate the contents of + ror dx,cl ; DX 6 more times for correct + ; alignment of the Physical Drive Vector + mov ax,bx + mov bx,dx ; Return the long value in both + ; AX:BX and AX:DX + ret + + Public _logical_drvs ; Logical Drives returns a LONG +_logical_drvs: ; vector with bits set for every + + mov cx,16 ; check the first 16 drives + mov ax,0 ; start with drive A: + mov bx,ax + +l_d10: + push ax ; pass the drive to _logical_drive + call _logical_drive ; call it + cmp ax,0 ; check return value + pop ax ; restore ax + jz l_d20 ; skip if zero return + or bx,1 ; set bit in bitmap +l_d20: + ror bx,1 ; shift bitmap right + inc ax ; next drive + loop l_d10 ; Loop 16 Times + + mov cx,10 ; Finally check the last 10 drives + mov dx,0 +l_d30: + push ax ; pass the drive to _logical_drive + call _logical_drive ; call it + cmp ax,0 ; check return value + pop ax ; restore ax + jz l_d40 ; skip if zero return + or dx,1 ; set bit in bitmap +l_d40: + ror dx,1 ; shift bitmap right + inc ax ; next drive + loop l_d30 ; Loop 10 Times + + mov cl,6 ; Now rotate the contents of + ror dx,cl ; DX 6 more times for correct + ; alignment of bits + mov ax,bx + mov bx,dx ; Return the long value in both + ret ; AX:BX and AX:DX + + Public _network_drvs ; Network Drives returns a LONG +_network_drvs: ; vector with bits set for every drive + xor ax,ax ; Start with BX:AX as + mov bx,ax ; zeros. + mov cx,'Z'-'A' ; We look at drives A-Z +n_d10: + add ax,ax ; we move the dword vector + adc bx,bx ; one place left + push ax + push bx ; save the vector + mov ah,MS_X_IOCTL + mov al,9 ; is device local ? + mov bl,cl ; drive number in BL + int DOS_INT + pop bx + pop ax ; recover the vector + jc n_d20 ; if an error skip network bit + test dx,1000h ; is device local ? + jz n_d20 ; if not then + or ax,1 ; set bit for this drive +n_d20: + loop n_d10 + mov dx,bx ; long value in both AX:BX and AX:DX + ret + public _physical_drive +_physical_drive PROC NEAR + +; BOOLEAN physical_drive(WORD); +; returns true if given drive (0-25) is physical. +; + push bp + mov bp,sp + push ds + push es + push si + push di + push dx + push cx + push bx + + mov bx,4[bp] ; get the drive number + inc bx ; A=1, B=2, etc + mov ax,4409h ; IOCTL Network/Local + int 21h ; do it + jc not_phys ; carry means invalid drive + and dx,1000h ; + cmp dx,0 + jne not_phys ; its a network drive + + mov ax,cs + mov ds,ax + mov es,ax + mov si,offset func60_in + mov di,offset func60_out + mov ax,4[bp] ; insert drive letter in input string + add al,'A' + mov [si],al ; + mov ah,60h ; Expand Path string + int 21h ; do it + jc not_phys ; carry set means invalid drive + + mov ax,4[bp] ; if drive letter changes then drive is + add al,'A' ; substed + cmp al,cs:[func60_out] + jne not_phys + + mov ax,-1 + jmp phys_exit +not_phys: + mov ax,0 +phys_exit: + pop bx + pop cx + pop dx + pop di + pop si + pop es + pop ds + pop bp + ret + +func60_in db "d:con",0 +func60_out db 0,0,0,0,0,0,0,0,0,0 + +_physical_drive ENDP + +; +; This function translates a logical to physical drive. +; + Public _pdrive +;------ +_pdrive: +;------ + push bp + mov bp,sp + push ds + push es + push si + push di + + mov ax,cs + mov ds,ax + mov es,ax + mov si,offset func60_in + mov di,offset func60_out + mov ax,4[bp] ; insert drive letter in input string + add al,'A' + mov [si],al + mov ah,60h ; Expand Path string + int 21h ; do it + mov ax,4[bp] ; assume invalid, hence no change + jc pdrive_exit ; carry set means invalid drive + mov al,cs:[func60_out] + sub al,'A' +pdrive_exit: + pop di + pop si + pop es + pop ds + pop bp + CRET 2 + + public _logical_drive +_logical_drive PROC NEAR + +; BOOLEAN logical_drive(WORD); +; returns TRUE if given drive (0-25) is logical +; + push bp + mov bp,sp + push ds + push es + push si + push di + push dx + push cx + push bx + + mov bx,4[bp] ; get the drive number + inc bx ; A=1, B=2, etc + mov ax,4409h ; IOCTL Network/Local + int 21h ; do it + jc not_logical ; carry means invalid drive + and dx,1000h ; + cmp dx,0 + jne not_logical ; its a network drive + + mov ax,cs + mov ds,ax + mov es,ax + mov si,offset func60_in + mov di,offset func60_out + mov ax,4[bp] ; insert drive letter in input string + add al,'A' + mov [si],al ; + mov ah,60h ; Expand Path string + int 21h ; do it + jc not_logical ; carry set means invalid drive + + mov ax,4[bp] ; if drive letter changes then drive is + add al,'A' ; substed + cmp al,cs:[func60_out] + je not_logical + + mov ax,-1 + jmp logical_exit +not_logical: + mov ax,0 +logical_exit: + pop bx + pop cx + pop dx + pop di + pop si + pop es + pop ds + pop bp + ret + +_logical_drive ENDP + + public _network_drive +_network_drive PROC NEAR + +; BOOLEAN network_drive(WORD); +; returns TRUE if given drive (0-25) is networked +; + push bp + mov bp,sp + push dx + push cx + push bx + + mov bx,4[bp] ; get the drive number + inc bx ; A=1, B=2, etc + mov ax,4409h ; IOCTL Network/Local + int 21h ; do it + jc not_networked ; carry means invalid drive + and dx,1000h ; + cmp dx,0 + jne not_networked ; its a network drive + + mov ax,-1 + jmp network_exit +not_networked: + mov ax,0 +network_exit: + pop bx + pop cx + pop dx + pop bp + ret + +_network_drive ENDP + +endif ;EXT_SUBST + +else ;!DOSPLUS + + Public _physical_drvs ; Physical Drives returns a LONG +_physical_drvs: ; Vector with bits set for every + mov cx,DRV_LOGINVEC ; Physical or Networked Drive + int BDOS_INT ; attached to the system + xor dx,dx ; Return the LONG value in both + mov bx,dx ; AX:DX and AX:BX for maximum + ret ; compatibility + + Public _network_drvs ; Network Drives returns a LONG +_network_drvs: ; vector with bits set for every + push es ; physical drive which has been + mov ax,0 ; mapped to a remote DRNET server + mov dx,ax + les bx,_pd ; Get Our Process Descriptor + mov cx,es:P_NDA[bx] ; and then the NDA Segment + jcxz n_d20 ; Skip Drive Test if no NDA + mov es,cx ; Get the RCT Address + les bx,es:dword ptr 04h ;; NDA_RCT ; From the NDA + mov cx,16 +n_d10: + test es:RCT_DSK[bx],080h ; Is this a Remote drive + jz n_d15 ; No + or ax,1 ; Set Drive Bit +n_d15: + ror ax,1 ; Rotate Drive Bit Vector + add bx,2 ; Update the Drive Pointer + loop n_d10 ; Loop Till Done +n_d20: + mov bx,dx ; Return the long value in both + pop es ; AX:BX and AX:DX + ret + +ifndef EXT_SUBST + + Public _logical_drvs ; Logical Drives returns a LONG +_logical_drvs: ; vector with bits set for every + push es + push si + push di + + les si,_pd ; Get Our Process Descriptor + mov si,es:P_CAT[si] ; and then the address of the + mov cx,16 ; first HDS and check the first + mov ax,0 ; 16 Drives + mov bx,ax + +l_d10: + mov di,es:word ptr [si] ; Has this drive got an HDS + test di,di ; then skip setting the bit in + jz l_d20 ; the vector register + cmp es:byte ptr [di],bl ; Is the HDS pointing to same drive + jz l_d20 ; Yes then this is a Physical Drive + or ax,1 +l_d20: + ror ax,1 + add si,2 + inc bx + loop l_d10 ; Loop 16 Tines + + mov cx,10 ; Finally check the last 10 HDS + mov dx,0 +l_d30: + mov di,es:word ptr [si] ; Has this drive got an HDS + test di,di ; then skip setting the bit in + jz l_d40 ; the vector register + cmp es:byte ptr [di],bl ; Is the HDS pointing to same drive + jz l_d40 ; Yes then this is a Physical Drive + or dx,1 +l_d40: + ror dx,1 + add si,2 + inc bx + loop l_d30 ; Loop 10 Tines + + mov cl,6 ; Now rotate the contents of + ror dx,cl ; DX 6 more times for correct + ; alignment of bits + pop di + pop si + pop es + mov bx,dx ; Return the long value in both + ret ; AX:BX and AX:DX + + +; +; This function use the CONCURRENT 5.xx CP/M function to translate +; a logical to physical drive. +; + Public _pdrive +;------ +_pdrive: +;------ + push bp + mov bp,sp + mov dl,4[bp] ; get the logical drive + mov cl,175 ; Logical to Physical Xlat + int BDOS_INT + cbw + pop bp + CRET 2 + +endif ;!EXT_SUBST +endif ;!DOSPLUS + + + Public _toupper + +UCASE equ 18 ; offset of dword ptr to uppercase func + +;------- +_toupper proc near +;------- +; Return the uppercase equivilant of the given character. +; The uppercase function defined in the international info block is +; called for characters above 80h. +; +; char ch; char to be converted +; char result; uppercase equivilant of ch +; +; result = toupper(ch); + + push bp + mov bp, sp + + mov ax, 4[bp] + mov ah, 0 ; al = character to be converted + cmp al, 'a' ; al < 'a'? + jb exit_toupper ; yes - done (char unchanged) + cmp al, 'z' ; al <= 'z'? + jbe a_z ; yes - do ASCII conversion + cmp al, 80h ; international char? + jb exit_toupper ; no - done (char unchanged) + +; ch >= 80h -- call international routine + call dword ptr [_country+UCASE] + jmp exit_toupper + +a_z: +; 'a' <= ch <= 'z' -- convert to uppercase ASCII equivilant + and al, 0DFh + +exit_toupper: + pop bp + ret + +_toupper endp + + + +ifdef DOSPLUS +if 0 + Public _hiload_status +;---------- +_hiload_status: +;---------- + push bp + mov bp,sp + mov dx,100h ; get hiload state + mov ax,(MS_X_IOCTL*256)+57h ; IO Control function + int DOS_INT ; do INT 21h + pop bp ; + ret + + Public _hiload_set +;---------- +_hiload_set: +;---------- + push bp + mov bp,sp + mov dx,4[bp] ; get state + mov dh,2 ; set hiload state + mov ax,(MS_X_IOCTL*256)+57h ; IO Control function + int DOS_INT ; do INT 21h + pop bp ; + ret +endif + + Public _get_upper_memory_link +_get_upper_memory_link: + + mov ax,5802h + int 21h + cbw + ret + + Public _set_upper_memory_link +_set_upper_memory_link: + + push bp + mov bp,sp + mov bx,4[bp] + mov ax,5803h + int 21h + pop bp + ret + + Public _get_alloc_strategy +_get_alloc_strategy: + + mov ax,5800h + int 21h + ret + + Public _set_alloc_strategy +_set_alloc_strategy: + + push bp + mov bp,sp + mov bx,4[bp] + mov ax,5801h + int 21h + pop bp + ret + + Public _alloc_region + +_alloc_region: + push es + xor ax,ax + mov es,ax ; assume no block allocated + mov ah,MS_M_ALLOC + mov bx,1 + int 21h ; allocate a small block + jc _alloc_region10 + mov es,ax + mov ah,MS_M_SETBLOCK + mov bx,0FFFFh + int 21h ; find out how big the block is + mov ah,MS_M_SETBLOCK + int 21h ; now grow to take up the block +_alloc_region10: + mov ax,es ; return address of block + pop es + ret + + Public _free_region + +_free_region: + push bp + mov bp,sp + push es + mov es,4[bp] + mov ah,MS_M_FREE + int 21h ; free the block + pop es + pop bp + ret + +endif + +; The Double Byte Character Set lead byte table. +; Each entry in the table except the last specifies a valid lead byte range. +; +; 0 +---------------+---------------+ +; | start of | end of | DBCS table entry 0 +; | range 0 | range 0 | +; 2 +---------------+---------------+ +; | start of | end of | DBCS table entry 1 +; | range 1 | range 1 | +; +---------------+---------------+ +; : +; n +---------------+---------------+ +; | 0 | 0 | end of DBCS table +; | | | +; +---------------+---------------+ + + + Public _dbcs_expected + +_dbcs_expected proc near +;------------- +; Returns true if double byte characters are to be expected. +; A call to dbcs_init() MUST have been made. +; Entry +; none +; Exit +; ax = 1 - double byte characters are currently possible +; 0 - double byte characters are not currently possible + +ifdef DOSPLUS + push ds + push si + lds si, dbcs_table_ptr ; DS:SI -> system DBCS table + lodsw ; ax = first entry in DBCS table + test ax, ax ; empty table? + jz de_exit ; yes - return 0 (not expected) + mov ax, 1 ; return 1 (yes you can expect DBCS) +de_exit: + pop si + pop ds +else + xor ax,ax ; CDOS doesn't support them +endif + ret +_dbcs_expected endp + + + Public _dbcs_lead + +_dbcs_lead proc near +;--------- +; Returns true if given byte is a valid lead byte of a 16 bit character. +; A call to init_dbcs() MUST have been made. +; Entry +; 2[bp] = possible lead byte +; Exit +; ax = 1 - is a valid lead byte +; 0 - is not a valid lead byte + +ifdef DOSPLUS + push bp + mov bp, sp + push ds + push si + + mov bx, 4[bp] ; bl = byte to be tested + lds si,dbcs_table_ptr ; ds:si -> system DBCS table + lodsw ; any entries ? + test ax,ax + jz dl_not_valid ; no DBC entries + +dl_loop: + lodsw ; al/ah = start/end of range + test ax, ax ; end of table? + jz dl_not_valid ; yes - exit (not in table) + cmp al, bl ; start <= bl? + ja dl_loop ; no - try next range + cmp ah, bl ; bl <= end? + jb dl_loop ; no - try next range + + mov ax, 1 ; return 1 - valid lead byte + +dl_not_valid: + pop si + pop ds + pop bp +else + xor ax,ax ; CDOS doesn't support them +endif + ret +_dbcs_lead endp + + + PUBLIC _extended_error +_extended_error PROC NEAR + + mov ah,59h + mov bx,0 + int 21h + neg ax + ret + +_extended_error ENDP + + PUBLIC _get_lines_page +_get_lines_page PROC NEAR + + push bp + push es + + mov ax,1130h + mov bx,0 + mov dx,24 ; preset dx to 24 in case function not supported + int 10h + + mov ax,dx ; returns (no. rows)-1 in dx + inc ax + + pop es + pop bp + ret + +_get_lines_page ENDP + + PUBLIC _get_scr_width +_get_scr_width PROC NEAR + + push bp + mov ah,0fh + int 10h + xor al,al + xchg ah,al + pop bp + ret + +_get_scr_width ENDP + + PUBLIC _novell_copy +_novell_copy PROC NEAR + + push bp + mov bp,sp + push si + push di + + mov ax,11f0h + mov si,4[bp] ; si = source handle + mov di,6[bp] ; di = destination handle + mov dx,8[bp] ; lo word of source length + mov cx,10[bp] ; hi word of source length + clc ; start with carry cleared + + int 2fh ; do it + + jc novcop_failure ; carry set means novell couldn't handle it + + cmp ax,11f0h + je novcop_failure ; ax hasn't changed, so novell isn't there + + mov ax,1 ; success ! + jmp novcop_exit + +novcop_failure: + mov ax,0 +novcop_exit: + pop di + pop si + pop bp + ret + +_novell_copy ENDP + + PUBLIC _call_novell +_call_novell PROC NEAR + + push bp + mov bp,sp + push es + push si + push di + + mov ah,8[bp] + mov al,0ffh + push ds + pop es + mov si,4[bp] + mov di,6[bp] + int 21h + + cmp al,0 + jne call_nov_err + jc call_nov_err + + mov ax,0 + jmp call_nov_exit + +call_nov_err: + mov ah,0 ;; clear ah, BUT allow all ret' values in al +call_nov_exit: + pop di + pop si + pop es + pop bp + ret + +_call_novell ENDP + + PUBLIC _nov_station +_nov_station PROC NEAR + + push bp + mov bp,sp + push si + + mov ax,0eeffh + int 21h + cmp ax,0ee00h + je ns_err + + mov si,4[bp] + mov [si],cx + mov 2[si],bx + mov 4[si],ax + mov ax,0 + jmp ns_exit + +ns_err: + mov ax,-1 + +ns_exit: + pop si + pop bp + ret + +_nov_station ENDP + + public _nov_connection +_nov_connection PROC NEAR + + push es + push si + +if 0 + mov ax,0 + mov es,ax + mov si,0 + mov ax,0ef03h + int 21h + + mov ax,es + cmp ax,0 + jne nc_ok + cmp si,0 + jne nc_ok + mov ax,-1 + jmp nc_exit + +nc_ok: + mov al,es:23[si] + mov ah,0 +endif + + mov ax,0dc00h + int 21h + jc nc_err + sub ah,ah + jmp nc_exit + +nc_err: + mov al,-1; + +nc_exit: + pop si + pop es + ret + +_nov_connection ENDP + +_TEXT ENDS + END diff --git a/COMMAND/DOSIF.H b/COMMAND/DOSIF.H new file mode 100644 index 0000000..cd0e8a7 --- /dev/null +++ b/COMMAND/DOSIF.H @@ -0,0 +1,181 @@ +/* +; File : $Workfile$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +*/ + +EXTERN VOID CDECL debug(VOID); + +#define EXT_SUBST 1 + +#if defined(MSC) || defined(MWC) || defined(TURBOC) || defined(__WATCOMC__) +#define bdos _BDOS +EXTERN BYTE * CDECL heap_get(WORD); +EXTERN BYTE * CDECL heap(VOID); +EXTERN VOID CDECL heap_set(BYTE *); +#endif + +#if !defined(MWC) +EXTERN BYTE * CDECL stack(WORD); +#endif + +#if defined(CPM) +#define ms_drv_space cpm_drv_space +#define ms_x_mkdir cpm_x_mkdir +#define ms_x_rmdir cpm_x_rmdir +#define ms_x_creat cpm_x_creat +#define ms_x_open cpm_x_open +#define ms_x_close cpm_x_close +#define far_read cpm_far_read +#define far_write cpm_far_write +#define ms_x_read cpm_x_read +#define ms_x_write cpm_x_write +#define ms_x_unlink cpm_x_unlink +#define ms_x_lseek cpm_x_lseek +#define ms_x_ioctl cpm_x_ioctl +#define ms_x_chmod cpm_x_chmod +#define ms_x_curdir cpm_x_curdir +#define ms_x_first cpm_x_first +#define ms_x_next cpm_x_next +#define ms_x_rename cpm_x_rename +#define ms_x_datetime cpm_x_datetime +#endif + +EXTERN VOID CDECL ms_drv_set(WORD); +EXTERN WORD CDECL ms_drv_get(VOID); +EXTERN WORD CDECL ms_drv_space(UWORD, UWORD * ,UWORD *, UWORD *); +EXTERN WORD CDECL ms_x_chdir(BYTE *); +EXTERN WORD CDECL ms_x_mkdir(BYTE *); +EXTERN WORD CDECL ms_x_rmdir(BYTE *); +EXTERN WORD CDECL ms_s_country(INTERNAT *); +EXTERN BYTE CDECL toupper(BYTE); +EXTERN WORD CDECL ms_x_creat(BYTE *, UWORD); +EXTERN WORD CDECL ms_x_open(BYTE *, UWORD); +EXTERN WORD CDECL ms_x_close(WORD); +EXTERN WORD CDECL ms_x_fdup(UWORD, UWORD); +EXTERN WORD CDECL ms_x_unique(BYTE *, UWORD); +EXTERN WORD CDECL far_read(UWORD, BYTE FAR *, UWORD); +EXTERN WORD CDECL far_write(UWORD, BYTE FAR *, UWORD); +EXTERN WORD CDECL ms_x_read(UWORD, BYTE *, UWORD); +EXTERN WORD CDECL ms_x_write(UWORD, BYTE *, UWORD); +EXTERN WORD CDECL ms_x_unlink(BYTE *); +EXTERN LONG CDECL ms_x_lseek(UWORD, LONG, UWORD); +EXTERN WORD CDECL ms_x_ioctl(UWORD); +EXTERN WORD CDECL ms_x_setdev(UWORD, UBYTE); +EXTERN WORD CDECL ms_x_chmod(BYTE *, UWORD, UWORD); +EXTERN WORD CDECL ms_x_curdir(UWORD, BYTE *); +EXTERN WORD CDECL ms_x_wait(VOID); +EXTERN WORD CDECL ms_x_first(BYTE *, UWORD, DTA *); +EXTERN WORD CDECL ms_x_next(DTA *); +EXTERN WORD CDECL ms_x_rename(BYTE *, BYTE *); +EXTERN WORD CDECL ms_x_datetime(BOOLEAN, UWORD, UWORD *, UWORD *); +EXTERN WORD CDECL ms_settime(SYSTIME *); +EXTERN WORD CDECL ms_setdate(SYSDATE *); +EXTERN VOID CDECL ms_gettime(SYSTIME *); +EXTERN VOID CDECL ms_getdate(SYSDATE *); +EXTERN VOID FAR * CDECL ms_idle_ptr(VOID); +EXTERN WORD CDECL ms_switchar(VOID); +EXTERN WORD CDECL ms_x_expand(BYTE *, BYTE *); + +EXTERN VOID CDECL mem_alloc(BYTE FAR * NEAR *, UWORD *, UWORD, UWORD); +EXTERN VOID CDECL mem_free (BYTE FAR * NEAR *); + +EXTERN UWORD CDECL psp_poke(UWORD, UWORD); /* Poke Handle Table */ + +EXTERN BOOLEAN CDECL dbcs_expected(VOID); +EXTERN BOOLEAN CDECL dbcs_lead(BYTE); + +#if !defined(CDOSTMP) +EXTERN UWORD CDECL ioctl_ver(VOID); +EXTERN VOID CDECL ms_x_exit(); +EXTERN VOID CDECL ms_f_verify(BOOLEAN); +EXTERN BOOLEAN CDECL ms_set_break(BOOLEAN); +EXTERN WORD CDECL ms_f_getverify(VOID); +EXTERN WORD CDECL ms_f_parse (BYTE *, BYTE *, UBYTE); +EXTERN WORD CDECL ms_f_delete (BYTE *); +EXTERN VOID CDECL restore_term_addr(); +#endif + +#if defined(DOSPLUS) +EXTERN WORD CDECL ms_x_getcp(UWORD *, UWORD *); +EXTERN WORD CDECL ms_x_setcp(UWORD); +/*EXTERN VOID CDECL hiload_set(BOOLEAN);*/ +EXTERN WORD CDECL get_upper_memory_link(VOID); +EXTERN VOID CDECL set_upper_memory_link(WORD); +EXTERN WORD CDECL get_alloc_strategy(VOID); +EXTERN VOID CDECL set_alloc_strategy(WORD); +EXTERN WORD CDECL alloc_region(); +EXTERN VOID CDECL free_region(WORD); +#endif + +EXTERN BOOLEAN CDECL env_entry(BYTE *, UWORD); /* CSUP.ASM */ +EXTERN BOOLEAN CDECL env_scan(BYTE *, BYTE *); /* CSUP.ASM */ +EXTERN BOOLEAN CDECL env_del(BYTE *); /* CSUP.ASM */ +EXTERN BOOLEAN CDECL env_ins(BYTE *); /* CSUP.ASM */ + +#if defined(CDOSTMP) +#define system bdos /* Call the BDOS Function for Common routines */ +#else +#define system msdos /* Call the MSDOS Function for Common routines */ +EXTERN WORD CDECL msdos(); +EXTERN WORD CDECL readline(BYTE *); +#endif + +#if defined(CDOSTMP) || defined(CDOS) +EXTERN VOID CDECL vc_data(UWORD *, UWORD *, UWORD *); +EXTERN WORD CDECL bdos(WORD,...); +#endif + +#if !defined(DOSPLUS) || !defined(EXT_SUBST) +EXTERN ULONG CDECL physical_drvs(VOID); +EXTERN ULONG CDECL network_drvs(VOID); +#endif +#if !defined(EXT_SUBST) +EXTERN ULONG CDECL logical_drvs(VOID); +EXTERN UWORD CDECL pdrive(UWORD); +#endif +EXTERN UWORD CDECL exec(BYTE *, UWORD, BYTE *, BOOLEAN); + +#if !defined(DOSPLUS) +EXTERN UWORD FAR * CDECL sysdat(UWORD); +#define SYSDATW(x) sysdat(x) +#define SYSDATB(x) ((UBYTE FAR *) sysdat(x)) +#endif + +EXTERN BOOLEAN CDECL physical_drive(WORD); +EXTERN BOOLEAN CDECL logical_drive(WORD); +EXTERN BOOLEAN CDECL network_drive(WORD); +EXTERN BOOLEAN CDECL extended_error(VOID); +EXTERN WORD CDECL get_lines_page(VOID); +EXTERN WORD CDECL get_scr_width(VOID); +EXTERN WORD CDECL novell_copy(WORD,WORD,ULONG); diff --git a/COMMAND/DRIVER.EQU b/COMMAND/DRIVER.EQU new file mode 100644 index 0000000..a5809cb --- /dev/null +++ b/COMMAND/DRIVER.EQU @@ -0,0 +1,59 @@ +; File : $DRIVER.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; ENDLOG +; Device driver header offsets. + + +DH_NEXT equ es:dword ptr 0 ; Dword Pointer to Next DEV +DH_NEXTOFF equ es:word ptr 0 ; Offset of next device +DH_NEXTSEG equ es:word ptr 2 ; Segment of next device +DH_ATTRIB equ es:word ptr 4 ; device attribute bits +DH_STRATEGY equ es:word ptr 6 ; offset of strategy entry +DH_INTERRUPT equ es:word ptr 8 ; offset of interupt entry +DH_NAME equ es:byte ptr 10 ; 8-BYTE device name + +DA_CHARDEV equ 8000h ; 1=character device, 0=block device +DA_IOCTL equ 4000h ; device supports IOCTL string I/O +DA_NONIBM equ 2000h ; dosen't require FAT for login +DA_OTILBSY equ 2000h ; supports "output until busy" +DA_REMOVE equ 0800h ; supports "removable media" check +DA_QUERY equ 0080h ; supports query ioctl +DA_GETSET equ 0040h ; supports 3.2 level functionality +DA_SPECIAL equ 0010h ; fast console ouput via INT 29h +DA_ISCLK equ 0008h ; device is current clock device +DA_ISNUL equ 0004h ; device is NUL device (reserved) +DA_BIGDRV equ 0002h ; supports > 65535 sector per drive +DA_ISCOT equ 0002h ; device is standard output device +DA_ISCIN equ 0001h ; device is standard input device + +FASTCON_INT equ 29h ; fast console output interrupt + diff --git a/COMMAND/F52DATA.DEF b/COMMAND/F52DATA.DEF new file mode 100644 index 0000000..44bb546 --- /dev/null +++ b/COMMAND/F52DATA.DEF @@ -0,0 +1,88 @@ +; File : $F52DATA.DEF$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +; The following equates define the Data Area whose address is +; returned by function 52. +; + +F52_BCBBUF equ es:dword ptr -0008h[bx] ; current buffer +F52_BCBOFF equ es:word ptr -0008h[bx] ; current buffer +F52_BCBSEG equ es:word ptr -0006h[bx] ; current buffer +F52_DMDROOT equ es:word ptr -0002h[bx] ; Memory Descriptor Root (Seg) +F52_DDSCPTR equ es:dword ptr 0000h[bx] ; DDSC Table Address +F52_FILEPTR equ es:dword ptr 0004h[bx] ; File Handle Table Address +F52_CLKDEV equ es:dword ptr 0008h[bx] ; Clock Device Header +F52_CONDEV equ es:dword ptr 000Ch[bx] ; Console Device Header +F52_SECSIZE equ es:word ptr 0010h[bx] ; Maximum Sector Size +F52_BUFINFOPTR equ es:dword ptr 0012h[bx] ; Buffer Info pointer +F52_PATHPTR equ es:dword ptr 0016h[bx] ; Path Control Table Address +F52_PATHOFF equ es:word ptr 0016h[bx] +F52_PATHSEG equ es:word ptr 0018h[bx] +F52_FCBPTR equ es:dword ptr 001Ah[bx] ; FCB Table Address +; equ es:word ptr 001Eh[bx] ; #Entries in FCB Table +F52_PHYDRV equ es:byte ptr 0020h[bx] ; Last Physical Drive +F52_LASTDRV equ es:byte ptr 0021h[bx] ; Last Logical Drive +F52_DEVROOT equ es:dword ptr 0022h[bx] ; Root Device Header +F52_JOINDRV equ es:byte ptr 0034h[bx] ; Number of JOIN'd drives +F52_SETVER equ es:dword ptr 0037h[bx] ; SETVER table pointer +F52_NUM_BUF equ es:word ptr 003Fh[bx] ; number of disk buffers +F52_READ_AHEAD equ es:word ptr 0041h[bx] ; size of read-ahead buffer +F52_BOOTDRV equ es:byte ptr 0043h[bx] ; boot drive (1-26) +F52_CPU_TYPE equ es:byte ptr 0044h[bx] ; 01 if >= 386SX +F52_EXT_MEM equ es:word ptr 0045h[bx] ; Int 15h, AH=87h +F52_BUF_INFO equ es:dword ptr 0047h[bx] ; points at Buffer Info +F52_HMAFLAG equ es:byte ptr 0053h[bx] ; 1 if buffers in HMA +F52_DEBLOCK equ es:word ptr 0056h[bx] ; deblock if buffers in HMA +F52_DMD_UPPER equ es:word ptr 0066h[bx] ; upper memory chain +F52_SHARE_STUB equ es:dword ptr 006Ah[bx] ; Share Stub Entries*15 + +;DRDOS Specific + +DRDOS_CRITSTUBS equ es:word ptr 0000h[bx] ; Offset of end of instance data +DRDOS_HIST1CTL equ es:word ptr 0004h[bx] ; History 1 Control +DRDOS_HIST2CTL equ es:word ptr 0006h[bx] ; History 2 Control +DRDOS_HISTFLG equ es:byte ptr 0008h[bx] ; History Buffer Flag +DRDOS_DUAL_LANG equ es:byte ptr 0009h[bx] ; Utils Dual Language Support +DRDOS_CUR_LANG equ es:byte ptr 000Ah[bx] ; Current Language +DRDOS_EXT_MEM equ es:word ptr 000Bh[bx] ; Total Extended Memory +DRDOS_HIMEM_ROOT equ es:word ptr 0010h[bx] ; High memory chain +DRDOS_ENVSEG equ es:word ptr 0012h[bx] ; Seg of environment +DRDOS_DMD_BASE equ es:word ptr 0016h[bx] ; base memory freed at +DRDOS_DMD_UPPER equ es:word ptr 0018h[bx] ; upper memory chain +DRDOS_MACHINE_ID equ es:word ptr 001Ah[bx] ; local machine ID +DRDOS_COUNTRY_FILE equ es:word ptr 001Eh[bx] ; offset of filename +DRDOS_HASHOFF equ es:word ptr 0020h[bx] ; fastopen hash root +DRDOS_HASHSEG equ es:word ptr 0022h[bx] ; pointer +DRDOS_HASHMAX equ es:word ptr 0024h[bx] ; max # dir entries +DRDOS_DEBLOCK equ es:word ptr 0026h[bx] ; himem deblock buffer +DRDOS_INT2F equ es:word ptr 002Ch[bx] ; internal Int 2F hook diff --git a/COMMAND/GLOBAL.C b/COMMAND/GLOBAL.C new file mode 100644 index 0000000..1d76f73 --- /dev/null +++ b/COMMAND/GLOBAL.C @@ -0,0 +1,168 @@ +/* +; File : $Workfile: GLOBAL.C$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +*/ + +/* + Date Comments + --------- ------------------------------------------------------------ + 21 Mar 88 Modify IN_PIPE and OUT_PIPE to be compatible with NOVELL 2.1 + 21 Sep 88 Change the default ECHO state to be ON. +*/ + +#include "defines.h" +#include +#include /* Command Definitions */ +/*.pa*/ +/* General Purpose Variables */ +GLOBAL BOOLEAN initflg = FALSE; /* Initial Load Flag */ +GLOBAL WORD drive = 0; /* Current default Drive */ +GLOBAL UWORD echoflg = ECHO_ON; /* Current Echo Status */ +GLOBAL BOOLEAN crlfflg = FALSE; /* No CR/LF Required before prompt */ + +/* Batch File Processing Variables */ +GLOBAL UWORD batchflg = 0; /* Currently processing Batch File */ + +/* FOR Sub-Command Variables */ +GLOBAL BOOLEAN for_flag = NO; /* FOR Sub-command Active */ + +/* I/O Redirection Control */ +GLOBAL WORD in_flag = NULL; +GLOBAL WORD out_flag = NULL; +GLOBAL UWORD in_handle = NULL; +GLOBAL UWORD out_handle = NULL; + +/* Pipe Control Data */ +GLOBAL BOOLEAN pipe_out = NO; /* Activate Pipe output */ +GLOBAL BOOLEAN pipe_in = NO; /* Activate Pipe Input */ +GLOBAL BOOLEAN preserve_pipe = NO; + +/* + * The following two structures are patched by NOVELL Version 2.1 + * to force the creation of the PIPE files in the current sub-directory + * rather than the root. The '/' is patched to a '.' by the NET3.COM + * program. + */ + +GLOBAL BYTE out_pipe[64] = "_:/\0_______.___"; /* Output Pipe Name "x:\filename.ext" */ + +GLOBAL BYTE *old_pipe; /* old pipe file name */ + + +GLOBAL BYTE pathchar[] = "\\"; /* The current path character. This */ + /* can be accessed as a byte using */ + /* "*pathchar" or as a string using */ + /* "pathchar". */ +#if defined(PASSWORD) +GLOBAL BYTE pwdchar[] = ";"; /* The Password delimiter. Which can*/ + /* be accessed in the same way as */ + /* pathchar. */ +#endif + +GLOBAL BYTE switchar[] = "/"; /* Switch Character */ + +GLOBAL BYTE dotdot[] = ".."; +GLOBAL BYTE d_slash_stardotstar[] = "x:\\*.*"; + +GLOBAL BOOLEAN back_flag = FALSE; /* Execute a BackGround Task*/ +GLOBAL BOOLEAN execed; +GLOBAL WORD page_len = 24; /* Screen Length */ +GLOBAL WORD page_wid = 80; /* Screen Width */ + +GLOBAL BOOLEAN break_flag; + +GLOBAL BOOLEAN err_flag; +GLOBAL UWORD err_ret; + +GLOBAL WORD ddrive; +GLOBAL BYTE FAR *bufaddr; /* External Copy Buffer Address */ +GLOBAL UWORD bufsize; /* External Copy Buffer Size */ + +GLOBAL INTERNAT country; /* country data structure */ + +#if defined(DOSPLUS) +GLOBAL BYTE *ftypes[] = { "com", "exe", "bat", NULL}; +#else +GLOBAL BYTE *ftypes[] = { "cmd", "com", "exe", "bat", NULL}; +#endif + +/* This pointer is initialized by the Startup routine and */ +/* would be defined there if I could persuade the compiler */ +/* to reference it correctly. */ + +#if !defined(DOSPLUS) +#include /* PD Structure Declaration */ + +GLOBAL PD FAR * CDECL pd = (PD FAR *) 1234L; /* FAR pointer to our PD */ +GLOBAL WORD CDECL sysdat_seg = 0; /* Segment address of SYSDAT */ +#endif + +GLOBAL BOOLEAN c_option = FALSE; +GLOBAL BOOLEAN k_option = FALSE; +GLOBAL BOOLEAN n_option = FALSE; +GLOBAL BOOLEAN allow_pexec = FALSE; + +GLOBAL BYTE FAR *gp_far_buff = 0L; +GLOBAL BYTE FAR *show_file_buf = 0L; + +GLOBAL UWORD FAR *parent_psp; +GLOBAL UWORD save_parent; + +#define FCONTROL struct fcc +MLOCAL FCONTROL { + BOOLEAN sflg; /* FOR File Search Flag */ + DTA search; /* FOR Search structure */ + BYTE *files; /* FOR File list */ + BYTE *cmd; /* FOR Command Line */ + BYTE forvar; /* FOR variable char */ +}; + +#define BCONTROL struct bcc +GLOBAL BCONTROL { + BCONTROL FAR *bcontrol; /* Previous Batch Control Structure */ + BOOLEAN eof; /* End of File Flag */ + LONG offset; /* Offset in BATCH file */ + LONG ret_offset[4]; /* return offset from gosub */ + BYTE *batcmd; /* Batch File Input parameters */ + UWORD batshift; /* Shift Offset */ + BYTE batfile[MAX_PATHLEN]; /* Batch File Name */ + UWORD stream; /* Stream for this Batch File */ + FCONTROL *fcontrol; /* Pointer to previous FOR command */ + BYTE *heap_start; /* Heap pointer before extra bytes */ + WORD heap_size; /* are added to shift to segment */ + BYTE save_area[1]; /* boundary. - EJH */ +} FAR *batch, FAR *batch_save; /* Master Batch Control Stucture */ + +WORD global_link; +WORD global_strat; +WORD global_in_hiload = 0; +WORD hidden_umb[10]; diff --git a/COMMAND/GLOBAL.H b/COMMAND/GLOBAL.H new file mode 100644 index 0000000..2ee5988 --- /dev/null +++ b/COMMAND/GLOBAL.H @@ -0,0 +1,155 @@ +/* +; File : $Workfile$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +*/ + +EXTERN BOOLEAN initflg; /* Initial Load Flag */ +EXTERN WORD drive; /* Current default Drive */ +EXTERN UWORD echoflg; /* Current Echo Status */ +EXTERN BOOLEAN crlfflg; /* CR/LF Required before prompt */ + +/* Batch File Processing Variables */ +EXTERN UWORD batchflg; /* Currently processing Batch File */ + +/* FOR Sub-Command Variables */ +EXTERN BOOLEAN for_flag; /* FOR Sub-command Active */ + +/* I/O Redirection Control */ +EXTERN WORD in_flag; +EXTERN WORD out_flag; +EXTERN WORD in_handle; +EXTERN WORD out_handle; + +/* Pipe Control Data */ +EXTERN BOOLEAN pipe_out; /* Activate Pipe output */ +EXTERN BOOLEAN pipe_in; /* Activate Pipe Input */ +EXTERN BOOLEAN preserve_pipe; +EXTERN BYTE out_pipe[]; /* Output Pipe Name "x:\filename.ext" */ +EXTERN BYTE *old_pipe; + +EXTERN BYTE pathchar[]; /* The current path character. This */ + /* can be accessed as a byte using */ + /* "*pathchar" or as a string using */ + /* "pathchar". */ +#if defined(PASSWORD) +EXTERN BYTE pwdchar[]; /* The Password delimiter. Which can*/ + /* be accessed in the same way as */ + /* pathchar. */ +#endif + +EXTERN BYTE switchar[]; /* Switch Character */ + +EXTERN BYTE dotdot[]; +EXTERN BYTE d_slash_stardotstar[]; + +EXTERN BOOLEAN back_flag; /* Execute a BackGround Task*/ +EXTERN BOOLEAN execed; /* were we execed from DOS? */ +EXTERN WORD page_len; /* Screen Length */ +EXTERN WORD page_wid; /* Screen Width */ + +EXTERN BOOLEAN break_flag; +EXTERN BOOLEAN err_flag; +EXTERN UWORD err_ret; + +EXTERN WORD ddrive; +EXTERN BYTE FAR *bufaddr; /* External Copy Buffer Address */ +EXTERN UWORD bufsize; /* External Copy Buffer Size */ + +EXTERN INTERNAT country; /* country data structure */ +#define JAPAN 81 /* country.code for Japan */ + +EXTERN BYTE *ftypes[]; + +EXTERN BOOLEAN c_option; +EXTERN BOOLEAN k_option; +EXTERN BOOLEAN n_option; +EXTERN BOOLEAN allow_pexec; + +EXTERN BYTE FAR *gp_far_buff; +EXTERN BYTE FAR *show_file_buf; +EXTERN UWORD FAR *parent_psp; +EXTERN UWORD save_parent; + +#define FCONTROL struct fcc +FCONTROL { + BOOLEAN sflg; /* FOR File Search Flag */ + DTA search; /* FOR Search structure */ + BYTE *files; /* FOR File list */ + BYTE *cmd; /* FOR Command Line */ + BYTE forvar; /* FOR variable char */ +}; + +#define BCONTROL struct bcc +BCONTROL { + BCONTROL FAR *bcontrol; /* Previous Batch Control Structure */ + BOOLEAN eof; /* End of File Flag */ + LONG offset; /* Offset in BATCH file */ + LONG ret_offset[4]; /* return offset from gosub */ + BYTE *batcmd; /* Batch File Input parameters */ + UWORD batshift; /* Shift Offset */ + BYTE batfile[MAX_PATHLEN]; /* Batch File Name */ + UWORD stream; /* Stream for this Batch File */ + FCONTROL *fcontrol; /* Pointer to previous FOR command */ + BYTE *heap_start; /* Heap pointer before extra bytes */ + WORD heap_size; /* are added to shift to segment */ + BYTE save_area[1]; /* boundary. - EJH */ +}; +EXTERN BCONTROL FAR *batch; +EXTERN BCONTROL FAR *batch_save; + + +EXTERN WORD global_link; +EXTERN WORD global_strat; +EXTERN WORD global_in_hiload; +EXTERN WORD hidden_umb[10]; + +/* + * File type index's returned by the Concurrent DOS P_PATH function + * and emulated in the findfile function. DOSPLUS does not search + * for the ".CMD" and therefore uses a modified index. + * + */ +#if defined(DOSPLUS) || defined(NETWARE) +#define COM_FILETYPE 0 /* MicroSoft .COM */ +#define EXE_FILETYPE 1 /* MicroSoft .EXE */ +#define BAT_FILETYPE 2 /* Batch File */ +#else +#define CMD_FILETYPE 0 /* Digital Reseach .CMD */ +#define COM_FILETYPE 1 /* MicroSoft .COM */ +#define EXE_FILETYPE 2 /* MicroSoft .EXE */ +#define BAT_FILETYPE 3 /* Batch File */ +#endif + +#define ERROR_EXIT 0x0200 /* Exit because of a Critical Error */ +#define BREAK_EXIT 0x0100 /* Exit because of a Control-Break */ diff --git a/COMMAND/HELP.H b/COMMAND/HELP.H new file mode 100644 index 0000000..721ca91 --- /dev/null +++ b/COMMAND/HELP.H @@ -0,0 +1,198 @@ +/* +; File : $Workfile$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +*/ + +#include + +#if !defined(CDOS) || defined(NOHELP) +#define HELP_AND NULL +#define HELP_APPEND NULL +#define HELP_ASSIGN NULL +#define HELP_BANK NULL +#define HELP_BREAK NULL +#define HELP_CALL NULL +#define HELP_CHDIR NULL +#define HELP_CLS NULL +#define HELP_COM NULL +#define HELP_COPY NULL +#define HELP_DATE NULL +#define HELP_DBG NULL +#define HELP_DEL NULL +#define HELP_DELQ NULL +#define HELP_DIR NULL +#define HELP_ECHO NULL +#define HELP_ECHOERR NULL +#define HELP_ERAQ NULL +#define HELP_ERASE NULL +#define HELP_EXIT NULL +#define HELP_FOR NULL +#define HELP_GOTO NULL +#define HELP_IDLE NULL +#define HELP_IF NULL +#define HELP_INPUT NULL +#define HELP_INPUTC NULL +#define HELP_LIMSIZE NULL +#define HELP_MEMSIZE NULL +#define HELP_MKDIR NULL +#define HELP_MORE NULL +#define HELP_NETDRIVE NULL +#define HELP_NETOFF NULL +#define HELP_NETON NULL +#define HELP_OR NULL +#define HELP_PATH NULL +#define HELP_PAUSE NULL +#define HELP_PAUSEERR NULL +#define HELP_PROMPT NULL +#define HELP_REM NULL +#define HELP_RENAME NULL +#define HELP_RMDIR NULL +#define HELP_SET NULL +#define HELP_SHIFT NULL +#define HELP_STOP NULL +#define HELP_SUBST NULL +#define HELP_SUSPEND NULL +#define HELP_TIME NULL +#define HELP_TRUENAME NULL +#define HELP_TYPE NULL +#define HELP_VER NULL +#define HELP_VERIFY NULL +#define HELP_VOL NULL +#else +#define HELP_AND help_and +#define HELP_APPEND help_append +#define HELP_ASSIGN help_assign +#define HELP_BANK help_bank +#define HELP_BREAK help_break +#define HELP_CALL help_call +#define HELP_CHDIR help_chdir +#define HELP_CLS help_cls +#define HELP_COM help_com +#define HELP_COPY help_copy +#define HELP_DATE help_date +#define HELP_DBG help_dbg +#define HELP_DEL help_del +#define HELP_DELQ help_delq +#define HELP_DIR help_dir +#define HELP_ECHO help_echo +#define HELP_ECHOERR help_echoerr +#define HELP_ERAQ help_eraq +#define HELP_ERASE help_erase +#define HELP_EXIT help_exit +#define HELP_FOR help_for +#define HELP_GOTO help_goto +#define HELP_IDLE help_idle +#define HELP_IF help_if +#define HELP_INPUT help_input +#define HELP_INPUTC help_inputc +#define HELP_LIMSIZE help_limsize +#define HELP_MEMSIZE help_memsize +#define HELP_MKDIR help_mkdir +#define HELP_MORE help_more +#define HELP_NETDRIVE help_netdrive +#define HELP_NETOFF help_netoff +#define HELP_NETON help_neton +#define HELP_OR help_or +#define HELP_PATH help_path +#define HELP_PAUSE help_pause +#define HELP_PAUSEERR help_pauseerr +#define HELP_PROMPT help_prompt +#define HELP_REM help_rem +#define HELP_RENAME help_rename +#define HELP_RMDIR help_rmdir +#define HELP_SET help_set +#define HELP_SHIFT help_shift +#define HELP_STOP help_stop +#define HELP_SUBST help_subst +#define HELP_SUSPEND help_suspend +#define HELP_TIME help_time +#define HELP_TRUENAME help_truename +#define HELP_TYPE help_type +#define HELP_VER help_ver +#define HELP_VERIFY help_verify +#define HELP_VOL help_vol + +EXTERN BYTE help_and []; +EXTERN BYTE help_append []; +EXTERN BYTE help_assign []; +EXTERN BYTE help_bank []; +EXTERN BYTE help_break []; +EXTERN BYTE help_call []; +EXTERN BYTE help_chdir []; +EXTERN BYTE help_cls []; +EXTERN BYTE help_com []; +EXTERN BYTE help_copy []; +EXTERN BYTE help_date []; +EXTERN BYTE help_dbg []; +EXTERN BYTE help_del []; +EXTERN BYTE help_delq []; +EXTERN BYTE help_dir []; +EXTERN BYTE help_echo []; +EXTERN BYTE help_echoerr[]; +EXTERN BYTE help_eraq []; +EXTERN BYTE help_erase []; +EXTERN BYTE help_exit []; +EXTERN BYTE help_for []; +EXTERN BYTE help_goto []; +EXTERN BYTE help_idle []; +EXTERN BYTE help_if []; +EXTERN BYTE help_input []; +EXTERN BYTE help_inputc []; +EXTERN BYTE help_limsize[]; +EXTERN BYTE help_memsize[]; +EXTERN BYTE help_mkdir []; +EXTERN BYTE help_more []; +EXTERN BYTE help_netdrive[]; +EXTERN BYTE help_netoff []; +EXTERN BYTE help_neton []; +EXTERN BYTE help_or []; +EXTERN BYTE help_path []; +EXTERN BYTE help_pause []; +EXTERN BYTE help_pauseerr []; +EXTERN BYTE help_prompt []; +EXTERN BYTE help_rem []; +EXTERN BYTE help_rename []; +EXTERN BYTE help_rmdir []; +EXTERN BYTE help_set []; +EXTERN BYTE help_shift []; +EXTERN BYTE help_stop []; +EXTERN BYTE help_subst []; +EXTERN BYTE help_suspend[]; +EXTERN BYTE help_time []; +EXTERN BYTE help_truename []; +EXTERN BYTE help_type []; +EXTERN BYTE help_ver []; +EXTERN BYTE help_verify []; +EXTERN BYTE help_vol []; +#endif diff --git a/COMMAND/HELPSTUB.ASM b/COMMAND/HELPSTUB.ASM new file mode 100644 index 0000000..9eb28f9 --- /dev/null +++ b/COMMAND/HELPSTUB.ASM @@ -0,0 +1,62 @@ +; File : $Workfile: HELPSTUB.ASM$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; ENDLOG +; HELPSTUB.ASM +; + +; The word value defined here is the first word in the help segment. +; It is a pointer to the message table which contains pointers to the +; actual messages. + + +include txhelp.def + + +CHELP GROUP _HELP +_HELP SEGMENT para public 'HELP' + +ifdef DLS + extrn _pri_table:word + extrn _alt_table:word + + dw offset CHELP:_pri_table + dw offset CHELP:_alt_table +else + extrn _single_table:word + +help_list dw offset CHELP:_single_table + +endif + +_HELP ENDS + +END diff --git a/COMMAND/IDLE.H b/COMMAND/IDLE.H new file mode 100644 index 0000000..1040993 --- /dev/null +++ b/COMMAND/IDLE.H @@ -0,0 +1,52 @@ +/* +; File : $Workfile$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +*/ + +#include + +#define IDLE_COMMAND 0x0001 +#define IDLE_DOSFUNC 0x0002 +#define IDLE_ON 0x4000 +#define IDLE_ENABLE 0x8000 + +typedef struct _idle_state { + WORD count; + WORD max; + WORD flags; + VOID FAR *vec; + WORD delay; + WORD reload; + WORD indos; +} IDLE_STATE; diff --git a/COMMAND/LOGIN.H b/COMMAND/LOGIN.H new file mode 100644 index 0000000..669ce77 --- /dev/null +++ b/COMMAND/LOGIN.H @@ -0,0 +1,151 @@ +/* +; File : $Workfile$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +*/ + +/* the following constants are in alphabetical order */ +#define ABORT_CODE 0 +#define CR 0xd +#define CMNT_LGTH 32 +#define DAY_LGTH 4 +#define ENABLED 0xff +#define EOF_CHAR 0x1a +#define ENTER 0xd +#define FLAGS 0x0056 /* addr. Flag Table */ +#define FNAME_LEN 12 +#define LDATE_LGTH 11 +#define LF 0xa +#define MAX_LINE 128 +#define MXWIDTH 19 +#define OKAY 0 +#define PROCNAME_LGTH 12 +#define ROOT_DIR "\\" +#define SEEK_END 2 +#define STIME_LGTH 8 +#define SUPERUSER 0 +#define SUPERUSERSTR "0000" +#define TYPE_PAGE (flags & 1) +#define TIME_LGTH 8 +#define USERID_LGTH 4 + +#define OWN_PROT_READ 0x0008 /* Owner */ +#define OWN_PROT_WRITE 0x0004 +#define OWN_PROT_EXEC 0x0002 +#define OWN_PROT_DEL 0x0001 + +#define GRP_PROT_READ 0x0080 /* Group */ +#define GRP_PROT_WRITE 0x0040 +#define GRP_PROT_EXEC 0x0020 +#define GRP_PROT_DEL 0x0010 + +#define WOR_PROT_READ 0x0800 /* World */ +#define WOR_PROT_WRITE 0x0400 +#define WOR_PROT_EXEC 0x0200 +#define WOR_PROT_DEL 0x0100 + +#define ALL_PROT_READ 0x0888 /* Owner + Group + World */ +#define ALL_PROT_WRITE 0x0444 +#define ALL_PROT_EXEC 0x0222 +#define ALL_PROT_DEL 0x0111 + +#define ALL_PROT 0x0FFF /* all groups, all access modes */ + + +#define AUTOEXEC_BAT "AUTOEXEC.BAT" + +EXTERN USER_INF_ENTRY user_info; +EXTERN UWORD station; /* station number */ + +EXTERN UBYTE login_enabled(VOID); /* LOGIN.C */ +EXTERN VOID login_station(VOID); /* LOGIN.C */ +EXTERN VOID login_consoles(VOID); /* LOGIN.C */ +EXTERN VOID lock_station(VOID); /* LOGIN.C */ +EXTERN WORD get_user_info(UWORD); /* LOGIN.C */ +EXTERN VOID time_stamp(UBYTE**,UBYTE*,UBYTE*); /* LOGIN.C */ +EXTERN VOID wait_for_enter(BOOLEAN); /* LOGIN.C */ +EXTERN WORD logout_user(VOID); /* LOGIN.C */ +EXTERN VOID login_save_initial_state(VOID); /* LOGIN.C */ +EXTERN BOOLEAN chk_mail(VOID); /* LOGIN.C */ +EXTERN UWORD aschextobin(BYTE*); /* LOGIN.C */ +EXTERN WORD sysnamecmp(UBYTE*,UBYTE*); /* LOGIN.C */ +EXTERN VOID logout(VOID); /* LOGIN.C */ +EXTERN VOID lock(VOID); /* LOGIN.C */ +EXTERN VOID cmd_logout(VOID); /* LOGIN.C */ +EXTERN VOID cmd_lock(VOID); /* LOGIN.C */ +EXTERN VOID logevent(UBYTE*,WORD); /* LOGIN.C */ +EXTERN BOOLEAN logged_in(VOID); /* LOGIN.C */ +EXTERN BOOLEAN waiting_on_login(VOID); /* LOGIN.C */ +EXTERN UWORD get_user_on_station(VOID); /* LOGIN.C */ +EXTERN BOOLEAN lock_requested(VOID); /* LOGIN.C */ + + +EXTERN VOID error_code(UWORD); /* COM.C */ +EXTERN VOID show_file(UWORD, BOOLEAN); /* COMINT.C */ +EXTERN VOID CDECL cmd_set(BYTE *); /* COMINT.C */ +EXTERN VOID CDECL cmd_cd(BYTE *); /* COMINT.C */ +EXTERN VOID CDECL cmd_exit(BYTE *); /* COMINT.C */ + +EXTERN BOOLEAN CDECL ansi_screen(VOID); /* LOGINASM.ASM */ +EXTERN VOID CDECL get_sys_path(UBYTE*); /* LOGINASM.ASM */ +EXTERN UBYTE CDECL background_proc(VOID); /* LOGINASM.ASM */ +EXTERN VOID CDECL disable_vc_switch(); /* LOGINASM.ASM */ +EXTERN VOID CDECL enable_vc_switch(); /* LOGINASM.ASM */ +EXTERN VOID CDECL disable(VOID); /* LOGINASM.ASM */ +EXTERN VOID CDECL enable(VOID); /* LOGINASM.ASM */ +EXTERN UWORD CDECL s_memory(UWORD); /* LOGINASM.ASM */ + +EXTERN UWORD CDECL heap_size(VOID); /* CSUP.ASM */ + +EXTERN PD FAR * CDECL pd; /* Far pointer to Current PD */ +EXTERN UWORD CDECL sysdat_seg; /* System Data Page */ +EXTERN UWORD _psp; /* PSP Segment */ + +struct qpb { + UWORD internal0; + UWORD id; + UWORD internal1; + UWORD *buffer; + UBYTE name[9]; + } ; + +struct apd { + UWORD pd; /* PD address */ + UWORD term; /* Process termination Code */ + UWORD cns; /* Console Number and Zero field*/ + BYTE name[PROCNAME_LGTH+1]; /* Process Name */ + }; + + + + diff --git a/COMMAND/MAKE.BAT b/COMMAND/MAKE.BAT new file mode 100644 index 0000000..546f8cd --- /dev/null +++ b/COMMAND/MAKE.BAT @@ -0,0 +1,122 @@ +@ECHO off +SET TOOLS=C:\TOOLS + +SET MASM=%TOOLS%\MASM.EXE +SET WATCOM=%TOOLS%\WATCOMC +SET WATCOMH=%TOOLS%\WATCOMC\H +SET WCG=%WATCOM%\BIN\WCGL.EXE +SET WCC=%WATCOM%\BIN\WCC.EXE +SET LINK510=%TOOLS%\LINK.EXE +SET BCC20=%TOOLS%\BCC.EXE +SET BCC20H=%TOOLS%\BCC20\H + +REM +REM YOU SHOULD NOT HAVE TO CHANGE ANYTHING BELOW THIS LINE. +REM + +REM Define local Caldera tools +SET LOCTOOLS=..\LTOOLS + +IF NOT EXIST BIN\*.* MD BIN + +REM Check if tools exist + +ECHO Checking for %MASM% +if not exist %MASM% goto badtool +ECHO Checking for %WCC% +if not exist %WCC% goto badtool +ECHO Checking for %LINK510% +if not exist %LINK510% goto badtool +ECHO Checking for %BCC20% +if not exist %BCC20% goto badtool + + +%MASM% message,.\bin\message; +IF ERRORLEVEL 1 GOTO FAILED +%MASM% resident,.\bin\resident; +IF ERRORLEVEL 1 GOTO FAILED +%MASM% txhelp,.\bin\txhelp; +IF ERRORLEVEL 1 GOTO FAILED + +%MASM% /DDOSPLUS /DWATCOMC /DPASCAL /DFINAL /MX /I.\ .\cstart.asm,.\bin\cstart.obj; +IF ERRORLEVEL 1 GOTO FAILED +%MASM% /DDOSPLUS /DWATCOMC /DPASCAL /DFINAL /MX /I.\ .\csup.asm,.\bin\csup.obj; +IF ERRORLEVEL 1 GOTO FAILED +%MASM% /DDOSPLUS /DWATCOMC /DPASCAL /DFINAL /MX /I.\ .\dosif.asm,.\bin\dosif.obj; +IF ERRORLEVEL 1 GOTO FAILED +%MASM% /DDOSPLUS /DWATCOMC /DPASCAL /DFINAL /MX /I.\ .\crit.asm,.\bin\crit.obj; +IF ERRORLEVEL 1 GOTO FAILED + +%WCC% /s /DFINAL /i=. /ms /os /dWATCOMC /i=%WATCOMH% /fo.\bin\com.obj .\com.c +IF ERRORLEVEL 1 GOTO FAILED +%WCC% /s /DFINAL /i=. /ms /os /dWATCOMC /i=%WATCOMH% /fo.\bin\comint.obj .\comint.c +IF ERRORLEVEL 1 GOTO FAILED +%WCC% /s /DFINAL /i=. /ms /os /dWATCOMC /i=%WATCOMH% /fo.\bin\support.obj .\support.c +IF ERRORLEVEL 1 GOTO FAILED + +%WCC% /s /DFINAL /i=. /ms /os /dWATCOMC /i=%WATCOMH% /fo.\bin\printf.obj .\printf.c +IF ERRORLEVEL 1 GOTO FAILED +%WCC% /s /DFINAL /i=. /ms /os /dWATCOMC /i=%WATCOMH% /fo.\bin\batch.obj .\batch.c +IF ERRORLEVEL 1 GOTO FAILED +%WCC% /s /DFINAL /i=. /ms /os /dWATCOMC /i=%WATCOMH% /fo.\bin\global.obj .\global.c +IF ERRORLEVEL 1 GOTO FAILED +%WCC% /s /DFINAL /i=. /ms /os /dWATCOMC /i=%WATCOMH% /fo.\bin\config.obj .\config.c +IF ERRORLEVEL 1 GOTO FAILED +%WCC% /s /DFINAL /i=. /ms /os /dWATCOMC /i=%WATCOMH% /fo.\bin\comcpy.obj .\comcpy.c +IF ERRORLEVEL 1 GOTO FAILED + +ECHO -w -d -f- -K -O -X -Z -c -ms -I%BCC20H% -DMESSAGE -DDOSPLUS -zSCGROUP -zTCODE -zR_MSG > RESP1 +ECHO -I.\ >> RESP1 +ECHO -o.\bin\cmdlist.obj .\cmdlist.c >> RESP1 +%BCC20% @resp1 +IF ERRORLEVEL 1 GOTO FAILED + +ECHO .\bin\cstart.obj .\bin\com.obj .\bin\csup.obj +> RESP2 +ECHO .\bin\dosif.obj .\bin\comint.obj .\bin\support.obj+>> RESP2 +ECHO .\bin\cmdlist.obj .\bin\printf.obj+>> RESP2 +ECHO .\bin\message.obj +>> RESP2 +ECHO .\bin\batch.obj .\bin\global.obj .\bin\config.obj+>> RESP2 +ECHO .\bin\comcpy.obj .\bin\crit.obj +>> RESP2 +ECHO +>> RESP2 +ECHO .\bin\resident.obj>> RESP2 +ECHO .\bin\command.exe>> RESP2 +ECHO .\command.map>> RESP2 +ECHO %WATCOM%\LIB\CLIBs>> RESP2 +%LINK510% /MAP @resp2; +IF ERRORLEVEL 1 GOTO FAILED + +%MASM% /DDOSPLUS /DWATCOMC /DPASCAL /DFINAL /MX /I.\ .\helpstub.asm,.\bin\helpstub.obj; +IF ERRORLEVEL 1 GOTO FAILED +ECHO .\bin\helpstub.obj+> RESP3 +ECHO .\bin\txhelp.obj>> RESP3 +ECHO .\bin\txhelp.exe>> RESP3 +%LINK510% @resp3; +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\exe2bin /S0000 .\bin\txhelp.exe .\bin\txhelp.bin +IF ERRORLEVEL 1 GOTO FAILED + +copy /b .\bin\command.exe+.\bin\txhelp.bin .\bin\command.com +goto exit + +:failed +ECHO Error in Build! +goto exit + +:badtool +ECHO Can't find that tool! + +:exit +REM ********************** +REM CLEAN UP THE AREA +REM ********************** +SET TOOLS= +SET MASM= +SET WCC= +SET LINK510= +SET BCC20= +SET WATCOMH= +SET BCC20H= +SET LOCTOOLS= + + \ No newline at end of file diff --git a/COMMAND/MESSAGE.ASM b/COMMAND/MESSAGE.ASM new file mode 100644 index 0000000..ebbec73 --- /dev/null +++ b/COMMAND/MESSAGE.ASM @@ -0,0 +1,514 @@ +NUL equ 0 +BS equ 8 +TAB equ 9 +LF equ 10 +CR equ 13 + +CGROUP group _MSG + +_MSG segment word public 'CODE' + assume ds:CGROUP, cs:CGROUP + +; Source .TFT file: 'TMP1.$$$' + public _msg_ver111 + public msg_ver111 +msg_ver111 label byte +_msg_ver111 db NUL , NUL + public _msg_lbl + public msg_lbl +msg_lbl label byte +_msg_lbl db LF, " Volume in drive %c ", NUL + public _msg_oklbl + public msg_oklbl +msg_oklbl label byte +_msg_oklbl db "is %s", NUL + public _msg_nolbl + public msg_nolbl +msg_nolbl label byte +_msg_nolbl db "does not have a label", NUL + public _msg_files + public msg_files +msg_files label byte +_msg_files db "File(s)", NUL + public _msg_free + public msg_free +msg_free label byte +_msg_free db "bytes free", NUL + public _msg_invalid_file + public msg_invalid_file +msg_invalid_file label byte +_msg_invalid_file db "Destination must be a file", NUL + public _msg_exist + public msg_exist +msg_exist label byte +_msg_exist db "%s files exist", LF, NUL + public _msg_ndir + public msg_ndir +msg_ndir label byte +_msg_ndir db "System", NUL + public _msg_nsys + public msg_nsys +msg_nsys label byte +_msg_nsys db "Directory", NUL + public _msg_badopt + public msg_badopt +msg_badopt label byte +_msg_badopt db "Invalid option: `%c%c'", NUL + public _msg_full + public msg_full +msg_full label byte +_msg_full db LF, "Disk full", LF, NUL + public _msg_devfail + public msg_devfail +msg_devfail label byte +_msg_devfail db LF, "Failure writing to device", LF, NUL + public _msg_syntax + public msg_syntax +msg_syntax label byte +_msg_syntax db "Syntax Error", LF, NUL + public _msg_badcmd + public msg_badcmd +msg_badcmd label byte +_msg_badcmd db "Command or filename not recognized", LF, NUL + public _msg_pathdrv + public msg_pathdrv +msg_pathdrv label byte +_msg_pathdrv db "Search path contains invalid drive", LF, NUL + public _msg_optline + public msg_optline +msg_optline label byte +_msg_optline db "%s (Y/N) ? ", NUL + public _msg_batterm + public msg_batterm +msg_batterm label byte +_msg_batterm db "Halt Batch Process (Y/N) ? ", NUL + public _msg_batmiss + public msg_batmiss +msg_batmiss label byte +_msg_batmiss db "Batch file %s missing", LF, NUL + public _msg_batnest + public msg_batnest +msg_batnest label byte +_msg_batnest db LF, "Batch files nested too deeply", LF, NUL + public _msg_dir + public msg_dir +msg_dir label byte +_msg_dir db " Directory of %s\%s", LF, NUL + public _msg_echo + public msg_echo +msg_echo label byte +_msg_echo db "ECHO = %s", LF, NUL + public _msg_xbatch + public msg_xbatch +msg_xbatch label byte +_msg_xbatch db "Batch Enhancer is %s", LF, NUL + public _msg_eraq + public msg_eraq +msg_eraq label byte +_msg_eraq db "%s (Y/N) ? ", NUL + public _msg_eraall + public msg_eraall +msg_eraall label byte +_msg_eraall db "Are you sure (Y/N) ? ", NUL + public _msg_era + public msg_era +msg_era label byte +_msg_era db "File not erased: %s - ", NUL + public _msg_label + public msg_label +msg_label label byte +_msg_label db "Label ""%s"" not found", NUL + public _msg_gosub + public msg_gosub +msg_gosub label byte +_msg_gosub db "GOSUBs nested too deeply", LF, NUL + public _msg_return + public msg_return +msg_return label byte +_msg_return db "RETURN without GOSUB encountered", LF, NUL + public _msg_mkdir + public msg_mkdir +msg_mkdir label byte +_msg_mkdir db "Unable to create directory", LF, NUL + public _msg_path + public msg_path +msg_path label byte +_msg_path db "No Path", LF, NUL + public _path_template + public path_template +path_template label byte +_path_template db "%.122s", LF, NUL + public _msg_ren + public msg_ren +msg_ren label byte +_msg_ren db "File already exists", LF, NUL + public _msg_use_rendir + public msg_use_rendir +msg_use_rendir label byte +_msg_use_rendir db "Use RENDIR to rename directories", LF, NUL + public _msg_rmdir + public msg_rmdir +msg_rmdir label byte +_msg_rmdir db "Directory invalid, in use, or not empty", LF, NUL + public _msg_break + public msg_break +msg_break label byte +_msg_break db "BREAK = %s", LF, NUL + public _msg_verify + public msg_verify +msg_verify label byte +_msg_verify db "VERIFY = %s", LF, NUL + public _msg_idle + public msg_idle +msg_idle label byte +_msg_idle db "IDLE detection is %s", LF, NUL + public _help_prog + public help_prog +help_prog label byte +_help_prog db "help$.exe", NUL + public _msg_nohelpprog + public msg_nohelpprog +msg_nohelpprog label byte +_msg_nohelpprog db "Cannot find help file HELP$.EXE", LF, NUL + public _help_com + public help_com +help_com label byte +_help_com db "COMMAND", TAB, "Executes a second copy of the default command processor.", LF, LF, "Syntax:", TAB, "COMMAND /H", LF, TAB, "COMMAND [dirpath][ /E:n][ /P[:filename]][ /Mx][ /Ccommand]", LF, LF, TAB + db "/H", TAB, "gives this screen.", LF, TAB, "dirpath", TAB, "drive and path to be used to reload COMMAND.COM.", LF, TAB, "/E:n", TAB, "allocate n number of bytes to the environment (512 default).", LF + db TAB, "/P", TAB, "Makes COMMAND.COM permanent. EXIT will not terminate it.", LF, TAB, TAB, "Optional filename causes filename to be used instead of", LF, TAB, TAB, "AUTOEXEC.BAT.", LF, TAB, "/" + db "C", TAB, "Executes ""command"" then terminates.", LF, TAB, "/ML", TAB, "Force resident portion to be in conventional (low) memory.", LF, TAB, "/MU", TAB, "Force resident portion to be in UPPER " + db "memory.", LF, TAB, "/MH", TAB, "Force resident portion to be in HIGH memory.", LF, LF, "Examples:", LF, TAB, "COMMAND /E:1024 /P", LF, TAB, "COMMAND /Cdir c:", LF, NUL + public _msg_curcp + public msg_curcp +msg_curcp label byte +_msg_curcp db "Active Code Page is %d", LF, NUL + public _msg_badcp + public msg_badcp +msg_badcp label byte +_msg_badcp db "Code Page %d has not been prepared", LF, NUL + public _msg_cpnf + public msg_cpnf +msg_cpnf label byte +_msg_cpnf db "Invalid Code Page, NLSFUNC not loaded, or COUNTRY.SYS not found", LF, NUL + public _msg_netsubst + public msg_netsubst +msg_netsubst label byte +_msg_netsubst db "Cannot SUBST a Networked Drive", LF, NUL + public _msg_netassign + public msg_netassign +msg_netassign label byte +_msg_netassign db "Cannot ASSIGN a Networked Drive", LF, NUL + public _msg_cpyright + public msg_cpyright +msg_cpyright label byte +_msg_cpyright db "Copyright (c) 1976, 1997 Caldera, Inc. ", LF, "All rights reserved.", LF, NUL + public _msg_serialno + public msg_serialno +msg_serialno label byte +_msg_serialno db "Serial number %s", LF, NUL + public _msg_oempatch + public msg_oempatch +msg_oempatch label byte +_msg_oempatch db "SeRiAlNuMbEr=", NUL + public _msg_serno + public msg_serno +msg_serno label byte +_msg_serno db 0, "XXX-0000-987654321X", NUL + public _msg_oemcpyrt + public msg_oemcpyrt +msg_oemcpyrt label byte +_msg_oemcpyrt db LF, "LICENSED FOR NON-COMMERCIAL USE ONLY", LF, 0, "FILLERFILLERFILLERFILLER", NUL + public _msg_version + public msg_version +msg_version label byte +_msg_version db LF, "Caldera OpenDOS %s.01", LF, NUL + public _msg_cpyself + public msg_cpyself +msg_cpyself label byte +_msg_cpyself db "Source and Destination cannot be the same file", LF, NUL + public _msg_fcopied + public msg_fcopied +msg_fcopied label byte +_msg_fcopied db " File(s) copied", LF, NUL + public _msg_envfull + public msg_envfull +msg_envfull label byte +_msg_envfull db "Environment Full", NUL + public _msg_enverr + public msg_enverr +msg_enverr label byte +_msg_enverr db "Environment error", NUL + public _msg_bados + public msg_bados +msg_bados label byte +_msg_bados db "Incorrect version of Operating System", LF, NUL + public _msg_loadpath + public msg_loadpath +msg_loadpath label byte +_msg_loadpath db "Invalid COMMAND search directory specified", LF, LF, NUL + public _msg_inop + public msg_inop +msg_inop label byte +_msg_inop db "Wrong number of parameters", LF, NUL + public _msg_binrd + public msg_binrd +msg_binrd label byte +_msg_binrd db "Binary reads from a device are not allowed", LF, NUL + public _msg_dlost + public msg_dlost +msg_dlost label byte +_msg_dlost db "Destination file contents lost before copy", LF, NUL + public _msg_onoff + public msg_onoff +msg_onoff label byte +_msg_onoff db "ON or OFF parameter required", LF, NUL + public _err_file + public err_file +err_file label byte +_err_file db "Filename too long", LF, NUL + public _err02 + public err02 +err02 label byte +_err02 db "File not found", NUL + public _err03 + public err03 +err03 label byte +_err03 db "Invalid directory specified", NUL + public _err04 + public err04 +err04 label byte +_err04 db "Too many files open", NUL + public _err05 + public err05 +err05 label byte +_err05 db "Access denied", NUL + public _err08 + public err08 +err08 label byte +_err08 db "Not enough Memory", NUL + public _err15 + public err15 +err15 label byte +_err15 db "Invalid drive specified", NUL + public _err19 + public err19 +err19 label byte +_err19 db "Disk write-protected", NUL + public _err20 + public err20 +err20 label byte +_err20 db "File Sharing Conflict", NUL + public _err83 + public err83 +err83 label byte +_err83 db "Physical Media Error", NUL + public _err86 + public err86 +err86 label byte +_err86 db "Invalid Password", NUL + public _msg_needpath + public msg_needpath +msg_needpath label byte +_msg_needpath db "Path required", NUL + public _msg_needfile + public msg_needfile +msg_needfile label byte +_msg_needfile db "Filename(s) required", NUL + public _msg_needdev + public msg_needdev +msg_needdev label byte +_msg_needdev db "Device name required", NUL + public _msg_drv_invalid + public msg_drv_invalid +msg_drv_invalid label byte +_msg_drv_invalid db "Current drive is no longer valid", NUL + public _sun_d + public sun_d +sun_d label byte +_sun_d db "Sun", NUL + public _mon_d + public mon_d +mon_d label byte +_mon_d db "Mon", NUL + public _tue_d + public tue_d +tue_d label byte +_tue_d db "Tue", NUL + public _wed_d + public wed_d +wed_d label byte +_wed_d db "Wed", NUL + public _thu_d + public thu_d +thu_d label byte +_thu_d db "Thu", NUL + public _fri_d + public fri_d +fri_d label byte +_fri_d db "Fri", NUL + public _sat_d + public sat_d +sat_d label byte +_sat_d db "Sat", NUL + public _jan_m + public jan_m +jan_m label byte +_jan_m db "January", NUL + public _feb_m + public feb_m +feb_m label byte +_feb_m db "February", NUL + public _mar_m + public mar_m +mar_m label byte +_mar_m db "March", NUL + public _apr_m + public apr_m +apr_m label byte +_apr_m db "April", NUL + public _may_m + public may_m +may_m label byte +_may_m db "May", NUL + public _jun_m + public jun_m +jun_m label byte +_jun_m db "June", NUL + public _jul_m + public jul_m +jul_m label byte +_jul_m db "July", NUL + public _aug_m + public aug_m +aug_m label byte +_aug_m db "August", NUL + public _sep_m + public sep_m +sep_m label byte +_sep_m db "September", NUL + public _oct_m + public oct_m +oct_m label byte +_oct_m db "October", NUL + public _nov_m + public nov_m +nov_m label byte +_nov_m db "November", NUL + public _dec_m + public dec_m +dec_m label byte +_dec_m db "December", NUL + public _am_time + public am_time +am_time label byte +_am_time db "am", NUL + public _pm_time + public pm_time +pm_time label byte +_pm_time db "pm", NUL + public _greeting_morning + public greeting_morning +greeting_morning label byte +_greeting_morning db "morning", NUL + public _greeting_afternoon + public greeting_afternoon +greeting_afternoon label byte +_greeting_afternoon db "afternoon", NUL + public _greeting_evening + public greeting_evening +greeting_evening label byte +_greeting_evening db "evening", NUL + public _cur_time + public cur_time +cur_time label byte +_cur_time db "Time: ", NUL + public _new_time + public new_time +new_time label byte +_new_time db LF, "Enter time: ", NUL + public _inv_time + public inv_time +inv_time label byte +_inv_time db LF, "Invalid time specified", NUL + public _cur_date + public cur_date +cur_date label byte +_cur_date db "Date: ", NUL + public _new_date + public new_date +new_date label byte +_new_date db LF, "Enter date (%s): ", NUL + public _inv_date + public inv_date +inv_date label byte +_inv_date db LF, "Invalid date specified", NUL + public _us_date + public us_date +us_date label byte +_us_date db "mm-dd-yy", NUL + public _euro_date + public euro_date +euro_date label byte +_euro_date db "dd-mm-yy", NUL + public _jap_date + public jap_date +jap_date label byte +_jap_date db "yy-mm-dd", NUL + public _inv_num + public inv_num +inv_num label byte +_inv_num db "Invalid Number", LF, NUL + public _msg_inactive + public msg_inactive +msg_inactive label byte +_msg_inactive db "Input Redirection Already Active", NUL + public _msg_outactive + public msg_outactive +msg_outactive label byte +_msg_outactive db "Output Redirection Already Active", NUL + public _msg_on + public msg_on +msg_on label byte +_msg_on db "on", NUL + public _msg_off + public msg_off +msg_off label byte +_msg_off db "off", NUL + public _yes_no + public yes_no +yes_no label byte +_yes_no db "YN", NUL + public _msg_pause + public msg_pause +msg_pause label byte +_msg_pause db "Strike a key when ready . . . ", NUL + public _msg_disabled + public msg_disabled +msg_disabled label byte +_msg_disabled db "IDLE is disabled", NUL + public _msg_internal + public msg_internal +msg_internal label byte +_msg_internal db "Internal Error Code %03d", NUL + public _msg_network + public msg_network +msg_network label byte +_msg_network db "Network Error %03d", NUL + public _msg_debug + public msg_debug +msg_debug label byte +_msg_debug db "DEBUG is %s", LF, NUL + public _msg_longjmp + public msg_longjmp +msg_longjmp label byte +_msg_longjmp db "LONGJMP Error %d", LF, NUL + public _msg_nohelp + public msg_nohelp +msg_nohelp label byte +_msg_nohelp db "Unable to give Help. Cannot find file %s.", LF, NUL + +_MSG ends + + + end + \ No newline at end of file diff --git a/COMMAND/MESSAGE.DEF b/COMMAND/MESSAGE.DEF new file mode 100644 index 0000000..d183d66 --- /dev/null +++ b/COMMAND/MESSAGE.DEF @@ -0,0 +1,246 @@ + extrn _am_time : byte + extrn am_time : byte + extrn _apr_m : byte + extrn apr_m : byte + extrn _aug_m : byte + extrn aug_m : byte + extrn _cur_date : byte + extrn cur_date : byte + extrn _cur_time : byte + extrn cur_time : byte + extrn _dec_m : byte + extrn dec_m : byte + extrn _err02 : byte + extrn err02 : byte + extrn _err03 : byte + extrn err03 : byte + extrn _err04 : byte + extrn err04 : byte + extrn _err05 : byte + extrn err05 : byte + extrn _err08 : byte + extrn err08 : byte + extrn _err15 : byte + extrn err15 : byte + extrn _err19 : byte + extrn err19 : byte + extrn _err20 : byte + extrn err20 : byte + extrn _err83 : byte + extrn err83 : byte + extrn _err86 : byte + extrn err86 : byte + extrn _err_file : byte + extrn err_file : byte + extrn _euro_date : byte + extrn euro_date : byte + extrn _feb_m : byte + extrn feb_m : byte + extrn _fri_d : byte + extrn fri_d : byte + extrn _greeting_afternoon : byte + extrn greeting_afternoon : byte + extrn _greeting_evening : byte + extrn greeting_evening : byte + extrn _greeting_morning : byte + extrn greeting_morning : byte + extrn _help_com : byte + extrn help_com : byte + extrn _help_prog : byte + extrn help_prog : byte + extrn _inv_date : byte + extrn inv_date : byte + extrn _inv_num : byte + extrn inv_num : byte + extrn _inv_time : byte + extrn inv_time : byte + extrn _jan_m : byte + extrn jan_m : byte + extrn _jap_date : byte + extrn jap_date : byte + extrn _jul_m : byte + extrn jul_m : byte + extrn _jun_m : byte + extrn jun_m : byte + extrn _mar_m : byte + extrn mar_m : byte + extrn _may_m : byte + extrn may_m : byte + extrn _mon_d : byte + extrn mon_d : byte + extrn _msg_badcmd : byte + extrn msg_badcmd : byte + extrn _msg_badcp : byte + extrn msg_badcp : byte + extrn _msg_badopt : byte + extrn msg_badopt : byte + extrn _msg_bados : byte + extrn msg_bados : byte + extrn _msg_batmiss : byte + extrn msg_batmiss : byte + extrn _msg_batnest : byte + extrn msg_batnest : byte + extrn _msg_batterm : byte + extrn msg_batterm : byte + extrn _msg_binrd : byte + extrn msg_binrd : byte + extrn _msg_break : byte + extrn msg_break : byte + extrn _msg_cpnf : byte + extrn msg_cpnf : byte + extrn _msg_cpyright : byte + extrn msg_cpyright : byte + extrn _msg_cpyself : byte + extrn msg_cpyself : byte + extrn _msg_curcp : byte + extrn msg_curcp : byte + extrn _msg_debug : byte + extrn msg_debug : byte + extrn _msg_devfail : byte + extrn msg_devfail : byte + extrn _msg_dir : byte + extrn msg_dir : byte + extrn _msg_disabled : byte + extrn msg_disabled : byte + extrn _msg_dlost : byte + extrn msg_dlost : byte + extrn _msg_drv_invalid : byte + extrn msg_drv_invalid : byte + extrn _msg_echo : byte + extrn msg_echo : byte + extrn _msg_enverr : byte + extrn msg_enverr : byte + extrn _msg_envfull : byte + extrn msg_envfull : byte + extrn _msg_era : byte + extrn msg_era : byte + extrn _msg_eraall : byte + extrn msg_eraall : byte + extrn _msg_eraq : byte + extrn msg_eraq : byte + extrn _msg_exist : byte + extrn msg_exist : byte + extrn _msg_fcopied : byte + extrn msg_fcopied : byte + extrn _msg_files : byte + extrn msg_files : byte + extrn _msg_free : byte + extrn msg_free : byte + extrn _msg_full : byte + extrn msg_full : byte + extrn _msg_gosub : byte + extrn msg_gosub : byte + extrn _msg_idle : byte + extrn msg_idle : byte + extrn _msg_inactive : byte + extrn msg_inactive : byte + extrn _msg_inop : byte + extrn msg_inop : byte + extrn _msg_internal : byte + extrn msg_internal : byte + extrn _msg_invalid_file : byte + extrn msg_invalid_file : byte + extrn _msg_label : byte + extrn msg_label : byte + extrn _msg_lbl : byte + extrn msg_lbl : byte + extrn _msg_loadpath : byte + extrn msg_loadpath : byte + extrn _msg_longjmp : byte + extrn msg_longjmp : byte + extrn _msg_mkdir : byte + extrn msg_mkdir : byte + extrn _msg_ndir : byte + extrn msg_ndir : byte + extrn _msg_needdev : byte + extrn msg_needdev : byte + extrn _msg_needfile : byte + extrn msg_needfile : byte + extrn _msg_needpath : byte + extrn msg_needpath : byte + extrn _msg_netassign : byte + extrn msg_netassign : byte + extrn _msg_netsubst : byte + extrn msg_netsubst : byte + extrn _msg_network : byte + extrn msg_network : byte + extrn _msg_nohelp : byte + extrn msg_nohelp : byte + extrn _msg_nohelpprog : byte + extrn msg_nohelpprog : byte + extrn _msg_nolbl : byte + extrn msg_nolbl : byte + extrn _msg_nsys : byte + extrn msg_nsys : byte + extrn _msg_oemcpyrt : byte + extrn msg_oemcpyrt : byte + extrn _msg_oempatch : byte + extrn msg_oempatch : byte + extrn _msg_off : byte + extrn msg_off : byte + extrn _msg_oklbl : byte + extrn msg_oklbl : byte + extrn _msg_on : byte + extrn msg_on : byte + extrn _msg_onoff : byte + extrn msg_onoff : byte + extrn _msg_optline : byte + extrn msg_optline : byte + extrn _msg_outactive : byte + extrn msg_outactive : byte + extrn _msg_path : byte + extrn msg_path : byte + extrn _msg_pathdrv : byte + extrn msg_pathdrv : byte + extrn _msg_pause : byte + extrn msg_pause : byte + extrn _msg_ren : byte + extrn msg_ren : byte + extrn _msg_return : byte + extrn msg_return : byte + extrn _msg_rmdir : byte + extrn msg_rmdir : byte + extrn _msg_serialno : byte + extrn msg_serialno : byte + extrn _msg_serno : byte + extrn msg_serno : byte + extrn _msg_syntax : byte + extrn msg_syntax : byte + extrn _msg_use_rendir : byte + extrn msg_use_rendir : byte + extrn _msg_ver111 : byte + extrn msg_ver111 : byte + extrn _msg_verify : byte + extrn msg_verify : byte + extrn _msg_version : byte + extrn msg_version : byte + extrn _msg_xbatch : byte + extrn msg_xbatch : byte + extrn _new_date : byte + extrn new_date : byte + extrn _new_time : byte + extrn new_time : byte + extrn _nov_m : byte + extrn nov_m : byte + extrn _oct_m : byte + extrn oct_m : byte + extrn _path_template : byte + extrn path_template : byte + extrn _pm_time : byte + extrn pm_time : byte + extrn _sat_d : byte + extrn sat_d : byte + extrn _sep_m : byte + extrn sep_m : byte + extrn _sun_d : byte + extrn sun_d : byte + extrn _thu_d : byte + extrn thu_d : byte + extrn _tue_d : byte + extrn tue_d : byte + extrn _us_date : byte + extrn us_date : byte + extrn _wed_d : byte + extrn wed_d : byte + extrn _yes_no : byte + extrn yes_no : byte diff --git a/COMMAND/MESSAGE.H b/COMMAND/MESSAGE.H new file mode 100644 index 0000000..adf4b83 --- /dev/null +++ b/COMMAND/MESSAGE.H @@ -0,0 +1,123 @@ +extern char near am_time[]; +extern char near apr_m[]; +extern char near aug_m[]; +extern char near cur_date[]; +extern char near cur_time[]; +extern char near dec_m[]; +extern char near err02[]; +extern char near err03[]; +extern char near err04[]; +extern char near err05[]; +extern char near err08[]; +extern char near err15[]; +extern char near err19[]; +extern char near err20[]; +extern char near err83[]; +extern char near err86[]; +extern char near err_file[]; +extern char near euro_date[]; +extern char near feb_m[]; +extern char near fri_d[]; +extern char near greeting_afternoon[]; +extern char near greeting_evening[]; +extern char near greeting_morning[]; +extern char near help_com[]; +extern char near help_prog[]; +extern char near inv_date[]; +extern char near inv_num[]; +extern char near inv_time[]; +extern char near jan_m[]; +extern char near jap_date[]; +extern char near jul_m[]; +extern char near jun_m[]; +extern char near mar_m[]; +extern char near may_m[]; +extern char near mon_d[]; +extern char near msg_badcmd[]; +extern char near msg_badcp[]; +extern char near msg_badopt[]; +extern char near msg_bados[]; +extern char near msg_batmiss[]; +extern char near msg_batnest[]; +extern char near msg_batterm[]; +extern char near msg_binrd[]; +extern char near msg_break[]; +extern char near msg_cpnf[]; +extern char near msg_cpyright[]; +extern char near msg_cpyself[]; +extern char near msg_curcp[]; +extern char near msg_debug[]; +extern char near msg_devfail[]; +extern char near msg_dir[]; +extern char near msg_disabled[]; +extern char near msg_dlost[]; +extern char near msg_drv_invalid[]; +extern char near msg_echo[]; +extern char near msg_enverr[]; +extern char near msg_envfull[]; +extern char near msg_era[]; +extern char near msg_eraall[]; +extern char near msg_eraq[]; +extern char near msg_exist[]; +extern char near msg_fcopied[]; +extern char near msg_files[]; +extern char near msg_free[]; +extern char near msg_full[]; +extern char near msg_gosub[]; +extern char near msg_idle[]; +extern char near msg_inactive[]; +extern char near msg_inop[]; +extern char near msg_internal[]; +extern char near msg_invalid_file[]; +extern char near msg_label[]; +extern char near msg_lbl[]; +extern char near msg_loadpath[]; +extern char near msg_longjmp[]; +extern char near msg_mkdir[]; +extern char near msg_ndir[]; +extern char near msg_needdev[]; +extern char near msg_needfile[]; +extern char near msg_needpath[]; +extern char near msg_netassign[]; +extern char near msg_netsubst[]; +extern char near msg_network[]; +extern char near msg_nohelp[]; +extern char near msg_nohelpprog[]; +extern char near msg_nolbl[]; +extern char near msg_nsys[]; +extern char near msg_oemcpyrt[]; +extern char near msg_oempatch[]; +extern char near msg_off[]; +extern char near msg_oklbl[]; +extern char near msg_on[]; +extern char near msg_onoff[]; +extern char near msg_optline[]; +extern char near msg_outactive[]; +extern char near msg_path[]; +extern char near msg_pathdrv[]; +extern char near msg_pause[]; +extern char near msg_ren[]; +extern char near msg_return[]; +extern char near msg_rmdir[]; +extern char near msg_serialno[]; +extern char near msg_serno[]; +extern char near msg_syntax[]; +extern char near msg_use_rendir[]; +extern char near msg_ver111[]; +extern char near msg_verify[]; +extern char near msg_version[]; +extern char near msg_xbatch[]; +extern char near new_date[]; +extern char near new_time[]; +extern char near nov_m[]; +extern char near oct_m[]; +extern char near path_template[]; +extern char near pm_time[]; +extern char near sat_d[]; +extern char near sep_m[]; +extern char near sun_d[]; +extern char near thu_d[]; +extern char near tue_d[]; +extern char near us_date[]; +extern char near wed_d[]; +extern char near yes_no[]; diff --git a/COMMAND/MSDOS.EQU b/COMMAND/MSDOS.EQU new file mode 100644 index 0000000..6b4738f --- /dev/null +++ b/COMMAND/MSDOS.EQU @@ -0,0 +1,131 @@ +; File : $Workfile: MSDOS.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; MSDOS.EQU 1.1 92/11/10 10:48:56 +; Added to appslib source directory. +; ENDLOG + +MS_P_TERMCPM equ 00H +MS_C_READ equ 01H +MS_C_WRITE equ 02H +MS_A_READ equ 03H +MS_A_WRITE equ 04H +MS_L_WRITE equ 05H +MS_C_RAWIO equ 06H +MS_C_RAWIN equ 07H +MS_C_NOECHO equ 08H +MS_C_WRITESTR equ 09H +MS_C_READSTR equ 0aH +MS_C_STAT equ 0bH +MS_C_FLUSH equ 0cH +MS_DRV_ALLRESET equ 0dH +MS_DRV_SET equ 0eH +MS_F_OPEN equ 0fH +MS_F_CLOSE equ 10H +MS_F_SFIRST equ 11H +MS_F_SNEXT equ 12H +MS_F_DELETE equ 13H +MS_F_READ equ 14H +MS_F_WRITE equ 15H +MS_F_MAKE equ 16H +MS_F_RENAME equ 17H +MS_DRV_GET equ 19H +MS_F_DMAOFF equ 1aH +MS_DRV_ALLOC equ 1bH +MS_DRV_ALLOCSPEC equ 1cH +MS_F_READRAND equ 21H +MS_F_WRITERAND equ 22H +MS_F_SIZE equ 23H +MS_F_RANDREC equ 24H +MS_S_SETINT equ 25H +MS_P_MKPSP equ 26H +MS_F_READBLK equ 27H +MS_F_WRITEBLK equ 28H +MS_F_PARSE equ 29H +MS_T_GETDATE equ 2aH +MS_T_SETDATE equ 2bH +MS_T_GETTIME equ 2cH +MS_T_SETTIME equ 2dH +MS_F_VERIFY equ 2eH +MS_F_DMAGET equ 2fH +MS_S_BDOSVER equ 30H +MS_P_TERMKEEP equ 31H +MS_S_BREAK equ 33H +MS_S_GETINT equ 35H +MS_DRV_SPACE equ 36H +MS_S_COUNTRY equ 38H +MS_X_MKDIR equ 39H +MS_X_RMDIR equ 3aH +MS_X_CHDIR equ 3bH +MS_X_CREAT equ 3cH +MS_X_OPEN equ 3dH +MS_X_CLOSE equ 3eH +MS_X_READ equ 3fH +MS_X_WRITE equ 40H +MS_X_UNLINK equ 41H +MS_X_LSEEK equ 42H +MS_X_CHMOD equ 43H +MS_X_IOCTL equ 44H +MS_X_DUP equ 45H +MS_X_DUP2 equ 46H +MS_X_CURDIR equ 47H +MS_M_ALLOC equ 48H +MS_M_FREE equ 49H +MS_M_SETBLOCK equ 4aH +MS_X_EXEC equ 4bH +MS_X_EXIT equ 4cH +MS_X_WAIT equ 4dH +MS_X_FIRST equ 4eH +MS_X_NEXT equ 4fH +MS_P_SETPSP equ 50H +MS_F_GETVERIFY equ 54H +MS_X_RENAME equ 56H +MS_X_DATETIME equ 57H +MS_M_STRATEGY equ 58h +MS_F_ERROR equ 59H +MS_X_MKTEMP equ 5aH +MS_X_MKNEW equ 5bH +MS_F_LOCK equ 5cH +MS_X_EXPAND equ 60H +MS_P_GETPSP equ 62H +MS_X_GETCP equ 6601h +MS_X_SETCP equ 6602h +MS_X_SETHC equ 67h +MS_X_COMMIT equ 68h + +DOS_INT equ 21h ; DOS Entry Point +; +STDIN equ 0 ; Standard Console Input Handle +STDOUT equ 1 ; Standard Console Output Handle +STDERR equ 2 ; Standard Error Output +STDAUX equ 3 ; Auxilary Device Handle +STDPRN equ 4 ; Printer Device Handle diff --git a/COMMAND/MSERROR.EQU b/COMMAND/MSERROR.EQU new file mode 100644 index 0000000..814bb1f --- /dev/null +++ b/COMMAND/MSERROR.EQU @@ -0,0 +1,121 @@ +; File : $MSERROR.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG + +ED_FUNCTION equ -01 ; invalid function number +ED_FILE equ -02 ; file not found +ED_PATH equ -03 ; path not found +ED_HANDLE equ -04 ; too many open files +ED_ACCESS equ -05 ; file access denied +ED_H_MATCH equ -06 ; invalid handle number +ED_DMD equ -07 ; memory descriptor destroyed +ED_MEMORY equ -08 ; insufficient memory +ED_BLOCK equ -09 ; invalid memory block addr +ED_ENVIRON equ -10 ; invalid environment +ED_FORMAT equ -11 ; invalid format +ED_ACC_CODE equ -12 ; invalid access code +ED_DATA equ -13 ; invalid data +ED_DRIVE equ -15 ; invalid drive specified +ED_DIR equ -16 ; can't remove current dir +ED_DEVICE equ -17 ; not same device +ED_ROOM equ -18 ; no more files + +ED_PROTECT equ -19 ; disk write protected +ED_BADUNIT equ -20 ; invalid drive specified +ED_NOTREADY equ -21 ; drive doesn't respond +ED_BADCMD equ -22 ; invalid command to driver +ED_BADDATA equ -23 ; data CRC error +ED_BADRHLEN equ -24 ; (shouldn't happen) +ED_BADSEEK equ -25 ; can't seek to track +ED_BADMEDIA equ -26 ; unrecognizable medium +ED_RNF equ -27 ; record/sector not found +ED_NOPAPER equ -28 ; printer error +ED_WRFAIL equ -29 ; write failed +ED_RDFAIL equ -30 ; read failed +ED_GENFAIL equ -31 ; anything failed +ED_SHAREFAIL equ -32 ; sharing conflict +ED_LOCKFAIL equ -33 ; locking conflict +ED_DISKCHG equ -34 ; invalid disk change +ED_NOFCBS equ -35 ; FCB table exhausted +ED_NOLOCKS equ -36 ; lock list items exhausted +ED_NET equ -50 ; Network Request Not Supported + +ED_NETACCESS equ -65 ; file access denied + +ED_NETPWD equ -73 ; Server Password Error +ED_NETVER equ -74 ; Incorrect Server version +ED_NETREQ equ -75 ; No Local Network Resources +ED_NETTIME equ -76 ; Network Time Out Error +ED_NETCOMM equ -77 ; Network Communications Error +ED_NETSRVR equ -78 ; No Server Network Resources +ED_NETLOG equ -79 ; Server Not Logged In + +ED_EXISTS equ -80 ; file already exists +ED_MAKE equ -82 ; Cannot Make (Files ??) +ED_FAIL equ -83 ; FAIL code returned from INT 24 +ED_STRUCT equ -84 ; Out of Structures +ED_ASSIGN equ -85 ; Already Assigned +ED_PASSWORD equ -86 ; Invalid Password +ED_PARAM equ -87 ; Invalid Parameter +ED_NETWRITE equ -88 ; Network write fault +ED_NETFUNC equ -89 ; Function not supported on network +ED_COMPONENT equ -90 ; system component not installed +ED_LASTERROR equ -90 ; Last Error Number Used + +CLASS_RESOURCE equ 1 ; Out of Resource +CLASS_TEMP equ 2 ; Temporary Situation +CLASS_AUTHOR equ 3 ; Authorization Error +CLASS_INTERNAL equ 4 ; Internal System Software Error +CLASS_HARDWARE equ 5 ; Hardware Failure +CLASS_SYSTEM equ 6 ; Serious System Failure +CLASS_APPLIC equ 7 ; Application Program Error +CLASS_LOST equ 8 ; File/Item Not Found +CLASS_FORMAT equ 9 ; File/Item Illegal Format +CLASS_LOCKED equ 10 ; File/Item Locked +CLASS_MEDIA equ 11 ; Media Failure +CLASS_EXISTS equ 12 ; Item Already Exists +CLASS_UNKNOWN equ 13 ; Unknown Classification + +ACT_RETRY equ 1 ; Retry a few times then prompt user +ACT_DELAY equ 2 ; Delay then as ACT_RETRY +ACT_USER equ 3 ; Prompt user to re-enter data +ACT_ABORT equ 4 ; Clean Up then ABORT the process +ACT_TERM equ 5 ; Terminate immeadiately NO CLEAN UP +ACT_IGNORE equ 6 ; Ignore the Error +ACT_URETRY equ 7 ; Retry the error after user intervention + +LOC_UNKNOWN equ 1 ; Unknown error location +LOC_BLOCK equ 2 ; Block Device Failure +LOC_NET equ 3 ; Network Failure +LOC_CHAR equ 4 ; Related to Serial/Character devices +LOC_MEMORY equ 5 ; Failure related to Memory diff --git a/COMMAND/MSERROR.H b/COMMAND/MSERROR.H new file mode 100644 index 0000000..91bdd45 --- /dev/null +++ b/COMMAND/MSERROR.H @@ -0,0 +1,102 @@ +/* File : $Workfile: MSERROR.H$ + * + * Description : Part of APPSLIB. + * + * Original Author : DIGITAL RESEARCH + * + * Last Edited By : $CALDERA$ + * + *-----------------------------------------------------------------------; + * Copyright Work of Caldera, Inc. All Rights Reserved. + * + * THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, + * PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. + * ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES + * WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF + * THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO + * HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE + * AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE + * AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, + * COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, + * CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, + * TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF + * CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT + * AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND + * CIVIL LIABILITY. + * ----------------------------------------------------------------------; + * + * *** Current Edit History *** + * *** End of Current Edit History *** + * + * $Log$ + * + * MSERROR.H 1.1 92/11/09 13:39:14 AHAY + * Converted to new build environment and version control system. + * + * + * ENDLOG + */ + +#define ED_OK 0 /* no error occured */ +#define ED_FUNCTION (-1) /* invalid function number */ +#define ED_FILE (-2) /* file not found */ +#define ED_PATH (-3) /* path not found */ +#define ED_HANDLE (-4) /* too many open files */ +#define ED_ACCESS (-5) /* file access denied */ +#define ED_H_MATCH (-6) /* invalid handle number */ +#define ED_DMD (-7) /* memory descriptor destroyed */ +#define ED_MEMORY (-8) /* insufficient memory */ +#define ED_BLOCK (-9) /* invalid memory block addr */ +#define ED_ENVIRON (-10) /* invalid environment */ +#define ED_FORMAT (-11) /* invalid format */ +#define ED_ACC_CODE (-12) /* invalid access code */ +#define ED_DATA (-13) /* invalid data */ +#define ED_DRIVE (-15) /* invalid drive specified */ +#define ED_DIR (-16) /* can't remove current dir */ +#define ED_DEVICE (-17) /* not same device */ +#define ED_ROOM (-18) /* no more files */ + +#define ED_PROTECT (-19) /* disk write protected */ +#define ED_BADUNIT (-20) /* invalid drive specified */ +#define ED_NOTREADY (-21) /* drive doesn't respond */ +#define ED_BADCMD (-22) /* invalid command to driver */ +#define ED_BADDATA (-23) /* data CRC error */ +#define ED_BADSEEK (-25) /* can't seek to track */ +#define ED_BADMEDIA (-26) /* unrecognizable medium */ +#define ED_RNF (-27) /* record/sector not found */ +#define ED_NOPAPER (-28) /* printer error */ +#define ED_WRFAIL (-29) /* write failed */ +#define ED_RDFAIL (-30) /* read failed */ +#define ED_GENFAIL (-31) /* anything failed */ +#define ED_SHAREFAIL (-32) /* sharing conflict */ +#define ED_LOCKFAIL (-33) /* locking conflict */ +#define ED_DISKCHG (-34) /* invalid disk change */ +#define ED_NOFCBS (-35) /* FCB table exhausted */ +#define ED_NOLOCKS (-36) /* lock list items exhausted */ + +#define ED_NET (-50) /* Network request not supported */ + +#define ED_NETACCESS (-65) /* file access denied */ + +#define ED_NETPWD (-73) /* Server Password Error */ +#define ED_NETVER (-74) /* Incorrect Server version */ +#define ED_NETREQ (-75) /* No Local Network Resources */ +#define ED_NETTIME (-76) /* Network Time Out Error */ +#define ED_NETCOMM (-77) /* Network Communications Error */ +#define ED_NETSRVR (-78) /* No Server Network Resources */ +#define ED_NETLOG (-79) /* Server Not Logged In */ + +#define ED_EXISTS (-80) /* file already exists */ +#define ED_MAKE (-82) /* cannot make (files ??) */ +#define ED_FAIL (-83) /* FAIL code returned from INT 24 */ +#define ED_STRUCT (-84) /* out of structures */ +#define ED_ASSIGN (-85) /* already assigned */ +#define ED_PASSWORD (-86) /* invalid password */ +#define ED_PARAM (-87) /* invalid parameter */ +#define ED_NETWRITE (-88) /* network write fault */ +#define ED_NETFUNC (-89) /* function not supported on network */ +#define ED_COMPONENT (-90) /* component not installed */ +#define ED_LASTERROR (-90) /* last error number used */ + +#define ACTION_USER 3 /* ask user to reenter input */ +#define ACTION_USER_INT 7 /* user intervention required */ diff --git a/COMMAND/PORTAB.H b/COMMAND/PORTAB.H new file mode 100644 index 0000000..82cd917 --- /dev/null +++ b/COMMAND/PORTAB.H @@ -0,0 +1,209 @@ +/**************************************************************************** +; File : $Workfile$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +* +* C P / M C R U N T I M E L I B H E A D E R F I L E +* ------------------------------------------------------------- +* +* This is an include file for assisting the user to write portable +* programs for C. All processor dependencies should be located here. +* +****************************************************************************/ + +#ifdef drc +#define DRC +#endif + +/* + * Standard type definitions + */ +#define BYTE char /* Signed byte */ +#ifdef DRC +#define UBYTE char /* Unsigned byte */ +#else +#define UBYTE unsigned char /* Unsigned byte */ +#endif +#define BOOLEAN int /* 2 valued (true/false) */ +#define WORD int /* Signed word (16 bits) */ +#define UWORD unsigned int /* unsigned word */ + +#define LONG long /* signed long (32 bits) */ +#ifdef DRC +#define ULONG long /* Unsigned long */ +#else +#define ULONG unsigned long /* Unsigned long */ +#endif + +#define REG register /* register variable */ +#define LOCAL auto /* Local var on 68000 */ +#define EXTERN extern /* External variable */ +#define MLOCAL static /* Local to module */ +#define GLOBAL /**/ /* Global variable */ +#define VOID void +#define DEFAULT int /* Default size */ +#define FLOAT float /* Floating Point */ +#define DOUBLE double /* Double precision */ + +#ifdef __WATCOMC__ /* Watcom C Version 7.00 */ +/* define pragma for 'cdecl' keyword to match Microsoft conventions */ +#pragma aux cdecl "_*" parm caller []\ + value struct float struct routine [ax] modify [ax bx cx dx es]; + +#pragma aux pascal "*" parm routine reverse []\ + value struct float struct routine [ax] modify [ax bx cx dx es]; +/*#define WATCOMC 1 /* Watcom C v7.0 */ +#define CDECL cdecl /* C calling convention */ +#define PASCAL pascal /* Pascal Calling Convention */ +#define FAR far /* FAR pointer or Function */ +#define NEAR near /* NEAR pointer or Function */ +#define CONST /**/ /* CONSTANT Value */ +#define VOLATILE /**/ /* VOLATILE must Always Read */ + +#else +#ifdef MSC +#define CDECL cdecl /* C calling convention */ +#define PASCAL pascal /* Pascal Calling Convention */ +#define FAR far /* FAR pointer or Function */ +#define NEAR near /* NEAR pointer or Function */ +#define CONST /**/ /* CONSTANT Value */ +#define VOLATILE /**/ /* VOLATILE must Always Read */ + +#else +#ifdef MSC5 +#define CDECL cdecl /* C calling convention */ +#define PASCAL pascal /* Pascal Calling Convention */ +#define FAR far /* FAR pointer or Function */ +#define NEAR near /* NEAR pointer or Function */ +#define CONST const /* CONSTANT value -- R/O */ +#define VOLATILE volatile /* VOLATILE must always read */ + +#else +#ifdef __TURBOC__ /* Borland TurboC Ver 1.50 */ +#define TURBOC 1 /* Define TURBOC */ +#define CDECL cdecl /* C calling convention */ +#define PASCAL pascal /* Pascal Calling Convention */ +#define FAR far /* FAR pointer or Function */ +#define NEAR near /* NEAR pointer or Function */ +#define CONST const /* CONSTANT value -- R/O */ +#define VOLATILE volatile /* VOLATILE must always read */ + +#else +#ifdef __HIGHC__ /* MetaWare High C */ +#define METAWARE 1 /* High C version 1.4 */ + +#define _PASCAL_CONV _CALLEE_POPS_STACK|_SAVE_REGS +#define _C_CONV _REVERSE_PARMS +#define FIXFUNC pragma Global_aliasing_convention("%C%r"); +#define VARFUNC pragma Global_aliasing_convention("_%a%r"); + /********************************/ +#define CDECL _cc (_C_CONV|_SAVE_REGS)/* MS C conventions */ +#define PASCAL _cc (_PASCAL_CONV) /* MS Pascal conventions */ +#define FAR _far /* FAR pointer or function */ +#define NEAR _near /* NEAR pointer or function */ +#define CONST const /* CONSTANT value -- R/O */ +#define VOLATILE volatile /* VOLATILE must always read */ + /********************************/ +pragma Calling_convention (_C_CONV,_DEFAULT); +VARFUNC /* set default to C */ + /********************************/ +pragma On (Optimize_for_space); /* space, not speed */ +pragma On (Quiet); /* don't be too verbose */ +pragma Off (Public_var_warnings); /* referenced before set */ +pragma Code ("_TEXT"); /* MSC compatible */ +pragma Static_segment ("_DATA"); /* MSC compatible */ +pragma Literals ("_DATA"); /* put constants into _DATA */ +pragma On (Char_default_unsigned); /* unsigned is safer */ +pragma Off (Push_regsize); /* push [mem] is safe */ + /********************************/ +#ifdef QUIET /********************************/ +pragma On (PCC_msgs); /* don't talk too much - */ +#endif /* UNIX PCC errors only... */ + /********************************/ +#ifdef REG /* if register defined already */ +#undef REG /* redefine register variables */ +#endif /* */ +#define REG /**/ /* make it ignore register vars */ +pragma Off (Use_reg_vars); /* allocate vars to SI, DI */ +pragma Off (Auto_reg_alloc); /* HC figures out SI,DI */ + /* */ +#ifndef NOPROTO /* */ +pragma Off (Prototype_override_warnings); +#define LINT_ARGS YES /* ANSI prototype checking */ +#endif /* */ + /********************************/ +#else /* all other compilers */ + /* (might not support ANSI) */ +#define CDECL /**/ /* C calling convention */ +#define PASCAL /**/ /* Pascal calling convention */ +#define FAR /**/ /* FAR pointer or function */ +#define NEAR /**/ /* NEAR pointer or function */ +#define CONST /**/ /* CONSTANT value */ +#define VOLATILE /**/ /* VOLATILE must always read */ + /********************************/ +#ifndef DRC /* If DRC not specified, */ +#define DRC /* assume it's it anyway */ +#endif /* */ + /********************************/ +#endif /* MetaWare C */ +#endif /* Borland TurboC */ +#endif /* MicroSoft C Version 5.00 */ +#endif /* MicroSoft C Version 4.00 */ +#endif /* Watcom C Version 7.00 */ + +#ifndef FIXFUNC +#define FIXFUNC /* Nothing */ +#define VARFUNC /* Nothing */ +#endif + +/****************************************************************************/ +/* Miscellaneous Definitions: */ +/****************************************************************************/ +#define FAILURE (-1) /* Function failure return val */ +#define SUCCESS (0) /* Function success return val */ +#define YES 1 /* "TRUE" */ +#define NO 0 /* "FALSE" */ +#define FOREVER for(;;) /* Infinite loop declaration */ +#undef NULL /* Remove previous definition */ +#define NULL 0 /* Null character value */ +#ifdef DRC /************************************/ +#define NULLPTR (BYTE *) 0 /* Null pointer value */ +#else /************************************/ +#define NULLPTR (VOID *) 0 /* Null pointer value */ +#endif /************************************/ +#define EOF (-1) /* EOF Value */ +#define TRUE (1) /* Function TRUE value */ +#define FALSE (0) /* Function FALSE value */ + +/****************************************************************************/ +/****************************************************************************/ diff --git a/COMMAND/PRINTF.C b/COMMAND/PRINTF.C new file mode 100644 index 0000000..27c98d1 --- /dev/null +++ b/COMMAND/PRINTF.C @@ -0,0 +1,560 @@ +/* +; File : $Workfile: PRINTF.C$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +*/ + +/* + * 26 Apr 88 Modify the Long conversion routine to display all 10 + * digits of a 32 bit integer when displayed in decimal + * 27 May 88 Added string undefs. + * 1? Jun 88 Support for CODE relative messages using the FARPTR routine. + * 05 Jun 89 Add EPRINTF routine to display messages on STDERR + * 30 Oct 89 dispense with digits & uc_digits in resident portion + * 8 Nov 89 Replaced ASCII calculation with to_dec(), etc. as used + * in APPALIB printf module. Much faster (eg dir /l 10% faster). + * 8 Jan 90 Added parameter order indexing option. + * 6-Mar-90 Watcom C v 7.0 + * 26-Mar-90 Make _printf CDECL again, otherwise arg processing screws up + * 23-May-90 increase printf buffers from 128 to 130 + * 02-Dec-90 Re-work, to flush buffer on \n to allow large input strings + * 28-May-91 local buffer is now on the stack instead of static. Reduces + * resident size by 128 bytes. + * 29-Jul-91 Buffer is now a far one, so output redirection to a file works + * on a NOVELL drive when we are in seg FFFF. + */ + +#include "defines.h" +#include + +#if defined(MWC) && defined(strlen) +#undef strcmp /* These are defined as macros in string.h */ +#undef strcpy /* which are expaneded in line under */ +#undef strlen /* Metaware C. These undefs avoid this. */ +#endif + +#include +#include "command.h" +#include "dosif.h" +#include "global.h" + +#define PRINTF -1 +#define EPRINTF -2 +#define SPRINTF -3 + +EXTERN VOID c_write (BYTE *, WORD); +EXTERN BYTE FAR * CDECL farptr (BYTE *); +EXTERN BOOLEAN isdigit (BYTE); +EXTERN BOOLEAN err_flag; + +/* forward references */ +MLOCAL UWORD CDECL _printf (BYTE *, UWORD *, UWORD); +MLOCAL VOID arg_ptrs (BYTE FAR *, UWORD *, UWORD **); +MLOCAL BYTE FAR * arg_siz (BYTE FAR *, UBYTE *); +MLOCAL BYTE FAR * arg_num (BYTE FAR *, UWORD *); +MLOCAL BYTE * to_hex (ULONG, BYTE *, BYTE); +MLOCAL BYTE * to_dec (ULONG, BYTE *); +MLOCAL BYTE * to_udec (ULONG, BYTE *); + +#define UPPER_CASE ('A'-10) +#define LOWER_CASE ('a'-10) + +#define MAX_ARG_NUM 10 /* max args with order indxs */ + +MLOCAL BYTE FAR *buff = NULLPTR; + +/*GLOBAL BYTE str[130];*/ +MLOCAL BYTE FAR *str; + +GLOBAL WORD CDECL printf(fmt,args) +BYTE *fmt; +UWORD args; +{ + UWORD totlen,len; + /*BYTE local_buff[130];*/ + UWORD bufsize; + + /*str = (BYTE FAR *) local_buff;*/ + str = gp_far_buff; + + buff = str; /* use local buffer for printing */ + totlen = _printf (fmt,&args,PRINTF); /* build up output string */ + len=(UWORD) buff - (UWORD) str; + if(len) /* if anything in the buffer */ + far_write(err_flag ? STDERR:STDOUT, str, len); + /* then flush it */ + + return totlen+len; /* Return the String Length */ + +} + +GLOBAL WORD CDECL eprintf(fmt,args) +BYTE *fmt; +UWORD args; +{ + UWORD totlen, len; + BYTE local_buff[130]; + + str = (BYTE FAR *) local_buff; + + buff = str; /* use local buffer for printing */ + err_flag = TRUE; + totlen = _printf (fmt,&args,EPRINTF); /* build up output string */ + len = buff-str; + if(len) { /* if anything in the buffer */ + far_write(STDERR,str,len); + } + err_flag = FALSE; + + return totlen+len; /* Return the String Length */ + +} + +GLOBAL WORD CDECL fprintf(handle, fmt, args) +UWORD handle; +BYTE *fmt; +UWORD args; +{ + UWORD totlen,len; + UWORD bufsize; + + str = gp_far_buff; + + buff = str; /* use local buffer for printing */ + totlen =_printf (fmt,&args,handle); /* build up output string */ + len = (UWORD) buff - (UWORD) str; + if(len) /* if anything in the buffer */ + far_write(handle, str, len); /* then flush it */ + + return totlen+len; /* Return the String Length */ + +} + +GLOBAL WORD CDECL sprintf(strg, fmt, args) +BYTE *strg; +BYTE *fmt; +UWORD args; +{ + buff = (BYTE FAR *) strg; /* Point buffer at String */ + return _printf (fmt,&args,SPRINTF); /* Generate the String */ +} + +MLOCAL UWORD CDECL _printf(fmt_near, args, type) +BYTE *fmt_near; +UWORD *args; +UWORD type; +{ + BYTE FAR *fmt; + WORD rjust; /* if string/number is right justified */ + WORD maxwidth, width; + BOOLEAN long_arg; /* true if next argument is long */ + ULONG value; + UWORD uvalue; + WORD i, k; + BYTE FAR *cp; + BYTE c, filler; + BYTE s[40], *sp; + LONG *lp; + UWORD *arg_list[MAX_ARG_NUM]; + UWORD arg_idx; + UWORD totlen=0; + + fmt = farptr(fmt_near); /* get full address of format string */ + arg_ptrs(fmt, args, arg_list); /* init table of argument addresses */ + + while ((c = *fmt++) != 0) /* scan format string */ + { + if (c == '%') { /* formatting code found */ + s[14] = 0; + rjust = YES; + filler = ' '; + maxwidth = 0x7fff; + + fmt = arg_num(fmt, &arg_idx); /* get argument index */ + if (arg_idx < MAX_ARG_NUM) { /* valid index? */ + fmt++; /* yes - skip '%' */ + args = arg_list[arg_idx]; /* lookup address of arg */ + } + + if ((c = *fmt) == '-') { /* string is left justified */ + rjust = NO; /* ... not right justified */ + c = *fmt++; /* get the next character */ + } + + if (c == '0') /* if leading zeroes desired */ + filler = '0'; /* use '0' instead of ' ' */ + + if (*fmt == '*') { /* if formatting width is parameter */ + /* then get it from parameters */ + width = (WORD)*args++; + fmt++; /* skip the asterisk */ + c = *fmt++; /* get next character */ + } + else /* get full width */ + for (width = 0; (c = *fmt++) >= '0' && c <= '9'; ) + width = width*10 + c - '0'; + + if (c == '.') { /* if decimal places specified */ + if (*fmt == '*') { /* if width is a parameter */ + maxwidth = (WORD)*args++; + fmt++; /* skip the asterisk */ + c = *fmt++; /* get next character */ + } + else /* get decimal places */ + for (maxwidth = 0; (c = *fmt++) >= '0' && c <= '9' ;) + maxwidth = maxwidth*10 + c - '0'; + } + + /* "%ld", "%lu", "lx" specified */ + long_arg = (c == 'l'); /* is the argument supplied long? */ + if (long_arg) /* if long argument */ + c = *fmt++; /* then skip the 'l' character */ + + switch (c) { + case 'd': /* signed argument */ + if (!long_arg) + value = (WORD) *args++; + else { + lp = (LONG *) args; + value = *lp++; + args = (UWORD *) lp; + } + break; + + case 'u': /* unsigned argument */ + case 'x': + case 'X': + if (!long_arg) + value = (UWORD) *args++; + else { + lp = (LONG *) args; + value = (ULONG) *lp++; + args = (UWORD *) lp; + } + break; + + default: /* "%s", "%c" */ + uvalue = (UWORD) *args++; /* get string address of char */ + } + + + switch (c) { /* now convert to ASCII */ + case 'd': /* signed decimal */ + sp = to_dec(value, s+14); + break; + + case 'u': /* unsigned decimal */ + sp = to_udec(value, s+14); + break; + + case 'x': /* unsigned hexadecimal, lower case */ + sp = to_hex(value, s+14, LOWER_CASE); + break; + + case 'X': /* unsigned hexadecimal, upper case */ + sp = to_hex(value, s+14, UPPER_CASE); + break; + + case 's': /* string -- could be far */ + cp = farptr((BYTE *)uvalue); + for (i=0; cp[i] != '\0'; i++) + ; + goto havelen; + + case 'c': + c = uvalue; + /* drop into "default:" */ + default: /* normal characters */ + sp = s+13; + *sp = c; + break; + } + + i = (s+14) - sp; /* work out length of string */ + cp = (BYTE FAR *) sp; /* convert to FAR pointer */ + +havelen: + if (i > maxwidth) + i = maxwidth; + + if (rjust) { + while (width-- > i) + *buff++ = filler; + } + + for (k = 0; *cp && k < maxwidth; ++k) { + if (*cp == '\n') + *buff++ = '\r'; + *buff++ = *cp++; + } + + if (!rjust) { /* if right justified */ + while (width-- > i) + *buff++ = ' '; + } + } + else if (c == '\n') { /* expand newline to CR,LF then flush the buffer */ + *buff++ = '\r'; + *buff++ = '\n'; + if (type!=SPRINTF) { + /* Flush the buffer */ + *buff = '\0'; /* terminate the string */ + switch (type) { + case PRINTF: + far_write(err_flag ? STDERR:STDOUT,str, + (UWORD) buff - (UWORD) str); + break; + case EPRINTF: + far_write(STDERR, str, buff-str); + break; + default: + far_write(type, str, buff-str); + break; + } /*ENDSWITCH*/ + totlen+=buff-str; + buff=str; + } + } + else + *buff++ = c; + } + *buff = '\0'; /* terminate the string */ + return totlen+=buff-str; +} + + + +/* Initialise the table of pointers to all arguments (ptr_list). + The ptr_list table will not be filled in unless the format + string (fmt) contains parameter order indexes. */ + +MLOCAL VOID arg_ptrs(fmt, args, ptr_list) +REG BYTE FAR *fmt; /* ASCIIZ format string */ +UWORD *args; /* pointer to first argument */ +UWORD *ptr_list[]; /* list of pointers to all arguments */ +{ +UWORD arg_cnt; /* running count of parameters found */ +UWORD num; +UBYTE size_list[MAX_ARG_NUM]; /* number bytes in each argument */ +UWORD i; + + + /* Read through format string to determine the size of each argument. */ + for (arg_cnt = 0; ; ) + { + while (*fmt && *fmt != '%') /* find the next parameter */ + fmt++; + + if (!*fmt) /* patameter found? */ + break; /* no - exit loop */ + fmt++; /* skip '%' */ + + if (*fmt == '%') /* "%%" escape for percent? */ + { + fmt++; /* yes - skip second '%' */ + continue; /* and look for next parameter */ + } + + fmt = arg_num(fmt, &num); /* get this argument's index */ + if (num >= MAX_ARG_NUM) /* arg index present and valid? */ + break; /* no - go no further */ + + /* record this argument's size */ + fmt = arg_siz(fmt, &size_list[num]); + arg_cnt++; /* one more argument found */ + } + + + /* Loop once for each argument found in format string, filling in + the offset for that argument in the size_list table. */ + for (i = 0; i < arg_cnt; i++) + { + ptr_list[i] = args; /* record the address of arg */ + args += (UWORD)(size_list[i]); /* update ptr by size of arg */ + } +} + + + +/* Determine the size in bytes (siz) of the argument that corresponds to the + given format string (fmt). Return a pointer to the character following + the last in the format string. For example... + + fmt siz + %d 2 + %ld 4 + %*d 4 +*/ + +MLOCAL BYTE FAR * arg_siz(fmt, siz) +REG BYTE FAR *fmt; /* printf argument format string */ +UBYTE *siz; /* returned argument size, in bytes */ +{ + + *siz = 0; /* argument size not yet known */ + + if (*fmt != '%') + return fmt; /* format string must begin with '%' */ + fmt++; /* skip '%' */ + + if (*fmt == '#') /* ignore various formatting ctrls */ + fmt++; + if (*fmt == '-') + fmt++; + if (*fmt == '0') + fmt++; + + if (*fmt == '*') + { /* width argument also on stack */ + *siz += sizeof(WORD); /* width argument is a WORD */ + fmt++; + } + else /* ignore any static width control */ + while (*fmt >= '0' && *fmt <= '9') + fmt++; + + if (*fmt == '.') + { + fmt++; + if (*fmt == '*') + { /* 2nd width argument on stack */ + *siz += sizeof(WORD); + fmt++; + } + else /* ignore any static width control */ + while (*fmt >= '0' && *fmt <= '9') + fmt++; + } + + if (*fmt == 'l') + { + *siz += sizeof(LONG); + fmt++; + } + else + *siz += sizeof(WORD); /* assume sizeof(WORD)==sizeof(BYTE *) */ + + return ++fmt; /* skip final char: 'd', 's', etc. */ +} + + + +/* Determine the index number (num) of the argument given by the format + string (fmt). If the format string does not have a valid index number + num is set to MAX_ARG_NUM. Return a pointer to the character following + the last in the index number. For example... + + fmt num returned pointer to... + 3%4d 3 '%' + 4d MAX_ARG_NUM '4' + % MAX_ARG_NUM '%' +*/ + +MLOCAL BYTE FAR * arg_num(fmt, num) +BYTE FAR *fmt; +UWORD *num; +{ +REG BYTE FAR *cp; +REG UWORD n; + + + *num = MAX_ARG_NUM; /* argument index not yet known */ + + cp = fmt; + if (!isdigit(*cp)) /* at least one digit expected */ + return fmt; + /* extract index number */ + for (n = 0; *cp >= '0' && *cp <= '9'; cp++) + n = n * 10 + *cp - '0'; + + if (*cp != '%') + return fmt; /* number must be terminated by '%' */ + + *num = n; /* record the index number */ + return cp; /* return pointer to last '%' */ +} + + + +MLOCAL BYTE * to_hex(n, s, hex_base) +ULONG n; +BYTE *s; +BYTE hex_base; /* 'a'-10 for lowercase, 'A'-10 uppercase */ +{ +REG UBYTE i; + + do + { + i = (UBYTE)n & 0x0F; + *--s = (i > 9) ? (hex_base + i) : ('0' + i); + n >>= 4; + } + while (n != 0); + + return s; +} + + + +MLOCAL BYTE * to_dec(n, s) +ULONG n; +BYTE *s; +{ + if ((LONG)n < 0) + { + s = to_udec(0 - (LONG)n, s); + *--s = '-'; /* preceed number with sign */ + return s; + } + else + return to_udec(n, s); +} + + + +MLOCAL BYTE * to_udec(n, s) +ULONG n; +BYTE *s; +{ + do + { + *--s = '0' + (n % 10); + n /= 10; + } + while (n != 0); + + return s; +} + + + diff --git a/COMMAND/RESIDENT.ASM b/COMMAND/RESIDENT.ASM new file mode 100644 index 0000000..ec53283 --- /dev/null +++ b/COMMAND/RESIDENT.ASM @@ -0,0 +1,126 @@ +NUL equ 0 +BS equ 8 +TAB equ 9 +LF equ 10 +CR equ 13 + +DGROUP group _DATA + +_DATA segment word public 'DATA' + assume ds:DGROUP + +; Source .TFT file: 'TMP1.$$$' + public _msg0 + public msg0 +msg0 label byte +_msg0 db "Write protect error$" + public _msg3 + public msg3 +msg3 label byte +_msg3 db "I/O error$" + public _msg2 + public msg2 +msg2 label byte +_msg2 db "Not ready error$" + public _msg4 + public msg4 +msg4 label byte +_msg4 db "Data error$" + public _msg6 + public msg6 +msg6 label byte +_msg6 db "Seek error$" + public _msg7 + public msg7 +msg7 label byte +_msg7 db "Bad media type$" + public _msg8 + public msg8 +msg8 label byte +_msg8 db "Sector not found$" + public _msg21 + public msg21 +msg21 label byte +_msg21 db "Printer out of paper$" + public _msg20 + public msg20 +msg20 label byte +_msg20 db "File Sharing Conflict$" + public _msg22 + public msg22 +msg22 label byte +_msg22 db "FCB table exhausted$" + public _msg_crlf + public msg_crlf +msg_crlf label byte +_msg_crlf db CR, LF, "$" + public _readmsg + public readmsg +readmsg label byte +_readmsg db " reading$" + public _writemsg + public writemsg +writemsg label byte +_writemsg db " writing$" + public _drivemsg + public drivemsg +drivemsg label byte +_drivemsg db " drive $" + public _charmsg + public charmsg +charmsg label byte +_charmsg db " device $" + public _abort_char + public abort_char +abort_char label byte +_abort_char db "A$" + public _abort_msg + public abort_msg +abort_msg label byte +_abort_msg db "Abort$" + public _retry_char + public retry_char +retry_char label byte +_retry_char db "R$" + public _retry_msg + public retry_msg +retry_msg label byte +_retry_msg db ", Retry$" + public _ignore_char + public ignore_char +ignore_char label byte +_ignore_char db "I$" + public _ignore_msg + public ignore_msg +ignore_msg label byte +_ignore_msg db ", Ignore$" + public _fail_char + public fail_char +fail_char label byte +_fail_char db "F$" + public _fail_msg + public fail_msg +fail_msg label byte +_fail_msg db ", Fail$" + public _prompt_msg + public prompt_msg +prompt_msg label byte +_prompt_msg db " ? $" + public _reload_msgs + public reload_msgs +reload_msgs label byte +_reload_msgs db CR, LF, "Cannot load the file ", 0 + public _reload_msgf + public reload_msgf +reload_msgf label byte +_reload_msgf db CR, LF, "Insert correct disk and Strike any key", 0 + public _reload_msgm + public reload_msgm +reload_msgm label byte +_reload_msgm db " No Memory", 0 + +_DATA ends + + + end + \ No newline at end of file diff --git a/COMMAND/RESIDENT.DEF b/COMMAND/RESIDENT.DEF new file mode 100644 index 0000000..ff0a02d --- /dev/null +++ b/COMMAND/RESIDENT.DEF @@ -0,0 +1,54 @@ + extrn _abort_char : byte + extrn abort_char : byte + extrn _abort_msg : byte + extrn abort_msg : byte + extrn _charmsg : byte + extrn charmsg : byte + extrn _drivemsg : byte + extrn drivemsg : byte + extrn _fail_char : byte + extrn fail_char : byte + extrn _fail_msg : byte + extrn fail_msg : byte + extrn _ignore_char : byte + extrn ignore_char : byte + extrn _ignore_msg : byte + extrn ignore_msg : byte + extrn _msg0 : byte + extrn msg0 : byte + extrn _msg2 : byte + extrn msg2 : byte + extrn _msg20 : byte + extrn msg20 : byte + extrn _msg21 : byte + extrn msg21 : byte + extrn _msg22 : byte + extrn msg22 : byte + extrn _msg3 : byte + extrn msg3 : byte + extrn _msg4 : byte + extrn msg4 : byte + extrn _msg6 : byte + extrn msg6 : byte + extrn _msg7 : byte + extrn msg7 : byte + extrn _msg8 : byte + extrn msg8 : byte + extrn _msg_crlf : byte + extrn msg_crlf : byte + extrn _prompt_msg : byte + extrn prompt_msg : byte + extrn _readmsg : byte + extrn readmsg : byte + extrn _reload_msgf : byte + extrn reload_msgf : byte + extrn _reload_msgm : byte + extrn reload_msgm : byte + extrn _reload_msgs : byte + extrn reload_msgs : byte + extrn _retry_char : byte + extrn retry_char : byte + extrn _retry_msg : byte + extrn retry_msg : byte + extrn _writemsg : byte + extrn writemsg : byte diff --git a/COMMAND/RESIDENT.H b/COMMAND/RESIDENT.H new file mode 100644 index 0000000..195e7c6 --- /dev/null +++ b/COMMAND/RESIDENT.H @@ -0,0 +1,27 @@ +extern char near abort_char[]; +extern char near abort_msg[]; +extern char near charmsg[]; +extern char near drivemsg[]; +extern char near fail_char[]; +extern char near fail_msg[]; +extern char near ignore_char[]; +extern char near ignore_msg[]; +extern char near msg0[]; +extern char near msg2[]; +extern char near msg20[]; +extern char near msg21[]; +extern char near msg22[]; +extern char near msg3[]; +extern char near msg4[]; +extern char near msg6[]; +extern char near msg7[]; +extern char near msg8[]; +extern char near msg_crlf[]; +extern char near prompt_msg[]; +extern char near readmsg[]; +extern char near reload_msgf[]; +extern char near reload_msgm[]; +extern char near reload_msgs[]; +extern char near retry_char[]; +extern char near retry_msg[]; +extern char near writemsg[]; diff --git a/COMMAND/RESP1 b/COMMAND/RESP1 new file mode 100644 index 0000000..8b4f011 --- /dev/null +++ b/COMMAND/RESP1 @@ -0,0 +1,3 @@ +-w -d -f- -K -O -X -Z -c -ms -IC:\TOOLS\BCC20\H -DMESSAGE -DDOSPLUS -zSCGROUP -zTCODE -zR_MSG +-I.\ +-o.\bin\cmdlist.obj .\cmdlist.c diff --git a/COMMAND/RESP2 b/COMMAND/RESP2 new file mode 100644 index 0000000..bab45b9 --- /dev/null +++ b/COMMAND/RESP2 @@ -0,0 +1,11 @@ +.\bin\cstart.obj .\bin\com.obj .\bin\csup.obj + +.\bin\dosif.obj .\bin\comint.obj .\bin\support.obj+ +.\bin\cmdlist.obj .\bin\printf.obj+ +.\bin\message.obj + +.\bin\batch.obj .\bin\global.obj .\bin\config.obj+ +.\bin\comcpy.obj .\bin\crit.obj + ++ +.\bin\resident.obj +.\bin\command.exe +.\command.map +C:\TOOLS\WATCOMC\LIB\CLIBs diff --git a/COMMAND/RESP3 b/COMMAND/RESP3 new file mode 100644 index 0000000..5b5df0c --- /dev/null +++ b/COMMAND/RESP3 @@ -0,0 +1,3 @@ +.\bin\helpstub.obj+ +.\bin\txhelp.obj +.\bin\txhelp.exe diff --git a/COMMAND/SECURITY.H b/COMMAND/SECURITY.H new file mode 100644 index 0000000..ab001ce --- /dev/null +++ b/COMMAND/SECURITY.H @@ -0,0 +1,240 @@ +/* +; File : $Workfile$ +; +; Description : Definitions of common security related structures. +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +*/ + + +/* All security information files have the following header before any + data entries. */ + +typedef struct +{ + UWORD signature; /* file identifier, see SIG_ */ + BYTE version; /* version No., see SECURE_VERSION */ + BYTE crlf[2]; +} INF_HEADER_ENTRY; + + +/* All security info files must be at the following version level + to be compatible with the definitions in this file. */ +#define SECURE_VERSION '0' + + +#define FNAME_LOGIN_TXT "LOGIN.TXT" +#define FNAME_LOCK_TXT "LOCK.TXT" + +#define FNAME_LOGIN_ERR "LOGIN.ERR" +#define FNAME_LOCK_ERR "LOCK.ERR" + + + +/****************************************************************************** + + User information file. + +******************************************************************************/ + + +/* The following structure defines the contents of a single entry in the + user information file. This file associates user id numbers, user names, + group names, etc for all users on a secure Concurrent DOS system. + + The file is in ASCII with one entry per line. Each variable is separated + by one space character and variables are all left justified space padded. + The lines are a fixed length, equal to sizeof(USER_INF_ENTRY). + Entries in the file are sorted on the userid field. + + An example file (where ... indicates absent space padding) - + +UI0 +0100 RogerGross Stellar rwdr----- C \roger ... 08-23-1990 10:30:52 ... +0101 Ant Stellar rwdr----- C \ant ... 08-22-1990 16:10:08 ... +0200 Stan Accounts rwd------ C \stan ... 08-10-1990 09:27:00 ... +0900 Julie Doc rwdrwdr-- C \julie ... 08-22-1990 08:09:11 ... + +*/ + + +#define FNAME_USER_INF "USER.INF" /* user information file name */ +#define SIG_USER_INF 0x4955 /* file signature "UI" in word order */ + +#define USERID_LGTH 4 +#define SYS_NAME_LGTH 12 +#define DEFACCESS_LGTH 9 +#define DATE_LGTH 10 +#define TIME_LGTH 8 +#define CMNT_LGTH 32 + + +typedef struct +{ + BYTE userid [USERID_LGTH+1]; + BYTE loginname [SYS_NAME_LGTH+1]; + BYTE groupname [SYS_NAME_LGTH+1]; + BYTE defaccess [DEFACCESS_LGTH+1]; + BYTE homedrv [2]; + BYTE homedir [PATH_LEN]; + BYTE date [DATE_LGTH+1]; /* mm-dd-yyyy */ + BYTE time [TIME_LGTH+1]; /* hh:mm:ss */ + BYTE comment [CMNT_LGTH+1]; + BYTE crlf [2]; +} USER_INF_ENTRY; + + +#define DEFLT_SU_NAME "Superuser" +#define DEFLT_SU_GROUP "Supergroup" + + + +/****************************************************************************** + + User password file. + +******************************************************************************/ + + + +/* The following structure defines the contents of a single entry in the + user password file. This file associates user id numbers with passwords + for all users on a secure Concurrent DOS system. + + The file is in a binary format. + Entries in the file are sorted on the userid field. +*/ + + +#define FNAME_USER_SYS "USER.SYS" /* user password file name */ +#define SIG_USER_SYS 0x5355 /* file signature "US" in word order */ + +typedef struct +{ + UWORD userid; + ULONG pword; +} USER_SYS_ENTRY; + + + +/****************************************************************************** + + Login history file. + +******************************************************************************/ + + + +/* The following structure defines the contents of a single entry in the + login.log history file. This file is a history of events on the system + such as login/out lock and errors. + + The file is in a binary format. + New Entries are appended to the file. +*/ + + +#define FNAME_LOGIN_LOG "LOGIN.LOG" +#define SIG_LOGIN_LOG 0x4C4C /* file signature "LL" in word order */ + +typedef struct +{ + UWORD year; /* 1980 - 2099 */ + UBYTE month; + UBYTE day; + UBYTE day_of_week; /* Ignored by ms_setdate */ +} SYSDAT; + +typedef struct +{ + UBYTE hour; /* (0 - 23) */ + UBYTE minute; /* (0 - 59) */ + UBYTE second; /* (0 - 59) */ + UBYTE hundredth; /* (0 - 99) */ +} SYSTIM; + +typedef struct +{ + UWORD userid; + UWORD station; + WORD event; + SYSTIM time; + SYSDAT date; +} LOGIN_LOG_ENTRY; + +#define LOG_LOGIN 0 +#define LOG_LOGOUT 1 +#define LOG_LOCK 2 +#define LOG_UNLOCK 3 +#define LOG_REBOOT 4 +#define LOG_POWERON 5 + +#define ERR_BASE 0 +#define ERR_USERPWORD ERR_BASE-1 +#define ERR_NOFILE ERR_BASE-2 +#define ERR_OPENFILE ERR_BASE-3 +#define ERR_BADFILE ERR_BASE-4 +#define ERR_READFILE ERR_BASE-5 +#define ERR_WRITEFILE ERR_BASE-6 +#define ERR_BADID ERR_BASE-7 +#define ERR_FATALSYSTEM ERR_BASE-8 +#define ERR_LOGIN ERR_BASE-9 +#define ERR_LOGOUT ERR_BASE-10 +#define ERR_LOCK ERR_BASE-11 +#define ERR_UNLOCK ERR_BASE-12 + + +/****************************************************************************** + + Miscellaneous definitions. + +******************************************************************************/ + + +#define SYS_PWORD_MINLEN 3 /* minimum password length */ +#define SYS_PWORD_MIN 6 /* minimum pw len (INSTALL only) */ +#define SYS_PWORD_MAX SYS_NAME_LGTH + +#define ID_NUM(n) ((n)&0x00FF) /* extract user No. from 16 bit id */ +#define ID_GROUP(n) ((n)>>8) /* extract group No. from 16 bit id */ +#define ID_GRP_USR(g,u) (((g)<<8)+(u)) /* convert group/user to 16 bit id */ + + +/* The following definition is used when accessing USER.SYS, USER.INF, etc. + Because these files may be open by other processes in a mode which denies + access to any other several attempts must be made to open them before + giving up. This definition governs the number of attempts to be made. + Note that a utility should perform a P_DISPATCH after each unsuccessful + attempt. */ +#define ACCESS_ATTEMPTS 1000 + + +/******************* E N D O F S E C U R I T Y . H *******************/ diff --git a/COMMAND/STRUCT.H b/COMMAND/STRUCT.H new file mode 100644 index 0000000..90a4953 --- /dev/null +++ b/COMMAND/STRUCT.H @@ -0,0 +1,89 @@ +/* +; File : $Workfile$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +*/ + +/* FCB defines */ + +#define FCB_NAME 1 +#define FCB_SIZE 32 +#define FCB_NAME_SIZE 11 +#define FCB_EXTENT 12 +#define FCB_CS 13 +#define FCB_RC 15 +#define FCB_ALUS 16 + + +struct xios_iopb { + UBYTE drv; + UBYTE mcnt; + UWORD track; + UWORD sector; + UBYTE FAR *dma_buffer; + }; + +struct xios_dpb { + UWORD spt; /* defined as per system guide */ + UBYTE bsh; /* This Structure forces the use of */ + UBYTE blm; /* the '/Zp' option on the compiler */ + UBYTE exm; /* for Packed structures. */ + UWORD dsm; + UWORD drm; + UBYTE al0; + UBYTE al1; + UWORD cks; + UWORD off; + UBYTE psh; + UBYTE prm; + }; + +struct segoff { + UWORD off; + UWORD seg; + }; + +struct f_data { + UBYTE srch_attrib; /* size 1 */ + UBYTE cur_drive; /* size 1 */ + UBYTE media; /* size 1 */ + UBYTE pattern[FCB_NAME_SIZE]; /* size 11 */ + UWORD cur_alu; /* size 2 */ + UWORD cur_index; /* size 2 */ + UBYTE filler[3]; /* size 3 */ + UBYTE fnd_attrib; /* size 1 */ + UWORD time; /* size 2 */ + UWORD date; /* size 2 */ + LONG file_size; /* size 4 */ + UBYTE file_name[63]; /* size ? */ + }; diff --git a/COMMAND/SUPPORT.C b/COMMAND/SUPPORT.C new file mode 100644 index 0000000..13cafa9 --- /dev/null +++ b/COMMAND/SUPPORT.C @@ -0,0 +1,1302 @@ +/* +; File : $Workfile: SUPPORT.C$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +*/ + +/* + File SUPPORT.C + Title SUPPORT routines for command.com + +Revision History:- +================== + +Date Description +----------------------------------------------------------------------------- +10 Apr 86 EQU function now makes a case independant match. +29 Apr 86 Single $ preceeds the screen control variables + Fix bug where if the last character of a screen control + variable was an octal character it was not printed + 6 May 86 yes() now requires a default to be specified previously + it assumed the default was NO. +21 May 86 Fixed bug with yes() function when default is NO. +22 May 86 Allow the screen control codes to be patched to longer strings + Upd`te ZAP_SPACES to delete all white space +Version 1.2 +=========== +31 Jul 86 Conditionally remove functions that cannot be fully supported + in a CDOS version of COMMAND.COM + 4 Aug 86 ANSI C compatibility MSC /W1 +30 Oct 86 FREE_DRIVE now forces the drive to point to the root + directory of the current drive. +17 Feb 87 Rewrote repwild() function to fix minor problems + Aug 87 Make all routines PASCAL calling convention (for Concurrent 6) +26 Oct 87 Update the F_CHECK routine to support multiple switches ie + "/wc" as well as "/w /c". +27 Oct 87 Stop F_CHECK from forcing the input line to lower case. +10 Nov 87 Modify F_CHECK flag zapping +18 Nov 87 Prevent GET_FILENAME copying a filename > than MAX_PATHLEN +16 Dec 87 Update D_CHECK to make fewer system calls. +29 Feb 88 Tidy the REPWILD routine - No Functional Change +15 Mar 88 Use ANSI Escape sequences for DOS Plus +27 Apr 88 Restore Range check to D_CHECK routine +25 May 88 Print a CR after a CLS to reset the current column count. +26 May 88 Change the Default HighLight and LowLight strings to NULL + for DOSPLUS. +27 May 88 Added string undefs. +23 Jun 88 Add new ONOFF function for XXX [=] ON|OFF parsing +28 Jun 88 Correct bug in YES routine for FAR messages + 1 Jul 88 Support Control-C from YES for TMP. + 6 Jul 88 Support the CON:filename syntax for COPY. +19 Sep 88 Enhance error checking on the F_CHECK routine. Now traps the + condition when switchar is at the end of the line. + 1 Dec 88 Convert all path parsing routines to be KANJI friendly. +21 Dec 88 Add generic ISDEV routine to SUPPORT.C +21 Dec 88 "*" to "*.*" conversion moved to CMD_DIR. +18 Apr 89 c_write: write to STDERR if err_flag set +6 Jun 89 Correct GET_FILENAME to parse path passwords. +6 Jun 89 echo: check for endline after on/off. +10 Aug 89 get rid of sysdate_fmt (year does not need to be %04d, which + upsets Japanese day) +10 Aug 89 day_name_len for day_names array elements +22 Aug 89 Japanese dayname comes after date + Remove day_name_len & work out length from array. +11 Sep 89 strupr(), strlwr() and stricmp() are now Kanji aware. + toupper() is now in DOSIF.ASM and uses international routine. +16 Oct 89 Kanji specific routines replaced with DBCS routines. +30 Oct 89 "Internal Error" moved to message.c (and no longer resident) +15 Dec 89 errors 50-72 give "Network error" rather than "Internal error" +6-Mar-90 Watcom C v 7.0 +13-Mar-90 Output CR/LF after errors +4-May-90 append_slash added +4-May-90 get_filename stops at ';' unless followed by pathchar(s) + ("append;" bug) +20-Sep-90 Created skip_char() and copy_char(). + Created is_blank() and amended deblank(), zap_spaces(), + is_filechar() and is_pathchar() to use it. +13-Mar-91 changed nofiles() function to cope with DIR.. on NOVELL drives. +18-Mar-91 tolower() ( and therefore strlwr() ) is now aware of TURKISH + capital I's with dots. +6-Aug-91 prompt_exec() function no longer uses the heap. This screwed us + up if the file to be execed was a batch file. +09-Jun-92 is_pathchar and d_check now cope with drive '[', etc, as used + by some novell applications. See also INVALID_DRV in command.h. +18-Jun-92 Added optional_line() function for '?' support in batch files. +----------------------------------------------------------------------------- +*/ + +#include "defines.h" +#include +/*#include */ + +#if defined(MWC) && defined(strlen) +#undef strcmp /* These are defined as macros in string.h */ +#undef strcpy /* which are expaneded in line under */ +#undef strlen /* Metaware C. These undefs avoid this. */ +#endif + +#include +#include +#if defined(CDOSTMP) +#include +#include +#endif + +#include "command.h" +#include "toupper.h" +#include "dosif.h" +#include "global.h" +#include "dos.h" + +EXTERN jmp_buf break_env; + +EXTERN VOID CDECL printf(BYTE *, ...); +EXTERN VOID CDECL eprintf(BYTE *, ...); +EXTERN VOID CDECL sprintf(BYTE *, BYTE *, ...); +#if defined(CDOSTMP) +EXTERN VOID CDECL int_break(VOID); /* COM.C Internal Break */ +#endif + +MLOCAL VOID screen(BYTE *, BYTE *); +MLOCAL VOID outs(BYTE *); +GLOBAL VOID crlf(VOID); +GLOBAL VOID putc(BYTE); +GLOBAL VOID c_write(BYTE *, UWORD); +GLOBAL BYTE * fptr(BYTE *); +GLOBAL BYTE * day_names(UWORD); + +/*.pa*/ +/* + * The following screen control sequences can be redefined or removed + * by entries in the environment or the OEM can patch these areas in the + * COMMAND.COM object and change the default values. + * + */ +#define CLS_KEY "$CLS=" /* CLS entry in environment */ +#define REVON_KEY "$ON=" /* REVON entry in environment */ +#define REVOFF_KEY "$OFF=" /* REVOFF entry in environment */ + +#ifdef DOSPLUS +/* + * For DOSPLUS the default screen control sequences are for an + * ANSI Terminal (IBM Sub-Set). + */ +#define CLS_DEF "\033[2J\0***" /* Default CLS string "ESC [2J"*/ +#define REVON_DEF "\0********" /* Default REVON string NULL */ +#define REVOFF_DEF "\0********" /* Default REVOFF string NULL */ + +EXTERN BOOLEAN CDECL int10_cls(VOID); /* Dirty Clear Screen Subroutine */ +#else +/* + * For Concurrent DOS the default screen control sequences are for a + * standard VT52 Terminal. + */ +#define CLS_DEF "\033E\0*****" /* Default CLS string "ESC E" */ +#define REVON_DEF "\033p\0*****" /* Default REVON string "ESC p" */ +#define REVOFF_DEF "\033q\0*****" /* Default REVOFF string "ESC q" */ +#endif + /* Invalid FileName Characters as */ + /* specified by the IBM DOS Tech */ + /* Reference Page 6-96 "func 29" */ +MLOCAL BYTE invalid_filechar[] = "*?\\.:;,=+<>|/\"[]"; + +/*.pa*/ +/* + * TIME AND DATE SUPPORT ROUTINES + * ============================== + * + * The following routines print the TIME and DATE using the international + * data. Two sets of routines are provided to display the SYSTEM Time and + * Date the second routine displays FILE based time and date. + */ +MLOCAL BYTE date_fmt [] = "%2d%c%02d%c%02d"; + +GLOBAL VOID disp_filetime(time) +unsigned time; +{ + WORD h, m; + BYTE ap; + + ap = ' '; /* assume no AM/PM used */ + h = (time >> 11); + m = (time >> 5) & 0x3f; + if (country.ampm == 0) /* if anglo saxon fashion */ + { /* need to convert things */ + ap = 'a'; /* assume morning */ + if (h == 0) /* 00:00 through 00:59 */ + h = 12; /* is special... */ + else if (h >= 12) /* test if afternoon */ + { + ap = 'p'; /* mark as afternoon */ + if (h > 12) /* if 13:00 through 23:59 */ + h -= 12; /* need to make " 1:00p" */ + } + } + + printf ("%2d%c%02d%c", + h, country.dtime[0], /* print hour, delimiter */ + m, ap); /* print minute, am/pm (if enabled) */ +} + +GLOBAL VOID disp_filedate(date) +unsigned date; +{ + WORD y, m, d; + WORD b; + + y = ((date >> 9) + 80)%100; + m = (date >> 5) & 0x0f; + d = date & 0x1f; + b = country.ddate[0]; + + switch (country.dt_fmt) + { + case 1: /* European format dd/mm/yy */ + printf (date_fmt, d,b,m,b,y); + break; + + case 2: /* Japanese format yy/mm/dd */ + printf (date_fmt, y,b,m,b,d); + break; + + default: /* US format mm/dd/yy for the rest*/ + printf (date_fmt, m,b,d,b,y); + break; + + }; +} + +GLOBAL VOID disp_systime() +{ + SYSTIME time; + WORD b = country.dtime[0]; + + ms_gettime(&time); + printf ("%2d%c%02d%c%02d.%02d", + time.hour, b, /* print hour, delimiter */ + time.min, b, /* print minute, delimiter */ + time.sec, time.hsec); /* Print the second and Hundredths */ +} + + +/* Return address of null terminated day name, given index (day). */ + +GLOBAL BYTE * day_names(day) +UWORD day; /* day of week: 0=sunday, 1=monday, .. */ +{ + switch (day) + { + case 0: return SUN_D; + case 1: return MON_D; + case 2: return TUE_D; + case 3: return WED_D; + case 4: return THU_D; + case 5: return FRI_D; + default: break; + } + + return SAT_D; +} + + +GLOBAL VOID disp_sysdate() +{ + SYSDATE date; + WORD y, m, d; + WORD b; + + ms_getdate(&date); /* Get the current date */ + y = date.year; + m = date.month; + d = date.day; + b = country.ddate[0]; + + if (country.dt_fmt != 2) /* Japanese day comes after date */ + printf("%s ", day_names(date.dow)); + + switch (country.dt_fmt) + { + case 1: /* European format dd/mm/yy */ + printf (date_fmt, d,b,m,b,y); + break; + + case 2: /* Japanese format yy/mm/dd */ + printf (date_fmt, y,b,m,b,d); + printf(" %s", day_names(date.dow)); + break; + + default: /* US format mm/dd/yy for the rest*/ + printf (date_fmt, m,b,d,b,y); + break; + }; +} + +/*.pa*/ +/* + * Screen handling routines to CLEAR the screen and emphasise text +*/ + +GLOBAL VOID CDECL cmd_cls() +{ +#if defined(DOSPLUS) + if(!int10_cls()) /* If no console device is */ + screen(CLS_KEY, CLS_DEF); /* active use the default */ + /* $CLS string. */ +#else /* For Concurrent DOS never*/ + screen(CLS_KEY, CLS_DEF); /* use INT 10 */ +#endif /* Finally print a CR to */ + putc('\r'); /* reset the internal */ + /* Column count. */ +} + +GLOBAL VOID revon() +{ + screen(REVON_KEY, REVON_DEF); +} + +GLOBAL VOID revoff() +{ + screen(REVOFF_KEY, REVOFF_DEF); +} + +MLOCAL VOID screen(key, def) +BYTE *key; /* Key name to match in the environment */ +BYTE *def; /* Default string to output if no match */ +{ +REG BYTE *cp; + + if(!env_scan(key, cp = (BYTE *)heap())) + /* and then search for the key */ + outs(cp); /* output the string on a match */ + else /* otherwise use the default */ + printf(def); /* supplied on entry */ +} + +/* + * This string output function will output a string containing + * a C format imbedded Octal number. This is mainly used for the + * CLS function. + */ +MLOCAL VOID outs(s) +BYTE *s; +{ +BYTE b = 0; +REG WORD f = 0; + + for(; *s; s++) { + if(f) { /* Generating an OCTAL number*/ + if(*s >= '0' && *s < '8') { /* check for a valid number */ + b <<= 3; /* and flush the buffer if it*/ + b += *s - '0'; /* is illegal. Otherwise add */ + } /* to the buffer and flush */ + else { /* after three characters */ + if(f != 3) + putc(b); + putc(*s); + f = 0; + continue; + } + + if(f-- == 1) + putc(b); + + continue; + } + + if(*s == '\\') { + f = 3; /* Initialise the Character count */ + b = 0; /* Zero the display value */ + continue; + } + + putc(*s); + } + + if(f && b) + putc(b); +} + + +/*.pa*/ +/* + * GENERAL PURPOSE STRING MANIPULATION ROUTINES + * ============================================ + * + */ +GLOBAL BYTE tolower(b) +BYTE b; +{ + if (b==0x8D) return('i'); /* For turkish dotted capital I */ + return((b < 'A' || b > 'Z') ? b : b + 0x20); +} + +GLOBAL BOOLEAN isdigit(b) +BYTE b; +{ + return (b >= '0' && b <= '9'); +} + +GLOBAL BYTE * skip_char(s) +REG BYTE *s; +{ + s++; + if (dbcs_lead(*(s - 1)) && *s >= ' ') + s++; + return(s); +} + +GLOBAL BYTE * copy_char(dest, source) +REG BYTE **dest, **source; +{ + if (dbcs_lead(**source)) + { + if (*(*source + 1) >= ' ') + { + *(*dest)++ = *(*source)++; + *(*dest)++ = *(*source); + } + } + else + { + *(*dest)++ = *(*source); + } + (*source)++; + return(*source); +} + +/* Check if character in string is blank. + Return size in bytes of blank character, zero if not blank character. */ + +GLOBAL WORD is_blank(s) +REG BYTE *s; +{ +WORD blank_size; + + if (*s == ' ' || *s == '\t') + blank_size = 1; + else if (dbcs_expected() && *s == 0x81 && *(s + 1) == 0x40) + blank_size = 2; /* KANJI space */ + else + blank_size = 0; + return(blank_size); +} + +GLOBAL BYTE * deblank(s) /* scan off leading white space */ +REG BYTE *s; /* starting address of scan */ +{ +REG WORD blank_size; + + while ((blank_size = is_blank(s)) != 0) + s += blank_size; + return (s); /* return deblanked string */ +} + +#if !(defined(MSC) || defined(MWC) || defined(TURBOC) || defined(WATCOMC)) +GLOBAL BYTE * strchr(s, b) +BYTE *s, b; +{ + while(b != *s && *s) + s++; + + if(*s) + return s; + else + return NULL; +} +#endif + +/* Convert all uppercase characters in ASCIIZ string to lowercase. + If country code is JAPAN Kanji character code pairs (ie 8 bit Kanji + escape code followed immediatly by 8 bit Kanji character code) are + not changed. */ + +GLOBAL BYTE *strlwr(s) +BYTE *s; +{ +REG BYTE *bp; + + + if (dbcs_expected()) /* are we looking out for DBCS? */ + { /* yes - DON'T CHANGE DBCS CODES */ + for (bp = s; *bp; bp++) + { + if (dbcs_lead(*bp)) /* is this first of a DBCS pair? */ + { + bp++; /* yes - skip over it */ + if (*bp == '\0') /* it is followed by its partner? */ + break; /* no - invalid DBCS, exit loop */ + } + else + *bp = tolower(*bp); /* no - lower case it */ + } + } + else + for (bp = s; *bp; bp++) + *bp = tolower(*bp); + + return s; +} + + + +/* Convert all lowercase characters in ASCIIZ string to uppercase. + Double byte characters are not changed. */ + +GLOBAL BYTE *strupr(s) +BYTE *s; +{ +REG BYTE *bp; + + + if (dbcs_expected()) /* are we looking out for DBCS? */ + { /* yes - DON'T CHANGE DBCS CODES */ + for (bp = s; *bp; bp++) + { + if (dbcs_lead(*bp)) /* is this first of a DBCS pair? */ + { + bp++; /* yes - skip over it */ + if (*bp == '\0') /* it is followed by its partner? */ + break; /* no - invalid DBCS, exit loop */ + } + else + *bp = toupper(*bp); /* no - upper case it */ + } + } + else + for (bp = s; *bp; bp++) + *bp = toupper(*bp); + + return s; +} + + + +/* + * STRNICMP does a caseless match on the two input strings for LEN + * characters. This function is only used for token matching for + * commands like FOR and IF. Double byte character set aware. + */ +GLOBAL WORD strnicmp(str1, str2, len) +REG BYTE *str1, *str2; +UWORD len; +{ + + while (len--) /* loop until len == 0 */ + { + if (dbcs_lead(*str1) || dbcs_lead(*str2)) + { /* one or both characters are DBCS */ + if (*str1 != *str2) /* are they identical? */ + return -1; /* no - return SMALER */ + + if(!*str1) + break; + + str1++; str2++; /* skip DBCS escape */ + + if (*str1 != *str2) /* are DBCS char codes identical? */ + return -1; /* no - return SMALLER */ + } + else + if (toupper(*str1) != toupper(*str2)) + return -1; + + if(!*str1) + break; + + str1++; str2++; + } + + return 0; /* return EQUAL */ +} + + + +/* + * ZAP_SPACES removes all white space from a string + */ +GLOBAL VOID zap_spaces(cp) +REG BYTE *cp; +{ +REG BYTE *cp1; + + do { + cp1 = deblank(cp); /* Skip leading whitespace */ + + if (cp1 != cp) /* If whitespace has been */ + strcpy(cp, cp1); /* skipped then move string */ + + while (*cp && !is_blank(cp)) /* Now skip over */ + cp++; /* normal characters */ + /* and repeat till the end */ + } while (*cp); +} + + +GLOBAL VOID strip_path(path, dir) +BYTE *path; +BYTE *dir; +{ + REG BYTE *cp; + REG WORD i; + + i = 0; /* assume empty path */ + for (cp=path; *cp; cp++) { /* scan the file name */ + if(dbcs_lead(*cp)) { /* If this is a DBCS */ + cp++; /* character then skip */ + continue; /* the next char */ + } + if ((*cp == *pathchar) || /* if path delimiter */ + (*cp == ':')) /* or drive specifier */ + i = (cp+1)-path; /* remember offset */ + } + strcpy (dir, path); /* make a copy */ + dir[i] = '\0'; /* discard all but path */ +} + +GLOBAL BOOLEAN getdigit(n, s) +WORD *n; /* Pointer to the word number to save */ +BYTE **s; /* String to Process */ +{ + + *n = 0; /* Zero the number */ + + while(!isdigit(**s) && **s) /* Skip all non digits */ + (*s)++; + + if(**s) { + while(isdigit(**s)) { /* Add all the digits in */ + *n = **s - '0' + *n * 10; + (*s)++; + } + return TRUE; /* and return success */ + } + else + return FALSE; +} + +/* + * Check that the number input by the user and held in S is in + * the range specified by MIN and MAX if this is so then update + * VALUE and return SUCCESS otherwise VALUE is unchabged and + * return FAILURE. + */ +GLOBAL BOOLEAN check_num(s, min, max, value) +BYTE *s; /* Input String */ +WORD min, max; /* Minimum and Maximum values */ +UWORD *value; /* Value Input */ +{ + WORD u; + + deblank(s); + + if(getdigit(&u, &s) == FALSE) + return FAILURE; + + if(*s) + return FAILURE; + + if(u < min || u > max) + return FAILURE; + + *value = u; + return SUCCESS; +} + +GLOBAL BOOLEAN iswild (path) +REG BYTE *path; +{ + while (*path && (*path != '*') && (*path != '?')) + path ++; + return (*path != '\0'); +} + +GLOBAL BOOLEAN is_filechar(s) +REG BYTE *s; +{ + if (*s == 0) return FALSE; + + if (is_blank(s) || strchr(invalid_filechar, *s)) + return FALSE; + + return TRUE; +} + +GLOBAL BOOLEAN is_pathchar(s) +REG BYTE *s; +{ + if (is_filechar(s) || + *s == *pathchar || + *s == '.' || + *s == ':' || + (*s >= 'Z'+1 && *s <= 'Z'+6)) + + return TRUE; + + return FALSE; +} + +/* + * Copy the file specification from OLDPATH to the buffer NEWPATH + * and return a pointer to the first byte after the extracted name. + * Remove any terminating ':' character from the file specification + * as the FDOS/PCMODE will try to match all characters in the string. + */ +GLOBAL BYTE * get_filename(newpath, oldpath, ambiguous) +REG BYTE *oldpath, *newpath; +BOOLEAN ambiguous; +{ +UWORD count = 0; +BYTE *pathname = oldpath; + +#if defined(PASSWORD) + while(is_pathchar(oldpath) || + ((*oldpath == *pwdchar) && (is_pathchar(oldpath + 1))) || + (ambiguous && (*oldpath == '*' || *oldpath == '?'))) { +#else + while(is_pathchar(oldpath) || + (ambiguous && (*oldpath == '*' || *oldpath == '?'))) { +#endif + if(++count < MAX_PATHLEN) { + *newpath++ = *oldpath; + if(dbcs_lead(*oldpath)) { + *newpath++=*++oldpath; + count++; + } + + } + if(*oldpath++ == ':' && count > 2 && !is_pathchar(oldpath)) { + /* Handle the CON:filename */ + newpath--; /* so loved by the users of */ + break; /* the COPY command. */ + } + } + + *newpath = '\0'; /* Terminate newpath with \0 */ + + if(count >= MAX_PATHLEN) { + longjmp(break_env, IA_FILENAME); + } + + return oldpath; +} + + +/* + * Returns the offset of the filename in a correctly formatted + * pathname string. + */ +GLOBAL BYTE * fptr(s) +REG BYTE *s; +{ + REG BYTE *tp; + + for(tp = s; *s; s++) { + if(dbcs_lead(*s)) { + s++; + continue; + } + + if(*s == ':' || *s == *pathchar) + tp = s+1; + } + return(tp); +} + +/* repwild replaces the wildcards in the destination filespec with + * the relevant information from the source filespec + * src is an explicit filename + * dest is a filename with wildcards + * + * eg src = fred.lst + * dest = *.txt becomes fred.txt + * dest = ?.* becomes f.lst + * dest = z*.* becomes zred.lst + * + * nb dest must be in a buffer with room for expansion + */ +GLOBAL VOID repwild(src,dest) +REG BYTE *src,*dest; +{ + BYTE t[13]; + BYTE *temp; + + temp=&t[0]; /* ptr to temp array */ + + if(!iswild(dest)) /* return if not wild */ + return; + + src = fptr(src); /* point to filename */ + if(!*src) /* If a blank filename has been */ + return; /* specified then return as an */ + /* invalid source specification */ + dest = fptr(dest); + + strcpy(temp,dest); /* copy wild dest to temp, as dest will get overwritten */ + + while (*temp) { /* while still more temp to process */ + if(*temp=='.') { /* advance src ptr to '.' */ + while(*src && *src!='.') + src++; + } /* drop into next check */ + + if(*src=='.') { + if(*temp=='.') { + *dest=*temp; /* copy '.' */ + goto inc; + } + else { /* advance temp to '.' or '\0', copying valid chars to dest */ + while(*temp && *temp!='.') { + if(*temp!='*' && *temp!='?') { + *dest=*temp; + dest++; + } + temp++; + } + goto skipinc; + } + } + + if(*temp=='*') { + while(*src && *src!='.') { /* copy rest of src till */ + *dest=*src; /* src = '.' or '\0' */ + dest++; + src++; + } + while(*temp && *temp!='.') /* inc temp past '*' */ + temp++; + goto skipinc; + } + + if (*temp=='?') + *dest=*src; /* copy src character to dest */ + else /* else *temp==normal char */ + *dest=*temp; /* copy temp character to dest */ + +inc: + if(*src) /* dont advance past terminator */ + src++; + + dest++; + temp++; +skipinc: + ; + } /* loop till end of while */ + + *dest='\0'; /* add terminator to dest */ +} + + +/*.pa*/ +/* + * Read a character from the console. The ABORT flag determines + * whether a ^C will abort the command or be treated as a negative + * reponse. DEF determines the default value that yes() will use. + * + */ + +EXTERN BYTE FAR * CDECL farptr(BYTE *); + +#define YES_CHAR (*farptr(YES_NO+0)) +#define NO_CHAR (*farptr(YES_NO+1)) + +GLOBAL BOOLEAN yes(abort, def) +BOOLEAN abort, def; +{ +BYTE yn; + +#if defined(CDOSTMP) + yn = (BYTE) bdos(C_RAWIO, 0xFD); /* Input a character and */ + if(abort && yn == 0x03) /* check for Control-C */ + int_break(); +#else + yn = (BYTE) msdos((abort ? MS_C_NOECHO : MS_C_RAWIN), NULL); +#endif /* read the response */ + if(yn >= ' ') /* If its printable then*/ + putc(yn); /* display the charcter */ + crlf(); /* new line */ + if(def) /* Now using the correct*/ + return((yn & 0xdf) != NO_CHAR); /* default value return */ + else /* process the users */ + return((yn & 0xdf) == YES_CHAR); /* input and return. */ +} + +/* + * ONOFF scans the command line for [=](ON|OFF) and returns + * YES, NO or FAILURE + */ +GLOBAL WORD onoff(cmd) +BYTE *cmd; +{ + + cmd = deblank(cmd); /* Deblank the string and */ + if (*cmd == '=') /* remove optional '=' */ + cmd = deblank(cmd+1); + + sprintf(heap(), "%s", MSG_ON); /* Check for ON */ + if(!strnicmp(cmd, heap(), strlen(heap()))) + if (*(deblank (cmd + strlen(heap()))) == 0) /* end of line? */ + return YES; + + sprintf(heap(), "%s", MSG_OFF); /* Check for OFF */ + if(!strnicmp(cmd, heap(), strlen(heap()))) + if (*(deblank (cmd + strlen(heap()))) == 0) /* end of line? */ + return NO; + + return FAILURE; +} + +GLOBAL VOID syntax() +{ + eprintf(MSG_SYNTAX); + crlfflg = YES; +} + +GLOBAL VOID crlf() +{ + printf("\n"); +} + +GLOBAL VOID putc(c) +BYTE c; +{ + printf("%c", c); +} + + +GLOBAL VOID puts(s) +BYTE *s; +{ + printf("%s",s); +} + + +GLOBAL VOID c_write(s, l) +BYTE *s; +UWORD l; +{ + ms_x_write (err_flag ? STDERR : STDOUT, s, l); +} + + +GLOBAL WORD e_check(ret) +REG WORD ret; +{ +REG BYTE *s; + + if (ret >= 0) /* if no error code */ + return ret; /* it's O.K. */ + + if (ret == ED_GENFAIL) ret = extended_error(); + + crlfflg = YES; /* Force a CR LF after the error */ + + switch (ret) + { + case ED_ROOM: /* Force ED_ROOM to return File Not Found msg */ + case ED_FILE: s = ERR02; break; /* File Not Found Error */ + case -1: + case ED_PATH: s = ERR03; break; /* Path Not Found */ + case ED_HANDLE: s = ERR04; break; /* Too many Open Files */ + case ED_ACCESS: s = ERR05; break; /* Access denied */ + case ED_MEMORY: s = ERR08; break; /* Insufficient Memory */ + case ED_ENVIRON: s = MSG_ENVERR;break; /* Invalid Environment */ + case ED_DRIVE: s = ERR15; break; /* Invalid Drive Spec */ + case ED_PROTECT: s = ERR19; break; /* Write Protect Disk */ + case ED_SHAREFAIL:s = ERR20; break; /* Sharing Conflict */ + default: + if(ret==ED_FAIL) + {s = ERR83; break;} /* Physical Media - FAILED */ + if(ret==ED_PASSWORD) + {s = ERR86; break;} /* Invalid Password */ +#if defined(CDOS) || defined(CDOSTMP) + if(ret==(-255)) + {s = ERR_RSC; break;} /* Resource is not Available */ +#endif + if (ED_NET >= ret && ret > ED_NETPWD) + {s = MSG_NETWORK; break;} /* Network Error */ + + s = MSG_INTERNAL; break; /* Internal Error */ + } + + eprintf(s, 0-ret); + eprintf("\n"); + return ret; +} + +#if 0 +MLOCAL BYTE *err_tab[] = { NULLPTR, /* 01 - Invalid Function Code */ + err02, /* 02 - File Not Found Error */ + err03, /* 03 - Path Not Found */ + err04, /* 04 - Too many Open Files */ + err05, /* 05 - Access denied */ + NULLPTR, /* 06 - Invalid Handle */ + NULLPTR, /* 07 - Invalid Memory Cntl Blk */ + err08, /* 08 - Insufficient Memory */ + NULLPTR, /* 09 - Invalid Memory Cntl Blk */ + msg_enverr, /* 10 - Invalid Environment */ + NULLPTR, /* 11 - Invalid Format */ + NULLPTR, /* 12 - Invalid Access Code */ + NULLPTR, /* 13 - Invalid Data */ + NULLPTR, /* 14 - Unused Error Code */ + err15, /* 15 - Invalid Drive Spec */ + err20, /* 20 - Sharing Conflict */ + err83, /* 83 - Physical Media - FAILED */ + err86, /* 86 - Invalid Password */ + err_rsc}; /* Resource is not Available */ + +GLOBAL WORD e_check(ret) +REG WORD ret; +{ +REG WORD error; /* Local copy of the error code */ + + if (ret >= 0) /* if no error code */ + return ret; /* it's O.K. */ + + crlfflg = YES; /* Force a CR LF after the error */ + error = ret; /* message has been displayed */ + if(error == ED_ROOM) /* Force ED_ROOM to return File Not */ + error = ED_FILE; /* found message. */ + + if(error < ED_DRIVE) { /* Check for error codes which have */ + if(error == ED_SHAREFAIL) /* been remapped so save space */ + error = (-16); + + if(error == ED_FAIL) /* Check for FAIL */ + error = (-17); + + if(error == ED_PASSWORD) /* Password Error */ + error = (-18); + } + + error = -error; + if(error <= sizeof(err_tab)/sizeof(BYTE *) && err_tab[error-1]) + eprintf(err_tab[error-1]); + else + eprintf("Internal Error Code %03d", error); + + return ret; +} +#endif + +GLOBAL BOOLEAN UNC(char *path) { + if (*path == '\\' && path[1] == '\\') return TRUE; + if (!*(path++) || !*(path++)) return FALSE; + while (*path) if (*(path++) == ':') return TRUE; + return FALSE; +} + + +GLOBAL BYTE * d_check(path) +REG BYTE *path; +{ + + ddrive = -1; /* return -1 for UNC names */ + if (UNC(path)) return(path); + ddrive = drive; /* if no drive is specified */ + if(!*path || path[1] != ':') /* then DDRIVE is set to */ + return(path); /* the default drive. */ + + ddrive = toupper(path[0]) - 'A'; /* Otherwise the requested */ + path += 2; /* drive is selected and */ + /* range checked */ + if(ddrive == drive) /* If the requested drive is*/ + return(path); /* the default drive is OK. */ + +/* + * If TRUE the D_CHECK only range checks the selected drive and + * returns a pointer to the next element of the path. If FALSE + * the drive is phyically selected. + */ +#if TRUE + if(!INVALID_DRV(ddrive)) + return(path); +#else + if(!INVALID_DRV(ddrive) && ms_drv_set(ddrive) == ddrive) { + ms_drv_set(drive); /* Restore Original Drive */ + return(path); /* and return Path */ + } +#endif + e_check(ED_DRIVE); /* Print an error message */ + return (NULL); /* and return a NULLPTR */ +} + + +GLOBAL BOOLEAN f_check(cmd, fchars, farray, ignore) +REG BYTE *cmd; +BYTE *fchars; +UWORD *farray; +BOOLEAN ignore; /* Ignore Illegal Options */ +{ + BYTE *s, *flg_start; + BOOLEAN flg_skip, flg_error; + BYTE c; + + *farray = 0; /* assume none of the flags present */ + + while(*cmd) { + if(*cmd++ != *switchar) + continue; + + flg_start = cmd - 1; /* Save switchar offset */ + flg_skip = FALSE; /* No Chars skipped */ + flg_error = TRUE; /* Assume first char is bad */ + FOREVER { + c = tolower(*cmd); /* Scan the string till the */ + if(!((c>='a' && c<='z')||(c>='0' && c<='9'))) + break; /* first non-alpha character*/ + + if((s=(BYTE *)strchr(fchars, c))) {/* check each char against */ + *farray |= 1 << (s-fchars); /* options string passed by */ + strcpy(cmd, cmd+1); /* the calling routine. */ + flg_error = FALSE; /* Reset error flag and set */ + } /* correct flag bit. */ + else { + flg_skip = flg_error = TRUE;/* On error set flg_skip and*/ + if(!ignore) /* break out of the loop if */ + break; /* ignore is FALSE. */ + cmd++; + } + } + + if(!flg_skip) /* If all characters have */ + *flg_start = ' '; /* been used then remove '/' */ + + if(flg_error && !ignore) { /* If an invalid char and */ + eprintf(MSG_BADOPT, *switchar, c); /* ignore is FALSE then */ + crlfflg = YES; /* print the error message */ + return FAILURE; + } + } + return SUCCESS; +} + + +GLOBAL BOOLEAN nofiles(path, attrib, exist, append_stardotstar) +REG BYTE *path; /* Search Path */ +WORD attrib; /* Search Attributes */ +BOOLEAN exist; /* Must files exist */ +BOOLEAN append_stardotstar; +{ + REG BYTE *cp; + DTA search; + WORD ret; + + if ((cp = d_check (path)) == NULLPTR) /* if bad drive letter */ + return FAILURE; /* don't do it */ + + if (!*fptr(cp)) { /* If only a path has been */ + strcat(cp, d_slash_stardotstar+3); /* specified expand to *.* */ + } + else if(!iswild (cp)) /* else is it path or file? */ + { /* wild cards imply files */ + ret = ms_x_first(path, ATTR_ALL, &search); /* get attributes */ + + if(ret == ED_ROOM) + ret = ED_FILE; + + if (ret < 0) /* if any errors */ + if(!exist && (ret == ED_FILE || ret == ED_PATH)) { + /* If file does not exist and*/ + /* this is NOT an error... */ + if (append_stardotstar) { + append_slash(path); /* "DIR .." on NOVELL drives */ + strcat(path, d_slash_stardotstar+3); + /* requires that we append */ + /* "*.*" here */ + } + return SUCCESS; /* return OK. */ + } + else { + e_check (ret); /* otherwise print message */ + return FAILURE; /* no files found */ + } + + if (search.fattr & ATTR_DIR) { /* if path names directory */ + append_slash(path); /* make it all files in it */ + strcat(path, d_slash_stardotstar+3); + } + + if(!exist) /* Must we check the file(s) */ + return SUCCESS; /* exist. If no return */ + } + + ret = ms_x_first(path, attrib, &search); /* Search for the file */ + + if(ret < 0) /* Check the error returned */ + if(!exist && (ret==ED_FILE || ret==ED_ROOM)) /* If file does not exist but*/ + return SUCCESS; /* this is not an error then */ + else { /* return Ok. */ + e_check (ret); /* otherwise print message */ + return FAILURE; /* no files found */ + } + + return SUCCESS; +} + +/* + * Check if FILENAME can be opened in Read Only mode and return the + * result. The file is then closed + */ +GLOBAL BOOLEAN file_exist(filename) +BYTE *filename; +{ +BYTE filebuf[MAX_PATHLEN]; +WORD h; + + get_filename(filebuf, filename, NO); + if((h = ms_x_open(filebuf, OPEN_READ)) > 0) { + ms_x_close(h); + return TRUE; + } + + return FALSE; +} + +/* + * Check if the handle passed to this routine is open on a FILE + * or a DEVICE. + */ +GLOBAL BOOLEAN isdev(handle) +UWORD handle; +{ + return (0x0080 & ms_x_ioctl(handle) ? TRUE : FALSE); +} + +/* + * If the string that has been passed doesn't end with a '\' add one + */ +GLOBAL append_slash(s) +BYTE *s; +{ +BYTE lastchar; + while (*s) { + lastchar = *s; + if (dbcs_lead(*s)) /* is this first of a DBCS pair? */ + s++; + s++; + } + if ((lastchar != '\\') && (lastchar != '/')) + strcat(s, pathchar); /* append a slash */ +} + + +GLOBAL VOID prompt_exec() +{ + BYTE temp[128]; + + if (!env_scan("PEXEC=",temp)) docmd(temp,TRUE); +} + +GLOBAL VOID optional_line(line) +BYTE *line; +{ + BYTE c; + BYTE *s; + + if (*line == 13 || *line == 10 || *line == 0) return; + + if (*line == '?') strcpy(line,line+1); + + if (*line == '\"') { + s = line+1; + while (*s && *s != '\"') putc(*s++); + s++; + strcpy(line,s); + } + else printf(MSG_OPTLINE,line); + + if (!yes(NO,NO)) *line = 0; + + /*printf("\n");*/ + +} diff --git a/COMMAND/SUPPORT.H b/COMMAND/SUPPORT.H new file mode 100644 index 0000000..d83dc13 --- /dev/null +++ b/COMMAND/SUPPORT.H @@ -0,0 +1,88 @@ +/* +; File : $Workfile$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +*/ + +EXTERN VOID disp_filetime(UWORD); +EXTERN VOID disp_filedate(UWORD); +EXTERN VOID disp_systime(VOID); +EXTERN VOID disp_sysdate(VOID); +EXTERN VOID revon(VOID); +EXTERN VOID revoff(VOID); +EXTERN VOID CDECL cmd_cls(VOID); +EXTERN BYTE tolower(BYTE); +EXTERN BOOLEAN isdigit(BYTE); +EXTERN BYTE * skip_char (BYTE *); +EXTERN BYTE * copy_char (BYTE **, BYTE **); +EXTERN WORD is_blank (BYTE *); +EXTERN BYTE * deblank (BYTE *); +EXTERN BOOLEAN iswild (BYTE *); +EXTERN VOID zap_spaces(BYTE *); +EXTERN VOID strip_path(BYTE *, BYTE *); +EXTERN BOOLEAN getdigit(WORD *, BYTE **); +EXTERN BOOLEAN check_num(BYTE *, UWORD, UWORD, UWORD *); +EXTERN BOOLEAN is_filechar(BYTE *); +EXTERN BOOLEAN is_pathchar(BYTE *); +EXTERN BYTE * get_filename(BYTE *, BYTE *, BOOLEAN); +EXTERN BYTE * fptr(BYTE *); +EXTERN VOID repwild(BYTE *, BYTE *); +EXTERN BOOLEAN yes(BOOLEAN ,BOOLEAN); +EXTERN WORD onoff(BYTE *); +EXTERN VOID syntax (VOID); +EXTERN VOID crlf (VOID); +EXTERN VOID putc (BYTE); +EXTERN VOID puts(BYTE *); +EXTERN BOOLEAN isdigit(BYTE); + +EXTERN BYTE * strlwr(BYTE *); +EXTERN BYTE * strupr(BYTE *); +EXTERN WORD strnicmp(const BYTE *, const BYTE *, UWORD); + +EXTERN WORD e_check(WORD); +EXTERN BYTE * d_check(BYTE *); +EXTERN BOOLEAN f_check(BYTE *, BYTE *, UWORD *, BOOLEAN); +EXTERN BOOLEAN nofiles(BYTE *, WORD, BOOLEAN, BOOLEAN); +EXTERN BOOLEAN file_exist(BYTE *); +EXTERN BOOLEAN isdev(UWORD); + +EXTERN VOID CDECL printf(BYTE *, ...); +EXTERN VOID CDECL eprintf(BYTE *, ...); +EXTERN VOID CDECL sprintf(BYTE *, BYTE *, ...); + +EXTERN UWORD CDECL findeof(BYTE FAR *, UWORD); + +EXTERN VOID append_slash(BYTE *); +EXTERN VOID prompt_exec(VOID); +EXTERN VOID optional_line(BYTE *); +EXTERN BYTE *day_names(UWORD); diff --git a/COMMAND/TOUPPER.H b/COMMAND/TOUPPER.H new file mode 100644 index 0000000..96bcbd4 --- /dev/null +++ b/COMMAND/TOUPPER.H @@ -0,0 +1,348 @@ +/* +; File : $Workfile$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +*/ + +#include + +#if defined(DLS) +EXTERN BYTE * cdecl dls_msg1(UWORD); + +#define MSG_LBL dls_msg1(DLS_msg_lbl) +#define MSG_OKLBL dls_msg1(DLS_msg_oklbl) +#define MSG_NOLBL dls_msg1(DLS_msg_nolbl) +#define MSG_FILES dls_msg1(DLS_msg_files) +#define MSG_FREE dls_msg1(DLS_msg_free) +#define MSG_EXIST dls_msg1(DLS_msg_exist) +#define MSG_NDIR dls_msg1(DLS_msg_ndir) +#define MSG_NSYS dls_msg1(DLS_msg_nsys) +#define MSG_BADOPT dls_msg1(DLS_msg_badopt) +#define MSG_FULL dls_msg1(DLS_msg_full) +#define MSG_SYNTAX dls_msg1(DLS_msg_syntax) +#define MSG_BADCMD dls_msg1(DLS_msg_badcmd) +#define MSG_PATHDRV dls_msg1(DLS_msg_pathdrv) +#define MSG_BATTERM dls_msg1(DLS_msg_batterm) +#define MSG_BATMISS dls_msg1(DLS_msg_batmiss) +#define MSG_BATNEST dls_msg1(DLS_msg_batnest) +#define MSG_DIR dls_msg1(DLS_msg_dir) +#define MSG_ECHO dls_msg1(DLS_msg_echo) +#define MSG_ERAQ dls_msg1(DLS_msg_eraq) +#define MSG_ERAALL dls_msg1(DLS_msg_eraall) +#define MSG_ERA dls_msg1(DLS_msg_era) +#define MSG_LABEL dls_msg1(DLS_msg_label) +#define MSG_MKDIR dls_msg1(DLS_msg_mkdir) +#define MSG_PATH dls_msg1(DLS_msg_path) +#define MSG_REN dls_msg1(DLS_msg_ren) +#define MSG_USE_RENDIR dls_msg1(DLS_msg_use_rendir) +#define MSG_RMDIR dls_msg1(DLS_msg_rmdir) +#define MSG_BREAK dls_msg1(DLS_msg_break) +#define MSG_VERIFY dls_msg1(DLS_msg_verify) +#define MSG_IDLE dls_msg1(DLS_msg_idle) +#define MSG_CPYRIGHT dls_msg1(DLS_msg_cpyright) +#define MSG_VERSION dls_msg1(DLS_msg_version) +#define MSG_CPYSELF dls_msg1(DLS_msg_cpyself) +#define MSG_FCOPIED dls_msg1(DLS_msg_fcopied) +#define MSG_DISABLED dls_msg1(DLS_msg_disabled) +#define MSG_ENVFULL dls_msg1(DLS_msg_envfull) +#define MSG_ENVERR dls_msg1(DLS_msg_enverr) +#define MSG_BADOS dls_msg1(DLS_msg_bados) +#define MSG_LOADPATH dls_msg1(DLS_msg_loadpath) +#define MSG_INOP dls_msg1(DLS_msg_inop) +#define MSG_BINRD dls_msg1(DLS_msg_binrd) +#define MSG_DLOST dls_msg1(DLS_msg_dlost) +#define MSG_ONOFF dls_msg1(DLS_msg_onoff) +#define MSG_NETWORK dls_msg1(DLS_msg_network) +#define ERR_FILE dls_msg1(DLS_err_file) +#define ERR02 dls_msg1(DLS_err02) +#define ERR03 dls_msg1(DLS_err03) +#define ERR04 dls_msg1(DLS_err04) +#define ERR05 dls_msg1(DLS_err05) +#define ERR08 dls_msg1(DLS_err08) +#define ERR15 dls_msg1(DLS_err15) +#define ERR20 dls_msg1(DLS_err20) +#define ERR83 dls_msg1(DLS_err83) +#define ERR86 dls_msg1(DLS_err86) +#define ERR19 dls_msg1(DLS_err19) +#define MSG_NEEDPATH dls_msg1(DLS_msg_needpath) +#define MSG_NEEDFILE dls_msg1(DLS_msg_needfile) +#define MSG_NEEDDEV dls_msg1(DLS_msg_needdev) +#define SUN_D dls_msg1(DLS_sun_d) +#define MON_D dls_msg1(DLS_mon_d) +#define TUE_D dls_msg1(DLS_tue_d) +#define WED_D dls_msg1(DLS_wed_d) +#define THU_D dls_msg1(DLS_thu_d) +#define FRI_D dls_msg1(DLS_fri_d) +#define SAT_D dls_msg1(DLS_sat_d) +#define CUR_TIME dls_msg1(DLS_cur_time) +#define NEW_TIME dls_msg1(DLS_new_time) +#define INV_TIME dls_msg1(DLS_inv_time) +#define CUR_DATE dls_msg1(DLS_cur_date) +#define NEW_DATE dls_msg1(DLS_new_date) +#define INV_DATE dls_msg1(DLS_inv_date) +#define US_DATE dls_msg1(DLS_us_date) +#define EURO_DATE dls_msg1(DLS_euro_date) +#define JAP_DATE dls_msg1(DLS_jap_date) +#define INV_NUM dls_msg1(DLS_inv_num) +#define MSG_LONGJMP dls_msg1(DLS_msg_longjmp) +#define MSG_INACTIVE dls_msg1(DLS_msg_inactive) +#define MSG_OUTACTIVE dls_msg1(DLS_msg_outactive) +#define MSG_ON dls_msg1(DLS_msg_on) +#define MSG_OFF dls_msg1(DLS_msg_off) +#define YES_NO dls_msg1(DLS_yes_no) +#define MSG_PAUSE dls_msg1(DLS_msg_pause) +#define MSG_INTERNAL dls_msg1(DLS_msg_internal) +#define MSG_DEBUG dls_msg1(DLS_msg_debug) +#define MSG_DEVFAIL dls_msg1(DLS_msg_devfail) +#define HELP_COM dls_msg1(DLS_help_com) +#define MSG_GOSUB dls_msg1(DLS_msg_gosub) +#define MSG_RETURN dls_msg1(DLS_msg_return) +#define MSG_OPTLINE dls_msg1(DLS_msg_optline) +#define AM_TIME dls_msg1(DLS_am_time) +#define PM_TIME dls_msg1(DLS_pm_time) +#define GREETING_MORNING dls_msg1(DLS_greeting_morning) +#define GREETING_AFTERNOON dls_msg1(DLS_greeting_afternoon) +#define GREETING_EVENING dls_msg1(DLS_greeting_evening) +#define JAN_M dls_msg1(DLS_jan_m) +#define FEB_M dls_msg1(DLS_feb_m) +#define MAR_M dls_msg1(DLS_mar_m) +#define APR_M dls_msg1(DLS_apr_m) +#define MAY_M dls_msg1(DLS_may_m) +#define JUN_M dls_msg1(DLS_jun_m) +#define JUL_M dls_msg1(DLS_jul_m) +#define AUG_M dls_msg1(DLS_aug_m) +#define SEP_M dls_msg1(DLS_sep_m) +#define OCT_M dls_msg1(DLS_oct_m) +#define NOV_M dls_msg1(DLS_nov_m) +#define DEC_M dls_msg1(DLS_dec_m) +#define MSG_DRV_INVALID dls_msg1(DLS_msg_drv_invalid) + +#define MSG_CURCP dls_msg1(DLS_msg_curcp) +#define MSG_BADCP dls_msg1(DLS_msg_badcp) +#define MSG_CPNF dls_msg1(DLS_msg_cpnf) +#define MSG_NETSUBST dls_msg1(DLS_msg_netsubst) +#define MSG_NETASSIGN dls_msg1(DLS_msg_netassign) +#define MSG_OEMCPYRT dls_msg1(DLS_msg_oemcpyrt) +#define MSG_SERNO dls_msg1(DLS_msg_serialno) + +#else + +#define MSG_LBL msg_lbl +#define MSG_OKLBL msg_oklbl +#define MSG_NOLBL msg_nolbl +#define MSG_FILES msg_files +#define MSG_FREE msg_free +#define MSG_EXIST msg_exist +#define MSG_NDIR msg_ndir +#define MSG_NSYS msg_nsys +#define MSG_BADOPT msg_badopt +#define MSG_FULL msg_full +#define MSG_DEVFAIL msg_devfail +#define MSG_SYNTAX msg_syntax +#define MSG_BADCMD msg_badcmd +#define MSG_PATHDRV msg_pathdrv +#define MSG_OPTLINE msg_optline +#define MSG_BATTERM msg_batterm +#define MSG_BATMISS msg_batmiss +#define MSG_BATNEST msg_batnest +#define MSG_DIR msg_dir +#define MSG_ECHO msg_echo +#define MSG_XBATCH msg_xbatch +#define MSG_ERAQ msg_eraq +#define MSG_ERAALL msg_eraall +#define MSG_ERA msg_era +#define MSG_LABEL msg_label +#define MSG_GOSUB msg_gosub +#define MSG_RETURN msg_return +#define MSG_MKDIR msg_mkdir +#define MSG_PATH msg_path +#define MSG_REN msg_ren +#define MSG_USE_RENDIR msg_use_rendir +#define MSG_RMDIR msg_rmdir +#define MSG_BREAK msg_break +#define MSG_VERIFY msg_verify +#define MSG_IDLE msg_idle +#define MSG_CPYRIGHT msg_cpyright +#define MSG_VERSION msg_version +#define MSG_CPYSELF msg_cpyself +#define MSG_FCOPIED msg_fcopied +#define MSG_DISABLED msg_disabled +#define MSG_ENVFULL msg_envfull +#define MSG_ENVERR msg_enverr +#define MSG_BADOS msg_bados +#define MSG_LOADPATH msg_loadpath +#define MSG_INOP msg_inop +#define MSG_BINRD msg_binrd +#define MSG_DLOST msg_dlost +#define MSG_ONOFF msg_onoff +#define ERR_FILE err_file +#define ERR02 err02 +#define ERR03 err03 +#define ERR04 err04 +#define ERR05 err05 +#define ERR08 err08 +#define ERR15 err15 +#define ERR20 err20 +#define ERR83 err83 +#define ERR86 err86 +#define ERR19 err19 +#define MSG_NEEDPATH msg_needpath +#define MSG_NEEDFILE msg_needfile +#define MSG_NEEDDEV msg_needdev +#define SUN_D sun_d +#define MON_D mon_d +#define TUE_D tue_d +#define WED_D wed_d +#define THU_D thu_d +#define FRI_D fri_d +#define SAT_D sat_d +#define JAN_M jan_m +#define FEB_M feb_m +#define MAR_M mar_m +#define APR_M apr_m +#define MAY_M may_m +#define JUN_M jun_m +#define JUL_M jul_m +#define AUG_M aug_m +#define SEP_M sep_m +#define OCT_M oct_m +#define NOV_M nov_m +#define DEC_M dec_m +#define CUR_TIME cur_time +#define NEW_TIME new_time +#define INV_TIME inv_time +#define CUR_DATE cur_date +#define NEW_DATE new_date +#define INV_DATE inv_date +#define US_DATE us_date +#define EURO_DATE euro_date +#define JAP_DATE jap_date +#define INV_NUM inv_num +#define MSG_INACTIVE msg_inactive +#define MSG_OUTACTIVE msg_outactive +#define MSG_ON msg_on +#define MSG_OFF msg_off +#define YES_NO yes_no +#define MSG_PAUSE msg_pause +#define MSG_INTERNAL msg_internal +#define MSG_NETWORK msg_network +#define MSG_DEBUG msg_debug +#define MSG_LONGJMP msg_longjmp +/*RG-05*/ +#define HELP_COM help_com +#define HELP_PROG help_prog +#define MSG_NOHELPPROG msg_nohelpprog +/*RG-05-end*/ + +#define AM_TIME am_time +#define PM_TIME pm_time + +#define GREETING_MORNING greeting_morning +#define GREETING_AFTERNOON greeting_afternoon +#define GREETING_EVENING greeting_evening + +#define MSG_DRV_INVALID msg_drv_invalid + +#if defined(CPM) +#define CUR_USER cur_user +#define INV_USER inv_user +#define MSG_SINGLECPM msg_singlecpm +#endif + + +#if defined(CDOSTMP) || defined(CPM) +#define MSG_CE_NO0 msg_ce_no0 +#define MSG_CE_NO2 msg_ce_no2 +#define MSG_CE_NO3 msg_ce_no3 +#define MSG_CE_NO4 msg_ce_no4 +#define MSG_CE_NO6 msg_ce_no6 +#define MSG_CE_NO7 msg_ce_no7 +#define MSG_CE_NO8 msg_ce_no8 +#define MSG_DRIVE msg_drive +#define MSG_READ msg_read +#define MSG_WRITE msg_write +#define MSG_ABORT msg_abort +#define MSG_RETRY msg_retry +#define MSG_IGNORE msg_ignore +#define MSG_FAIL msg_fail +#define MSG_NE_NO0 msg_ne_no0 +#define MSG_NE_NO1 msg_ne_no1 +#define MSG_NE_NO2 msg_ne_no2 +#define MSG_NE_NO3 msg_ne_no3 +#define MSG_NE_NO4 msg_ne_no4 +#define MSG_NE_NO5 msg_ne_no5 +#define MSG_NE_NO6 msg_ne_no6 +#define MSG_SERVER msg_server +#endif + + +#if defined(CDOSTMP) || defined(CDOS) +#define MSG_NOGOOD msg_nogood +#define MSG_NOFAIL msg_nofail +#define MSG_NOATCH msg_noatch +#define MSG_NFGOOD msg_nfgood +#define MSG_NFFAIL msg_nffail +#define MSG_NFATCH msg_nfatch +#define MSG_PWDPRMPT msg_pwdprmpt +#define MSG_BADSTOP msg_badstop +#define MSG_BANK msg_bank +#define MSG_SUSPEND msg_suspend +#define MSG_MEMSIZE msg_memsize +#define MSG_LIMSIZE msg_limsize +#define MSG_LOCAL msg_local +#define MSG_REMOTE msg_remote +#define MSG_APPEND msg_append +#define MSG_CPYPRMPT msg_cpyprmpt +#define ERR_RSC err_rsc +#define MSG_LIMOFF msg_limoff +/*RG-01*/ +#if !defined(NOSECURITY) +#define MSG_UHAVEMAIL msg_uhavemail +#endif +/*RG-01-end*/ +/*RG-05-*/ +#define MSG_HELP msg_help +/*RG-05-end*/ +#endif + +#if defined(DOSPLUS) +#define MSG_CURCP msg_curcp +#define MSG_BADCP msg_badcp +#define MSG_CPNF msg_cpnf +#define MSG_NETSUBST msg_netsubst +#define MSG_NETASSIGN msg_netassign +#define MSG_OEMCPYRT msg_oemcpyrt +#define MSG_SERIALNO msg_serialno +#endif + +#endif diff --git a/COMMAND/TXHELP.ASM b/COMMAND/TXHELP.ASM new file mode 100644 index 0000000..063fcb7 --- /dev/null +++ b/COMMAND/TXHELP.ASM @@ -0,0 +1,312 @@ +NUL equ 0 +BS equ 8 +TAB equ 9 +LF equ 10 +CR equ 13 + +PRI equ 0 +ALT equ 1 + +DGROUP group _DATA +CHELP group _HELP + +_DATA segment word public 'DATA' + assume ds:DGROUP, cs:DGROUP + + public _single_table + + public _dls_table + + public _dls_init + public _dls_get_table + public _dls_language + +_dls_table dw 0 + +__dls_init__ db 0 + +_single_table label word + +; Source .TFT file: 'TMP1.$$$' + public help_aaa +help_aaa equ $ - _single_table + dw CHELP:_help_aaa + public help_and +help_and equ $ - _single_table + dw CHELP:_help_and + public help_break +help_break equ $ - _single_table + dw CHELP:_help_break + public help_call +help_call equ $ - _single_table + dw CHELP:_help_call + public help_chcp +help_chcp equ $ - _single_table + dw CHELP:_help_chcp + public help_chdir +help_chdir equ $ - _single_table + dw CHELP:_help_chdir + public help_cls +help_cls equ $ - _single_table + dw CHELP:_help_cls + public help_copy +help_copy equ $ - _single_table + dw CHELP:_help_copy + public help_ctty +help_ctty equ $ - _single_table + dw CHELP:_help_ctty + public help_date +help_date equ $ - _single_table + dw CHELP:_help_date + public help_del +help_del equ $ - _single_table + dw CHELP:_help_del + public help_delq +help_delq equ $ - _single_table + dw CHELP:_help_delq + public help_dir +help_dir equ $ - _single_table + dw CHELP:_help_dir + public help_echo +help_echo equ $ - _single_table + dw CHELP:_help_echo + public help_eraq +help_eraq equ $ - _single_table + dw CHELP:_help_eraq + public help_erase +help_erase equ $ - _single_table + dw CHELP:_help_erase + public help_exit +help_exit equ $ - _single_table + dw CHELP:_help_exit + public help_for +help_for equ $ - _single_table + dw CHELP:_help_for + public help_gosubreturn +help_gosubreturn equ $ - _single_table + dw CHELP:_help_gosubreturn + public help_goto +help_goto equ $ - _single_table + dw CHELP:_help_goto + public help_hiload +help_hiload equ $ - _single_table + dw CHELP:_help_hiload + public help_idle +help_idle equ $ - _single_table + dw CHELP:_help_idle + public help_if +help_if equ $ - _single_table + dw CHELP:_help_if + public help_mkdir +help_mkdir equ $ - _single_table + dw CHELP:_help_mkdir + public help_or +help_or equ $ - _single_table + dw CHELP:_help_or + public help_path +help_path equ $ - _single_table + dw CHELP:_help_path + public help_pause +help_pause equ $ - _single_table + dw CHELP:_help_pause + public help_prompt +help_prompt equ $ - _single_table + dw CHELP:_help_prompt + public help_rem +help_rem equ $ - _single_table + dw CHELP:_help_rem + public help_rename +help_rename equ $ - _single_table + dw CHELP:_help_rename + public help_rmdir +help_rmdir equ $ - _single_table + dw CHELP:_help_rmdir + public help_set +help_set equ $ - _single_table + dw CHELP:_help_set + public help_shift +help_shift equ $ - _single_table + dw CHELP:_help_shift + public help_switch +help_switch equ $ - _single_table + dw CHELP:_help_switch + public help_time +help_time equ $ - _single_table + dw CHELP:_help_time + public help_truename +help_truename equ $ - _single_table + dw CHELP:_help_truename + public help_type +help_type equ $ - _single_table + dw CHELP:_help_type + public help_ver +help_ver equ $ - _single_table + dw CHELP:_help_ver + public help_verify +help_verify equ $ - _single_table + dw CHELP:_help_verify + public help_vol +help_vol equ $ - _single_table + dw CHELP:_help_vol + + +_DATA ends + +_HELP segment word public 'HELP' + + assume ds:CHELP, cs:CHELP + +; Source .TFT file: 'TMP1.$$$' +_help_aaa db "Available internal commands are:", LF, LF, NUL +_help_truename db "Reserved command.", NUL +_help_break db "BREAK", TAB, "Controls how you break out of programs using Ctrl+Break or Ctrl+C.", LF, LF, "Syntax:", LF, TAB, "BREAK /H", LF, TAB, "BREAK [ON|OFF]", LF, LF, TAB, "/H", TAB, "gives this scre" + db "en", LF, TAB, "ON", TAB, "turns break checking on (default)", LF, TAB, "OFF", TAB, "turns break checking off", LF, TAB, "none", TAB, "no parameters displays the state of break ON or OFF", LF + db LF, "Examples:", LF, TAB, "BREAK OFF", LF, TAB, "BREAK", NUL +_help_call db "CALL", TAB, "Used in batch files, this command will call another batch file and", LF, TAB, "return when it has finished executing it.", LF, LF, "Syntax:", LF, TAB, "CALL /H", LF, TAB, "CALL [d" + db ":][path]file[.BAT][ params[...]]", LF, LF, TAB, "/H", TAB, "gives this screen", LF, TAB, "d:", TAB, "drive where batch file resides", LF, TAB, "path", TAB, "path where batch file resides", LF + db TAB, "file", TAB, "name of batch file to call", LF, TAB, ".BAT", TAB, "optional filename extension", LF, TAB, "params", TAB, "parameter list read by called batch file as %%1 %%2 ... etc", LF, LF + db "Examples:", LF, TAB, "CALL doit.bat", LF, TAB, "CALL setdate 5 Nov 90", NUL +_help_chdir db "CHDIR", TAB, "Shows the path, or changes the current directory. Can be", LF, TAB, "abbreviated to CD.", LF, LF, "Syntax:", LF, TAB, "CHDIR /H", LF, TAB, "CHDIR [[d:]dirpath]", LF, LF, TAB, "/" + db "H", TAB, "gives this screen", LF, TAB, "d:", TAB, "drive on which dirpath resides", LF, TAB, "dirpath", TAB, "directory to change to", LF, TAB, "none", TAB, "no parameters displays the curre" + db "nt drive and directory", LF, LF, "Examples:", LF, TAB, "CHDIR c:\homedir", LF, TAB, "CD ..", LF, TAB, "CD", NUL +_help_cls db "CLS", TAB, "Clears the display screen.", LF, LF, "Syntax:", LF, TAB, "CLS /H", LF, LF, TAB, TAB, "/H", TAB, "gives this screen", LF, LF, "Example:", LF, TAB, "CLS", NUL +_help_copy db "COPY", TAB, "Copies or combines files", LF, LF, "Syntax:", LF, " COPY /H", LF, " COPY device|wildspec[+wildspec...][switches] [device|filespec[switches]]", LF, LF, " device", TAB, "is CON" + db ",LPTn,PRN,NUL,COMn or AUX", LF, " wildspec", TAB, "source device, file or list of files to be included", LF, " filespec", TAB, "destination file or device", LF, " switches", TAB, "/A treat" + db " file as ASCII", LF, TAB, TAB, "/B treat source file as binary (ignore Ctrl+Z in file)", LF, TAB, TAB, "/V verify source and destination match", LF, TAB, TAB, "/S include system or hidden fil" + db "es in copy", LF, TAB, TAB, "/C prompt for confirmation by user before copying", LF, TAB, TAB, "/Z zeros top bit of every byte in destination", LF, "Examples:", LF, TAB, "COPY file1+file2 file" + db "3", LF, TAB, "COPY *.txt c:dir1", NUL +_help_date db "DATE", TAB, "Displays and changes the date.", LF, LF, "Syntax:", LF, TAB, "DATE /H", LF, TAB, "DATE [mm-dd-yy] (US format)", LF, TAB, "DATE [dd-mm-yy] (European format)", LF, TAB, "DATE [yy-" + db "mm-dd] (Japanese format)", LF, LF, TAB, "/H", TAB, "gives this screen", LF, TAB, "mm", TAB, "month 1 to 12", LF, TAB, "dd", TAB, "day 1 to 31", LF, TAB, "yy", TAB, "2 or 4 digit year", LF + db TAB, "none", TAB, "no parameters displays date then prompts for new date", LF, LF, "Examples:", LF, TAB, "DATE 16-11-90", LF, TAB, "DATE", NUL +_help_del db "DEL", TAB, "Erases files.", LF, LF, "Syntax:", LF, TAB, "DEL /H", LF, TAB, "DEL wildspec [/C|/P][/S]", LF, LF, TAB, "/H", TAB, " gives this screen", LF, TAB, "/C|/P", TAB, " prompt befo" + db "re deletion", LF, TAB, "/S", TAB, " include system files", LF, TAB, "wildspec file to be deleted (wildcards allowed)", LF, LF, "Examples:", LF, TAB, "DEL *.EXE /CS", LF, TAB, "DEL MYFILE." + db "TXT", NUL +_help_delq db "DELQ", TAB, "Erases files but queries you before doing so.", LF, LF, "Syntax:", LF, TAB, "DELQ /H", LF, TAB, "DELQ wildspec [/S]", LF, LF, TAB, "/H", TAB, " gives this screen", LF, TAB, "/" + db "S", TAB, " include system files", LF, TAB, "wildspec file to be deleted (wildcards allowed)", LF, LF, "Examples:", LF, TAB, "DELQ *.EXE /S", LF, TAB, "DELQ MYFILE.TXT", NUL +_help_dir db "DIR", TAB, "Displays the files in a directory.", LF, LF, "Syntax:", TAB, "DIR /H", LF, TAB, "DIR [wildspec] [/L|/2|/W] [/P|/N] [/A|/D|/S] [/C|/R]", LF, LF, TAB, "/H", TAB, " gives this scree" + db "n", LF, TAB, "wildspec files to be displayed (wildcards allowed)", LF, TAB, "/A", TAB, " displays all files", LF, TAB, "/C or /R make other switches default for next time", LF, TAB, "/D", TAB + db " displays files without system attribute set (default)", LF, TAB, "/L", TAB, " long format. Include size, date and time (default)", LF, TAB, "/2", TAB, " as above except files are displayed i" + db "n two columns", LF, TAB, "/N", TAB, " return to default paging switch", LF, TAB, "/P", TAB, " pause at end of full page. Default is no paging", LF, TAB, "/S", TAB, " displays files with sy" + db "stem attribute set", LF, TAB, "/W", TAB, " wide format. Displays file and directory names only", LF, TAB, "none", TAB, " no parameters displays all files using current default", LF, TAB, TAB + db " switches", LF, "Example:", LF, TAB, "DIR /C /W", NUL +_help_echo db "ECHO", TAB, "Used in batch files, this command is used to display a message", LF, TAB, "to the screen.", LF, LF, "Syntax:", LF, TAB, "ECHO /H", LF, TAB, "ECHO [ON|OFF|string]", LF, LF, TAB, "/" + db "H", TAB, "gives this screen", LF, TAB, "ON", TAB, "turn echoing on (default)", LF, TAB, "OFF", TAB, "turn echoing off", LF, TAB, "string", TAB, "display ""string""", LF, LF, "Examples:", LF + db TAB, "ECHO OFF", LF, TAB, "ECHO You are running the %%OS%% operating system.", NUL +_help_eraq db "ERAQ", TAB, "Erases files but queries you before doing so.", LF, TAB, "ERAQ wildspec [/S]", LF, LF, TAB, "/H", TAB, " gives this screen", LF, TAB, "/S", TAB, " include system files", LF, TAB + db "wildspec file to be deleted (wildcards allowed)", LF, LF, "Examples:", LF, TAB, "ERAQ *.EXE /S", LF, TAB, "ERAQ MYFILE.TXT", NUL +_help_erase db "ERASE", TAB, "Erases files. Can be abbreviated to ERA.", LF, LF, "Syntax:", LF, TAB, "ERASE /H", LF, TAB, "ERASE wildspec [/C|/P][/S]", LF, LF, TAB, "/H", TAB, " gives this screen", LF, TAB + db "/C|/P", TAB, " prompt before deletion", LF, TAB, "/S", TAB, " include system files", LF, TAB, "wildspec file to be deleted (wildcards allowed)", LF, LF, "Examples:", LF, TAB, "ERASE *.EXE" + db " /CS", LF, TAB, "ERA MYFILE.TXT", NUL +_help_exit db "EXIT", TAB, "Terminates a batch file or secondary command processor.", LF, LF, "Syntax:", LF, TAB, "EXIT [/H]", LF, LF, TAB, "/H", TAB, "gives this screen", LF, LF, "Example:", LF, TAB, "E" + db "XIT", NUL +_help_for db "FOR", TAB, "Most commonly used in batch files, this command is used to repeat", LF, TAB, "a sequence of commands substituting a filename from a list with each", LF, TAB, "iteration of the loop.", LF + db LF, "Syntax:", LF, TAB, "FOR /H", LF, TAB, "FOR %%[%%]var IN (fileset) DO command", LF, LF, TAB, "%%%%var", TAB, " variable used to reference a filename in a batch file", LF, TAB, "%%var", TAB + db " variable used to reference a filename at the command line", LF, TAB, "fileset", TAB, " list of files to perform operation upon", LF, TAB, "command", TAB, " operation to be performed", LF, LF + db "Example:", LF, TAB, "FOR %%%%f IN (myprog.asm acct.bas acct2.bas)DO TYPE %%%%f", LF, TAB, "FOR %%f IN (myprog.asm acct.bas acct2.bas)DO TYPE %%f", NUL +_help_goto db "GOTO", TAB, "Used in batch files, this command causes execution of commands", LF, TAB, "to alter to a specified point in the batch file.", LF, LF, "Syntax:", LF, TAB, "GOTO /H", LF, TAB, "GOTO" + db " label", LF, LF, TAB, "/H", TAB, "gives this screen", LF, TAB, "label", TAB, "label to jump to", LF, LF, "Example:", LF, TAB, ":start", LF, TAB, "type myfile.txt", LF, TAB, "goto start", NUL +_help_gosubreturn db "GOSUB/RETURN", LF, TAB, "The GOSUB command causes execution to jump to a specified point ", LF, TAB, "in a batch file. When a RETURN command is encountered, execution ", LF, TAB, "will continue f" + db "rom the line after the GOSUB.", LF, LF, "Syntax:", LF, TAB, "GOSUB label", LF, LF, "Example:", LF, TAB, "GOSUB myfunc", LF, TAB, "GOTO finished", LF, TAB, ":myfunc", LF, TAB, "ECHO Hello" + db LF, TAB, "RETURN", LF, TAB, ":finished", NUL +_help_switch db "SWITCH", TAB, "This command allows the user to select an entry from a menu ", LF, TAB, "in a batch file. The keys 1 - 9 will select the appropriate label ", LF, TAB, "from the command line. A RETU" + db "RN command returns execution to the ", LF, TAB, "line after the SWITCH command.", LF, LF, "Syntax:", LF, TAB, "SWITCH label [,label..]", LF, LF, "Example:", LF, TAB, "SWITCH label1,label2,la" + db "bel3,label4", LF, TAB, "GOTO finished", LF, TAB, ":label1", LF, TAB, "ECHO Hello", LF, TAB, "RETURN", LF, TAB, ":label2", LF, TAB, "ECHO World", LF, TAB, "RETURN", LF, TAB, "...", NUL +_help_idle db "IDLE", TAB, "Turns dynamic idle detection on or off.", LF, LF, "Syntax:", LF, TAB, "IDLE /H", LF, TAB, "IDLE [= ][ON|OFF]", LF, LF, TAB, "/H", TAB, "gives this screen", LF, TAB, "ON", TAB + db "enables idle detection", LF, TAB, "OFF", TAB, "disables idle detection", LF, TAB, "none", TAB, "no parameters displays the state ON or OFF", LF, LF, "Example:", LF, TAB, "IDLE = ON", LF, TAB + db "IDLE OFF", NUL +_help_if db "IF", TAB, "Used in batch files, this command allows conditional execution", LF, TAB, "of commands based upon specified conditions.", LF, LF, "Syntax:", TAB, "IF /H", LF, TAB, "IF [NOT] conditio" + db "n [AND [NOT] condition] [OR [NOT] condition] command", LF, LF, TAB, "/H", TAB, " gives this screen", LF, LF, TAB, "condition ERRORLEVEL [==] number", LF, TAB, TAB, " EXIST [==] filespec" + db LF, TAB, TAB, " string1 ==|!=|>|>=|<|<=|<> string2", LF, TAB, TAB, " #value1 ==|!=|>|>=|<|<=|<> #value2", LF, LF, "Examples: IF EXIST c:\bin\editor.exe c:\bin\editor %%1", LF, TAB, " IF " + db "NOT ""%%1"" == ""english"" ECHO Invalid Language Specified", LF, TAB, " IF #%%mem%% < #540 ECHO Not Enough Memory", NUL +_help_and db "AND", TAB, "Used with the IF command.", LF, TAB, "Enter IF /? for more information.", LF, NUL +_help_or db "OR", TAB, "Used with the IF command.", LF, TAB, "Enter IF /? for more information.", LF, NUL +_help_mkdir db "MKDIR", TAB, "Creates a subdirectory. Can be abbreviated to MD.", LF, LF, "Syntax:", LF, TAB, "MKDIR /H", LF, TAB, "MKDIR [d:]dirpath", LF, LF, TAB, "/H", TAB, " gives this screen", LF, TAB + db "d:", TAB, " drive", LF, TAB, "dirpath", TAB, " subdirectory to create", LF, LF, "Examples:", LF, TAB, "MKDIR \USERS\ROGER", LF, TAB, "MD ..\USERS\LESLEY", NUL +_help_path db "PATH", TAB, "Sets or displays a search path for commands or batch files.", LF, LF, "Syntax:", LF, TAB, "PATH /H", LF, TAB, "PATH [[d:]dirpath[;[d:]dirpath...]]", LF, LF, TAB, "d:", TAB, "dri" + db "ve on which dirpath resides", LF, TAB, "dirpath", TAB, "subdirectory path", LF, TAB, ";", TAB, "path separator, or on its own, sets PATH to nothing", LF, TAB, "none", TAB, "no parameters disp" + db "lays current path", LF, LF, "Examples:", LF, TAB, "PATH", LF, TAB, "PATH c:\osutils;c:\bin;d:\users\roger", LF, TAB, "PATH;", NUL +_help_pause db "PAUSE", TAB, "Used in batch files, this command halts execution of the batch", LF, TAB, "file until a key is pressed.", LF, LF, "Syntax:", LF, TAB, "PAUSE /H", LF, TAB, "PAUSE [comment]", LF, LF + db TAB, "/H", TAB, "gives this screen", LF, TAB, "comment", TAB, "displays ""comment"" if echo is on", LF, TAB, "none", TAB, "no parameters displays default pause message", LF, LF, "Examples:", LF + db TAB, "PAUSE", LF, TAB, "Strike a key when ready . . .", LF, LF, TAB, "PAUSE Put disk number 2 in drive A:", LF, TAB, "Strike a key when ready . . .", NUL +_help_prompt db "PROMPT", TAB, "Modifies the command prompt.", LF, LF, "Syntax:", TAB, "PROMPT /H or PROMPT [$list]", LF, LF, "Where list can be:", LF, " $ $ character", TAB, TAB, "t time", LF, " d date", TAB + db TAB, TAB, "p current directory", LF, " v OS version number", TAB, TAB, "n drive letter", LF, " g the "">"" character", TAB, TAB, "l the ""<"" character", LF, " b the ""|"" character", TAB + db TAB, "q the ""="" character", LF, " h backspace", TAB, TAB, TAB, "e the escape character (ASCII 27)", LF, " x run the program defined in the PEXEC environment variable", LF, " - turns th" + db "e prompt off", LF, LF, "Example:", LF, " PROMPT $p$g ==> C:\DIR>", NUL +_help_rem db "REM", TAB, "Used in batch files, this command causes the remainder of the", LF, TAB, "line to be ignored.", LF, LF, "Syntax:", LF, TAB, "REM /H", LF, TAB, "REM [comment]", LF, LF, TAB, "/H", TAB + db TAB, "gives this screen", LF, TAB, "comment", TAB, TAB, "comment text", LF, LF, "Examples:", LF, TAB, "REM Ignore the rest of this line", LF, TAB, "REM XDEL \*.* /sdrn THIS IS SAFE SINCE IT " + db "WONT GET EXECUTED", NUL +_help_rename db "RENAME", TAB, "Renames files, or moves files between subdirectories on the same", LF, TAB, "disk. Can be abbreviated to REN.", LF, LF, "Syntax:", LF, TAB, "RENAME /H", LF, TAB, "RENAME oldwild" + db "spec newwildspec", LF, LF, TAB, "/H", TAB, TAB, "gives this screen", LF, TAB, "oldwildspec", TAB, "full path and filename of source file(s)", LF, TAB, "newwildspec", TAB, "full path and fil" + db "ename of destination file(s)", LF, LF, "Examples:", LF, TAB, "RENAME *.TXT *.DOC", LF, TAB, "REN AUTOEXEC.BAT *.SAV", LF, TAB, "REN \MYFILE.BAT \ARCHIVE\MYFILE.BAT", NUL +_help_rmdir db "RMDIR", TAB, "Removes specified subdirectory. Can be abbreviated to RD.", LF, LF, "Syntax:", LF, TAB, "RMDIR /H", LF, TAB, "RMDIR [d:]dirpath", LF, LF, TAB, "/H", TAB, TAB, "gives this scre" + db "en", LF, TAB, "d:", TAB, TAB, "drive upon which dirpath resides", LF, TAB, "dirpath", TAB, TAB, "subdirectory to remove", LF, LF, "Examples:", LF, TAB, "RMDIR \users\ian", LF, TAB, "RD \" + db "work\test", NUL +_help_set db "SET", TAB, "Inserts strings into the command processors environment.", LF, LF, "Syntax:", LF, TAB, "SET /H", LF, TAB, "SET [name=[string]]", LF, LF, TAB, "/H", TAB, "gives this screen", LF, TAB + db "name=", TAB, "environment variable name to be assigned", LF, TAB, "string", TAB, "string to assign to name", LF, TAB, "none", TAB, "no parameters displays all environment strings", LF, LF, "E" + db "xamples:", LF, TAB, "SET archive=c:\archive\", LF, TAB, "SET flags=-b-t$r", LF, TAB, "SET backup=", NUL +_help_shift db "SHIFT", TAB, "Used in batch files, this command allows you to change the", LF, TAB, "position of command line parameters to access more than 10", LF, TAB, "(%%0 through %%9) replacement variables." + db LF, LF, "Syntax:", LF, TAB, "SHIFT [/H]", LF, LF, TAB, "/H", TAB, "gives this screen", LF, LF, "Example:", LF, TAB, ":loop", LF, TAB, "if ""%%1"" == """" goto done", LF, TAB, "copy %%1 " + db "c:\archive", LF, TAB, "shift", LF, TAB, "goto loop", LF, TAB, ":done", NUL +_help_time db "TIME", TAB, "Displays and changes the time of day.", LF, LF, "Syntax:", LF, TAB, "TIME /H", LF, TAB, "TIME [hh[:mm[:ss]][a|p] [/C]", LF, LF, TAB, "/H", TAB, "gives this screen", LF, TAB, "h" + db "h", TAB, "hours 0 to 23 (24 hour clock) or 1 to 12 if a or p specified", LF, TAB, "mm", TAB, "minutes 0 to 59", LF, TAB, "ss", TAB, "seconds 0 to 59", LF, TAB, "a|p", TAB, "am|pm", LF, TAB + db "/C", TAB, "displays time continuously", LF, TAB, "none", TAB, "no parameters displays the current time, then prompts for a", LF, TAB, TAB, "new time. Press Return to leave the time unchanged", LF + db LF, "Examples:", LF, TAB, "TIME 5:23:8", LF, TAB, "TIME 7:32", LF, TAB, "TIME", NUL +_help_type db "TYPE", TAB, "Displays the contents of a text file on screen.", LF, LF, "Syntax:", LF, TAB, "TYPE /H", LF, TAB, "TYPE wildspec [/P]", LF, LF, TAB, "/H", TAB, " gives this screen", LF, TAB, "w" + db "ildspec file to be displayed (wildcards allowed)", LF, TAB, "/P", TAB, " pause when screen full", LF, LF, "Examples:", LF, TAB, "TYPE *.TXT /P", LF, TAB, "TYPE C:\AUTOEXEC.BAT", NUL +_help_ver db "VER", TAB, "Displays the version number of the operating system in use.", LF, LF, "Syntax:", LF, TAB, "VER [/H]", LF, LF, TAB, "/H", TAB, "gives this screen", LF, LF, "Example:", LF, TAB, "V" + db "ER", NUL +_help_verify db "VERIFY", TAB, "Switches the Verify option on or off, which causes the operating", LF, TAB, "system to check that data is correctly written to disk after each", LF, TAB, "disk write operation.", LF + db LF, "Syntax:", LF, TAB, "VERIFY /H", LF, TAB, "VERIFY [ON|OFF]", LF, LF, TAB, "/H", TAB, "gives this screen", LF, TAB, "ON", TAB, "turns VERIFY on", LF, TAB, "OFF", TAB, "turns VERIFY of" + db "f (default)", LF, TAB, "none", TAB, "no parameters displays the current VERIFY state, on or off", LF, LF, "Examples:", LF, TAB, "VERIFY ON", LF, TAB, "VERIFY", NUL +_help_vol db "VOL", TAB, "Displays the disk volume label.", LF, LF, "Syntax:", LF, TAB, "VOL /H", LF, TAB, "VOL [d:]", LF, LF, TAB, "/H", TAB, "gives this screen", LF, TAB, "d:", TAB, "drive to display" + db " volume label", LF, TAB, "none", TAB, "no parameters displays the volume label of the default drive", LF, LF, "Example:", LF, TAB, "VOL", NUL +_help_chcp db "CHCP", TAB, "Change the active Code Page.", LF, LF, "Syntax:", LF, TAB, "CHCP /H", LF, TAB, "CHCP [cp]", LF, LF, TAB, "/H", TAB, "gives this screen", LF, TAB, "cp", TAB, "new active Code " + db "Page", LF, TAB, "none", TAB, "no parameters displays the current active Code Page", LF, LF, "Example:", LF, TAB, "CHCP 850", NUL +_help_ctty db "CTTY", TAB, "Redirect console input and output to a port.", LF, LF, "Syntax:", LF, TAB, "CTTY /H", LF, TAB, "CTTY port", LF, LF, TAB, "/H", TAB, "gives this screen", LF, TAB, "port", TAB, "p" + db "ort to redirect to", LF, LF, "Example:", LF, TAB, "CTTY COM1:", NUL +_help_hiload db "HILOAD", TAB, "Load and execute a program in upper memory.", LF, LF, "Syntax:", LF, TAB, "HILOAD /H", LF, TAB, "HILOAD fname", LF, LF, TAB, "/H", TAB, "gives this screen", LF, TAB, "fname", TAB + db "filename of program to load", LF, LF, TAB, "(LOADHIGH and LH can be used instead of HILOAD)", LF, LF, "HILOAD only has an effect if MemoryMAX software is present and there is", LF, "upper memory" + db " available. If this is not so then the program will load and", LF, "execute in conventional memory.", LF, LF, "Example:", LF, TAB, "HILOAD CURSOR", NUL + +_HELP ends + + +_TEXT segment word public 'CODE' + assume cs:_TEXT, ds:DGROUP + +; unsigned dls_language(void) +_dls_language proc near + + xor ax, ax + ret + +_dls_language endp + +; void dls_init(void) +_dls_init proc near + + inc __dls_init__ + ret + +_dls_init endp + +; void * dls_get_table(unsigned param) +_dls_get_table proc near + + mov al, __dls_init__ + cbw + test al, al + je dls_gt_end + mov ax, offset DGROUP:_single_table + mov word ptr _dls_table, ax + +dls_gt_end: + ret + +_dls_get_table endp + +_TEXT ends + + + end + \ No newline at end of file diff --git a/COMMAND/TXHELP.DEF b/COMMAND/TXHELP.DEF new file mode 100644 index 0000000..d8935cf --- /dev/null +++ b/COMMAND/TXHELP.DEF @@ -0,0 +1,57 @@ +ifndef _DLS_INCLS_ +; DLS parameters passed to _dls_get_table function. +DLS_NO equ 0 +DLS_YES equ 1 + +endif ; !_DLS_INCLS_ + +; DLS system functions. + extrn _dls_init : near + extrn _dls_get_table : near + extrn _dls_language : near + +; DLS system variables. + extrn _dls_table : word + + +; Component messages equated to entries in _dls_table. +help_aaa equ 0 +help_and equ 2 +help_break equ 4 +help_call equ 6 +help_chcp equ 8 +help_chdir equ 10 +help_cls equ 12 +help_copy equ 14 +help_ctty equ 16 +help_date equ 18 +help_del equ 20 +help_delq equ 22 +help_dir equ 24 +help_echo equ 26 +help_eraq equ 28 +help_erase equ 30 +help_exit equ 32 +help_for equ 34 +help_gosubreturn equ 36 +help_goto equ 38 +help_hiload equ 40 +help_idle equ 42 +help_if equ 44 +help_mkdir equ 46 +help_or equ 48 +help_path equ 50 +help_pause equ 52 +help_prompt equ 54 +help_rem equ 56 +help_rename equ 58 +help_rmdir equ 60 +help_set equ 62 +help_shift equ 64 +help_switch equ 66 +help_time equ 68 +help_truename equ 70 +help_type equ 72 +help_ver equ 74 +help_verify equ 76 +help_vol equ 78 diff --git a/COMMAND/TXHELP.H b/COMMAND/TXHELP.H new file mode 100644 index 0000000..d4bdbfd --- /dev/null +++ b/COMMAND/TXHELP.H @@ -0,0 +1,111 @@ +#ifndef _DLS_INCLS_ + +#ifdef __cplusplus +extern "C" { +#endif + /* DLS system functions. */ + extern void near cdecl dls_init(void); + extern void near * near cdecl dls_get_table(unsigned); + extern unsigned near cdecl dls_language(void); +#ifdef __cplusplus +}; +#endif + +/* DLS parameters passed to dls_get_table() function. */ +#define DLS_NO 0 +#define DLS_YES 1 + +#define _DLS_INCLS_ +#endif /* !_DLS_INCLS_ */ + +/* DLS system variables. */ +extern void near * near * near cdecl dls_table; + + +/* DLS static initialisation macros. */ +#define DLS_number(n) (*(unsigned int near *)dls_table[n]) +#define DLS_char(n) (*(char near *)dls_table[n]) +#define DLS_string(n) ((char near *)dls_table[n]) +#define DLS_array(n) ((char near * near *)dls_table[n]) + +/* Component messages equated to table entries. */ +#define DLS_help_aaa 0 +#define help_aaa ((char near *)dls_table[0]) +#define DLS_help_and 1 +#define help_and ((char near *)dls_table[1]) +#define DLS_help_break 2 +#define help_break ((char near *)dls_table[2]) +#define DLS_help_call 3 +#define help_call ((char near *)dls_table[3]) +#define DLS_help_chcp 4 +#define help_chcp ((char near *)dls_table[4]) +#define DLS_help_chdir 5 +#define help_chdir ((char near *)dls_table[5]) +#define DLS_help_cls 6 +#define help_cls ((char near *)dls_table[6]) +#define DLS_help_copy 7 +#define help_copy ((char near *)dls_table[7]) +#define DLS_help_ctty 8 +#define help_ctty ((char near *)dls_table[8]) +#define DLS_help_date 9 +#define help_date ((char near *)dls_table[9]) +#define DLS_help_del 10 +#define help_del ((char near *)dls_table[10]) +#define DLS_help_delq 11 +#define help_delq ((char near *)dls_table[11]) +#define DLS_help_dir 12 +#define help_dir ((char near *)dls_table[12]) +#define DLS_help_echo 13 +#define help_echo ((char near *)dls_table[13]) +#define DLS_help_eraq 14 +#define help_eraq ((char near *)dls_table[14]) +#define DLS_help_erase 15 +#define help_erase ((char near *)dls_table[15]) +#define DLS_help_exit 16 +#define help_exit ((char near *)dls_table[16]) +#define DLS_help_for 17 +#define help_for ((char near *)dls_table[17]) +#define DLS_help_gosubreturn 18 +#define help_gosubreturn ((char near *)dls_table[18]) +#define DLS_help_goto 19 +#define help_goto ((char near *)dls_table[19]) +#define DLS_help_hiload 20 +#define help_hiload ((char near *)dls_table[20]) +#define DLS_help_idle 21 +#define help_idle ((char near *)dls_table[21]) +#define DLS_help_if 22 +#define help_if ((char near *)dls_table[22]) +#define DLS_help_mkdir 23 +#define help_mkdir ((char near *)dls_table[23]) +#define DLS_help_or 24 +#define help_or ((char near *)dls_table[24]) +#define DLS_help_path 25 +#define help_path ((char near *)dls_table[25]) +#define DLS_help_pause 26 +#define help_pause ((char near *)dls_table[26]) +#define DLS_help_prompt 27 +#define help_prompt ((char near *)dls_table[27]) +#define DLS_help_rem 28 +#define help_rem ((char near *)dls_table[28]) +#define DLS_help_rename 29 +#define help_rename ((char near *)dls_table[29]) +#define DLS_help_rmdir 30 +#define help_rmdir ((char near *)dls_table[30]) +#define DLS_help_set 31 +#define help_set ((char near *)dls_table[31]) +#define DLS_help_shift 32 +#define help_shift ((char near *)dls_table[32]) +#define DLS_help_switch 33 +#define help_switch ((char near *)dls_table[33]) +#define DLS_help_time 34 +#define help_time ((char near *)dls_table[34]) +#define DLS_help_truename 35 +#define help_truename ((char near *)dls_table[35]) +#define DLS_help_type 36 +#define help_type ((char near *)dls_table[36]) +#define DLS_help_ver 37 +#define help_ver ((char near *)dls_table[37]) +#define DLS_help_verify 38 +#define help_verify ((char near *)dls_table[38]) +#define DLS_help_vol 39 +#define help_vol ((char near *)dls_table[39]) diff --git a/COMMAND/TXLOGIN.H b/COMMAND/TXLOGIN.H new file mode 100644 index 0000000..950d331 --- /dev/null +++ b/COMMAND/TXLOGIN.H @@ -0,0 +1,127 @@ +/* +; File : $Workfile$ +; +; Description : login security extensions +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +*/ + +#if defined(CDOSTMP) || defined(CDOS) +#define STD_MSG std_msg +#define MSG_BADHOMEDRV msg_badhomedrv +#define MSG_BADHOMEDIR msg_badhomedir +#define MSG_LOGGEDIN msg_loggedin +#define NAME_PROMPT name_prompt +#define PWORD_PROMPT pword_prompt +#define MSG_BADUSERPWORD msg_baduserpword +#define MSG_LOGINFAILED msg_loginfailed +#define MSG_SEP msg_sep +#define MSG_LOGGEDOUT msg_loggedout +#define MSG_BADFILE msg_badfile +#define MSG_NOFILE msg_nofile +#define MSG_BADREADFILE msg_badreadfile +#define MSG_BADWRITEFILE msg_badwritefile +#define MSG_BADOPENFILE msg_badopenfile +#define MSG_ENTERTOCONT msg_entertocont +#define MSG_LOGLOCKED msg_loglocked +#define MSG_LOCKED msg_locked +#define MSG_UNLOCKFAILED msg_unlockfailed +#define MSG_UNLOCKED msg_unlocked +#define SUN_D sun_d +#define MON_D mon_d +#define TUE_D tue_d +#define WED_D wed_d +#define THU_D thu_d +#define FRI_D fri_d +#define SAT_D sat_d +#define MSG_PROCRUNNING msg_procrunning +#define MSG_VCNUM msg_vcnum +#define MSG_PROCNAME msg_procname +#define MSG_STOPPROC msg_stopproc +#define MSG_FAILABORT msg_failabort +#define UNKNOWN msg_unknown +#define MSG_GETSUPERPWORD1 msg_getsuperpword1 +#define MSG_GETSUPERPWORD2 msg_getsuperpword2 +#define MSG_CANNOTLOCK msg_cannotlock +#define MSG_CANNOTLOGOUT msg_cannotlogout +#define MSG_TYPEEXIT msg_typeexit +#define MSG_HEAPSIZE msg_heapsize +#define MSG_WILLNOTLOCK msg_willnotlock + +EXTERN BYTE yesch; +EXTERN BYTE noch; +EXTERN BYTE std_msg[]; +EXTERN BYTE err_msg[]; +EXTERN BYTE log_msg[]; +EXTERN BYTE msg_baduserpword[]; +EXTERN BYTE msg_badhomedir[]; +EXTERN BYTE msg_badhomedrv[]; +EXTERN BYTE msg_loggedin[]; +EXTERN BYTE name_prompt[]; +EXTERN BYTE pword_prompt[]; +EXTERN BYTE msg_loginfailed[]; +EXTERN BYTE msg_sep[]; +EXTERN BYTE msg_loggedout[]; +EXTERN BYTE msg_erroccurred[]; +EXTERN BYTE msg_badfile[]; +EXTERN BYTE msg_nofile[]; +EXTERN BYTE msg_badreadfile[]; +EXTERN BYTE msg_badwritefile[]; +EXTERN BYTE msg_badopenfile[]; +EXTERN BYTE msg_entertocont[]; +EXTERN BYTE msg_loglocked[]; +EXTERN BYTE msg_locked[]; +EXTERN BYTE msg_unlockfailed[]; +EXTERN BYTE msg_unlocked[]; +EXTERN BYTE sun_d[]; +EXTERN BYTE mon_d[]; +EXTERN BYTE tue_d[]; +EXTERN BYTE wed_d[]; +EXTERN BYTE thu_d[]; +EXTERN BYTE fri_d[]; +EXTERN BYTE sat_d[]; +EXTERN BYTE msg_procrunning[]; +EXTERN BYTE msg_vcnum[]; +EXTERN BYTE msg_procname[]; +EXTERN BYTE msg_stopproc[]; +EXTERN BYTE msg_failabort[]; +EXTERN BYTE msg_unknown[]; +EXTERN BYTE msg_getsuperpword1[]; +EXTERN BYTE msg_getsuperpword2[]; +EXTERN BYTE msg_cannotlock[]; +EXTERN BYTE msg_cannotlogout[]; +EXTERN BYTE msg_typeexit[]; +EXTERN BYTE msg_heapsize[]; +EXTERN BYTE msg_willnotlock[]; + +#endif + + diff --git a/IBMBIO/BDOSLDR.A86 b/IBMBIO/BDOSLDR.A86 new file mode 100644 index 0000000..e37bd71 --- /dev/null +++ b/IBMBIO/BDOSLDR.A86 @@ -0,0 +1,573 @@ +; File : $BDOSLDR.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG + + include i:reqhdr.equ + include i:driver.equ + include config.equ + +; MISC constants +CR equ 0dh ;the usual +LF equ 0ah + + +DATTS equ byte ptr 11 + DA_VOLUME equ 08h + DA_DIR equ 10h +DBLOCK1 equ word ptr 26 + + +eject +CGROUP group INITCODE, INITDATA + +INITCODE cseg 'INITCODE' + +eject +if DOS5 +VER_MUSTBE equ 1072h +else +VER_MUSTBE equ 1071h +endif + + Public dos_version_check + + Public read_dos ; read BDOS from disk + +;-------- +read_dos: ; read in the BDOS +;-------- + call login_drive ; build BPB for the boot drive + mov si,offset dos_name ; get name of file to open + call open_file ; open the BDOS file + call read_file ; read in the system file + ret + +login_drive: +;----------- + les di,boot_device ; get device driver address + mov dl,boot_drv ; get the boot drive sub unit + mov ax,es + or ax,di ; make sure boot device is initialised + jnz login_drive10 + jmp dev_fail +login_drive10: + mov ax,es:6[di] ; get strategy offset + mov strat_off,ax + mov strat_seg,es ; get strategy segment + mov ax,es:8[di] ; get interrupt offset + mov intrpt_off,ax + mov intrpt_seg,es ; get interrupt segment + + mov bx,offset req_hdr + mov ds:RH_UNIT,dl ; save logical unit to use + mov ds:RH_CMD,CMD_BUILD_BPB + call device_request ; tell it to build a BPB + jc dev_fail ; return if can't determine BPB + push ds ! push si + push ds ! pop es + mov di,offset local_bpb ; ES:DI -> local BPB copy + mov cx,BPB_LENGTH + lds si,ds:RH2_BPB ; copy BPB to local memory + rep movsb + pop si ! pop ds + +; Now we have to figure out whether the media uses 12 or 16 bit FATs. +; To that end, we need to compute the # of clusters on the drive: + + mov fat16,0 ; assume 12 bit FAT + + mov al,BT_nfats ; compute FAT size + mov ah,0 ; AX = # of FAT copies (usually 2) + mul BT_fat_size ; AX/DX = size of FAT in sectors + + add ax,BT_reserved_sectors ; add in bootstrap sectors + adc dx,0 + mov cx,ax ; CX/BP = sector address of root dir + mov bp,dx + + mov ax,32 ; compute root directory size + mul BT_dirsize ; AX/DX = bytes in directory + mov bx,BT_bytes_per_sector + dec bx ; BX = sector size - 1 for rounding + add ax,bx ; round up to next sector size + adc dx,0 + inc bx ; BX = sector size in bytes + div bx ; AX = # of root directory sectors + add cx,ax ; CX/BP = sectors before data area + adc bp,0 + + mov ax,BT_total_sectors ; AX/DX = total disk size in sectors + sub dx,dx + test ax,ax ; is it actually larger than 65535? + jnz dev_small ; no, AX/DX is correct + mov ax,BT_total_long ; else get real size from extension + mov dx,BT_total_long+2 +dev_small: ; AX/DX = disk size in sectors + sub ax,cx ; AX/DX = data sectors + sbb dx,bp + ; now convert this to clusters + mov bl,BT_sctr_per_cluster + mov bh,0 ; BX = sectors per clusters + div bx ; AX = # of data clusters + inc ax + inc ax ; cluster 0,1 are reserved + cmp ax,0FF6h ; is this too large for 12 bits? + jbe dev_12bit ; skip if 12 bits will do + mov fat16,-1 ; else we use 16 bits +dev_12bit: + ret + + +dos_version_check: +;----------------- + mov ax,4452h + int 21h ; try and get DRDOS version number + jc dev_fail ; it's not DRDOS ! + cmp ax,VER_MUSTBE ; version check the DRDOS BDOS + jne dev_fail ; reject all but the one we want + ret ; return now I'm happy + +dev_fail: ; any error has occurred loading the BDOS +;-------- +; Print '$' terminated message at offset DX to console without using the BDOS +; + mov dx,offset dos_msg + les di,resdev_chain ; get first device driver address +fail_scan: + test es:DH_ATTRIB[di],DA_CHARDEV + jz fail_next ; skip if not a character device + test es:DH_ATTRIB[di],DA_ISCOT + jnz fail_found ; skip if console device found +fail_next: + les di,es:[di] ; get next device + jmps fail_scan +fail_found: + mov ax,es:6[di] ; get strategy offset + mov strat_off,ax + mov strat_seg,es ; get strategy segment + mov ax,es:8[di] ; get interrupt offset + mov intrpt_off,ax + mov intrpt_seg,es ; get interrupt segment + + mov bx,offset req_hdr + mov ds:RH_CMD,CMD_OUTPUT ; write to console + mov ds:RH_LEN,RH4_LEN ; set request header length + mov ds:RH4_BUFOFF,dx ; set address of string + mov ds:RH4_BUFSEG,ds + mov ds:RH4_COUNT,-1 + mov si,dx ; now find the end of the string +fail_count_chars: + inc ds:RH4_COUNT ; print another char + lodsb ; examine the next one + cmp al,'$' ; terminating char ? + jnz fail_count_chars + call device_request ; call the console driver + + sti + jmps $ ; wait for reboot + + +device_request: ; general device driver interface +;-------------- +; entry: BX -> request header +; exit: CY = 1 if error + + push ds ! push es + push ds ! pop es + mov ds,strat_seg + callf cs:strat_ptr + callf cs:intrpt_ptr + pop es ! pop ds + test ds:RH_STATUS,RHS_ERROR + jnz devreq_err + clc + ret +devreq_err: + jmp dev_fail ; print error message + + + ret + +open_file: ; open BDOS system file +;--------- +; entry: SI -> 11 byte file name + + mov al,BT_nfats + cbw + mul BT_fat_size ; DX:AX = # FAT sectors + + mov cx,ax ; CX = rel_sctr dir start + mov dx,BT_dirsize ; dx = # entries to scan + +open_f1: ; CX = current dir sector + ; DX = current dir count + ; SI -> file name + push cx ! push dx ! push si + push ds ! pop es ; ES:BX -> sector buffer + mov bx,offset sector_buffer + mov dx,1 ; read one directory sector + call rd_sector_rel ; via disk driver + pop si ! pop dx ! pop cx + inc cx ; increment sector for next time + + sub bx,bx ; start at beginning of sector +open_f2: + lea di,sector_buffer[bx] ; ES:DI -> directory entry + push si ! push di ! push cx ; save name ptr and count + push ds ! pop es + mov cx,11 + repe cmpsb ; check if name matches + pop cx ! pop di ! pop si + jne open_f3 ; skip if name doesn't match + test DATTS[di],DA_DIR+DA_VOLUME + jz open_foundit ; skip if matches +open_f3: + dec dx ; count down root directory entries + jz open_fail ; skip if root directory done + add bx,32 ; next entry in directory sector + cmp bx,BT_bytes_per_sector ; sector complete? + jb open_f2 ; loop back while more + jmps open_f1 ; read next directory sector + +open_fail: ; file not found + jmp dev_fail + +open_foundit: ; found the open file handle + mov ax,DBLOCK1[di] ; get first disk block + mov start_cluster,ax ; save starting cluster + xor ax,ax + ret ; return success + + +read_file: ; read BDOS files into memory at MEM_CURRENT:0000 +;--------- + mov ax,current_dos ; Get the Segment address to + mov dta_seg,ax ; load the BDOS at + sub ax,ax + mov dta_off,ax +rd_file1: + mov cluster_count,1 ; we can read at least one cluster + mov cx,start_cluster +rd_file2: ; check if next cluster contiguous + push cx ; save current cluster number + call next_cluster ; get link to next cluster + pop dx ; get previous cluster # + inc dx ; is current cluster contiguous? + cmp cx,dx ; contiguos if CX == DX + jne rd_file3 ; no, need a separate read + inc cluster_count ; else read one more cluster + jmps rd_file2 ; try again with next cluster +rd_file3: ; CX = next chain, multi cluster read + push cx ; save start of next chain + les bx,dta_ptr ; ES:BX -> transfer address + mov cx,start_cluster ; previous contiguous chain starts here + mov dx,cluster_count ; length of chain in clusters + call rd_cluster ; read DX clusters + mov al,BT_sctr_per_cluster + mov ah,0 ; AX = sectors per cluster + mul cluster_count ; AX = sectors in chain to read + mul BT_bytes_per_sector ; AX = bytes in chain to read + add dta_off,ax + pop cx ; CX = next (noncontiguous) cluster + mov start_cluster,cx ; start of new chain + inc cx ; was it end of file cluster number? + jnz rd_file1 ; go back for more if not + ; else all clusters done + ret + + +get_FAT_byte: +;------------ +; entry: BX = offset into FAT + + mov ax,bx ; BX = offset into FAT + sub dx,dx ; AX/DX = 32 bit offset + div BT_bytes_per_sector ; AX = sector, DX = offset in sector + push dx ; save offset in sector + call locate_FAT ; read FAT sector AX + pop bx ; BX = offset in FAT sector + mov al,sector_buffer[bx] ; get byte from FAT buffer + ret + + +locate_FAT: +;---------- +; entry: AX = FAT sector to locate + + cmp ax,current_fatsec ; AX = sector offset into FAT + je locate_FAT_match ; O.K. if same as last time + + mov current_fatsec,ax ; set new sector for next time + push cx ! push si ; preserve FAT index + mov cx,ax ; CX = sector number + mov bx,offset sector_buffer + push ds ! pop es ; ES:BX -> sector buffer + mov dx,1 ; DX = single sector + call rd_sector_rel ; read FAT sector + pop si ! pop cx ; restore FAT index + +locate_FAT_match: ; return with right sector in buffer + ret + + +eject +; reads sectors relative to start of DOS area on disk (start=0) +; same parameters as rd_sector +rd_sector_rel: +;------------- +; entry: CX = sector address relative to first FAT sector +; DX = sector count + + sub bp,bp ;overflow word = 0 + add cx,BT_reserved_sectors + adc bp,0 +; jmps rd_sector + + +; reads absolute sectors from hard disk using rom bios +rd_sector: +;--------- +; entry: DX = number of sectors +; ES:BX -> data transfer buffer +; DS -> program global data segment +; CX/BP = absolute sector # (32 bit) (low/high) + + push cx ! push dx ; save parameters + mov req3_bufoff,bx ; save transfer offset + mov req3_bufseg,es ; save transfer segment + mov req3_count,dx ; set sector count + mov bx,offset req_hdr ; BX -> request header + mov ds:RH_CMD,CMD_INPUT ; read from disk device + mov req3_sector,cx ; set requested sector address +if DOS5 + mov req_hdr,RH4_LEN + mov req3_sector32,cx ; with 32 sector number + mov req3_sector32+2,bp + test bp,bp ; large sector number? + jz rd_sec1 ; no, normal request header + mov req3_sector,0FFFFh ; mark as a large request +rd_sec1: +else + mov req3_sector+2,bp ; (support large DOS drives) + mov req_hdr,24 ; indicate large request +endif + call device_request ; tell it to read sectors + pop cx ! pop dx + ret ; if CY, AH=error code + + +rd_cluster: +;---------- +; entry: CX = DOS cluster number. +; DX = cluster count +; ES:BX -> transfer buffer + + push bx ! push es + + mov al,BT_sctr_per_cluster + mov ah,0 ; AX = sectors per cluster + mul dx ; AX = sectors in all clusters + push ax ; save the sector count + + sub cx,2 ; cluster 2 is data area start + mov al,BT_sctr_per_cluster + cbw + mul cx ; AX,DX = relative sector # + mov cx,ax + mov bp,dx ; CX,BP = data area sector # + + mov al,BT_nfats ; compute FAT size + mov ah,0 ; AX = # of FAT copies (usually 2) + mul BT_fat_size ; AX/DX = size of FAT in sectors + add cx,ax + adc bp,dx ; CX,BP = end of FAT sectors + + mov ax,32 + mul BT_dirsize ; AX,DX = bytes in root directory + mov bx,BT_bytes_per_sector + dec bx + add ax,bx ; round up directory size + adc dx,0 + inc bx + div bx ; AX = root directory sectors + add cx,ax + adc bp,0 ; add root directory size + + add cx,BT_reserved_sectors ; add in boot sector(s) + adc bp,0 + + pop dx ! pop es ! pop bx ; sector count, disk address + + jmp rd_sector ; DX secs from CX/BP to ES:BX + + +; Finds the NEXT cluster after the one passed in CX in an allocation +; chain by using the FAT. Returns the carry set if the end of chain +; mark is found, otherwise returns the NEW cluster # in CX. +next_cluster: +;------------ + push dx ! push bx ; save some registers + cmp fat16,0 ; check if this is 12 bit media + je next_cluster12 ; skip if old fashioned 12 bit + mov ax,2 + mul cx ; AX/DX = byte offset in FAT (max. 128K) + div BT_bytes_per_sector ; AX = FAT sector #, DX = byte offset + push dx ; save byte offset within sector + call locate_FAT ; get FAT sector AX + pop bx ; BX = offset within sector + mov cx,word ptr sector_buffer[bx] + ; get 16 bit from FAT + + cmp cx,0FFF7h ; check if too large for # + jae next_cluster_eof ; set carry, EOF + clc + jmps next_cluster_ret ; good link + +next_cluster12: ; DOS 2.x disk + push cx ; save cluster number + mov bx,cx + add bx,bx ; BX = cluster# * 2 + add bx,cx ; BX = cluster# * 3 + shr bx,1 ; BX = cluster# * 1.5 + push bx ; save offset in the FAT + inc bx ; BX = offset of high byte + call get_FAT_byte ; get the high byte in AL + pop bx ; BX = offset of low byte + push ax ; save high byte on stack + call get_FAT_byte ; get the low byte in AL + pop bx ; pop off high byte into BL + mov ah,bl ; set high byte, AX = word + pop cx ; restore cluster number + shr cx,1 ; test if even or odd + jnc even_fat ; if even entry, done + mov cl,4 ; odd entry, shift down one nibble + shr ax,cl ; else need to justify +even_fat: ; even entry, strip off top bits + and ax,0fffh ; bx[0..11] are cluster + mov cx,ax ; CX = cluster number + cmp cx,0ff7h ; compare with largest legal 12 bit # + jae next_cluster_eof ; check for end mark + clc + jmps next_cluster_ret ; return value in CX, CY = 0 +next_cluster_eof: + mov cx,-1 ; indicate end of chain + stc ; end of chain +next_cluster_ret: + pop bx ! pop dx + ret + + +eject +; +; INITIALIZED DATA SEGMENT +; ======================== +INITDATA dseg 'INITDATA' + + extrn resdev_chain:dword ; resident device driver root + extrn current_dos:word ; current BDOS segment + extrn boot_device:dword ; device driver we boot from + extrn boot_drv:byte ; boot drive + extrn dos_name:byte ; name of BDOS file + +strat_ptr rd 0 +strat_off rw 1 +strat_seg rw 1 + +intrpt_ptr rd 0 +intrpt_off rw 1 +intrpt_seg rw 1 + +dta_ptr rd 0 +dta_off rw 1 +dta_seg rw 1 + +start_cluster rw 1 +cluster_count rw 1 + +current_fatsec dw -1 ; no FAT sector read yet +fat16 dw 0 ; defaults to 12 bit FAT + +; single error message if BDOS can't be loaded: + + +include initmsgs.def ; Include TFT Header File + + +;dos_msg db CR,LF,'Can''t load DOS file.$' + + +; static request header for DOS device driver I/O + +req_hdr db 22 +req_unit rb 1 +req_cmd rb 1 +req_status rw 1 + rd 2 +req_media rb 1 + rb 16 + +req1_return equ byte ptr req_media+1 +req1_volid equ word ptr req_media+2 + +req2_bufoff equ word ptr req_media+1 +req2_bufseg equ word ptr req_media+3 +req2_bpb equ word ptr req_media+5 + +req3_buffer equ dword ptr req_media+1 +req3_bufoff equ word ptr req_media+1 +req3_bufseg equ word ptr req_media+3 +req3_count equ word ptr req_media+5 +req3_sector equ word ptr req_media+7 +req3_volid equ word ptr req_media+9 +req3_sector32 equ word ptr req_media+13 + +; local copy of the BPB for the boot device + +local_bpb rb 0 +BT_bytes_per_sector rw 1 +BT_sctr_per_cluster rb 1 +BT_reserved_sectors rw 1 +BT_nfats rb 1 +BT_dirsize rw 1 +BT_total_sectors rw 1 +BT_fatid rb 1 +BT_fat_size rw 1 +BT_sectors_per_track rw 1 +BT_nheads rw 1 +BT_hidden_sectors rw 2 +BT_total_long rw 2 +BPB_LENGTH equ (offset $-offset local_bpb) + + extrn sector_buffer:byte + + end diff --git a/IBMBIO/BDOSSTUB.A86 b/IBMBIO/BDOSSTUB.A86 new file mode 100644 index 0000000..0d78999 --- /dev/null +++ b/IBMBIO/BDOSSTUB.A86 @@ -0,0 +1,48 @@ +; File : $BDOSSTUB.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG + +CGROUP group INITCODE + +INITCODE cseg 'INITCODE' + + public read_bdos +read_bdos: + ret + + + public bdos_version_check +bdos_version_check: + ret + + end diff --git a/IBMBIO/BIN/BDOSLDR.OBJ b/IBMBIO/BIN/BDOSLDR.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..aef6c9c1eb11f53e49456efa873d3ef0c8aeeec8 GIT binary patch literal 1871 zcmZ{kO>7fa5Xa~3n)Nyk&Icic4=rgM0&SFtxB((UP}b{>V-nl(uCu|h6bqpu_0%@8 zOFyI%6hU#8Le)cssvI1p>ZQFPwJIMiq}nBkD)m5G4v0%>4|VENRiwf}mDs-7O^m42 z%g-}!-+MFvnR%Y@fIAS3sRKdf#JQ~iponUuwR3-Cdt1k`#&&;eIDiv9!*VCY4I7&R}q^zQ?tc3^+_4d-V$VNOdAgT$xL#Am_ zw=b+FVoK7v4Wp~X9gR7s?F~|FD4JN`p!UfF18aL@gEGd#OKdr7yB#$=W^W6zlP=5h zN<)ewM`<-;G#^!#Xz;X?-`ZWaQl}VYsTFnq6H%;V5)>%l}^wFKlJaK4uk2^Hk(x%F*j+=<_mR%n7a{e2tQ&Uq7R`VQix-S zR}kZflN6ulPXqG~um+7Il~&lr$vZG}5L%Yb%w^p(A<*l?(DL2(J5xdjd<~_Qo}TVU zRc~^bsAU;fl;97~jd9&$)mdU(1Hdvgmt+@AWO)2#AiJU2>@F7nw;Z$<{P1)am_E#C z3t~IMmShW&wH;w!Hn&lqJ-iA!g;pyFAHeot1BJ39Qpd};v5vtZ;9@iSa!BpQM zM>5_?qp^#&a_nC5*76}sm$%JU!pn2U48Uv!w9L)&u)z6%fbOe=c;OEi33Pp*y!}D1_d($-mlHElZ{SeozV=q^8~n*fyO6lgErU zBerW>OaYCj1JsIc7b1Y@MI1p4BJ5EbL2DFo9Pt|BEv?~f{uD4pVsvrUkg1!khPb9L z(i#eGtRf4eNu%Wf>!TBWht@YIJWpRl6Xfcf@m0_QJ-aQouy%Ai5Qh*? zyA(z@j^35HBJ43ch?b-^Jj{E6`I)(DS&vgAMmX;QQccSSQ173je^r@(0Y5M% A9{>OV literal 0 HcmV?d00001 diff --git a/IBMBIO/BIN/BDOSSTUB.OBJ b/IBMBIO/BIN/BDOSSTUB.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..2dcf391876e327aaea93a96d0794be08ba52d9e7 GIT binary patch literal 188 zcmZqRX5e&k@ed9T33YNj+9Aonz!2mZ?5k^GreLUNlBi&4r0bhlq-$X=IL(ZKfz>r4 zB*>A)+26&LH8{l4*_*}1F~pI>)6X*mBnD@&IlBk>hX#NZ2Fze*&|qRA&0ovE_Zh{&EBO_;!tD{Ri$Sn*Ej6xtfKFl>J*wf!H-r2*|*_)Ap UQFZ|v10w^&;lr1^m>3vJ0O_hL0RR91 literal 0 HcmV?d00001 diff --git a/IBMBIO/BIN/BIOS.MAP b/IBMBIO/BIN/BIOS.MAP new file mode 100644 index 0000000..4ed6203 --- /dev/null +++ b/IBMBIO/BIN/BIOS.MAP @@ -0,0 +1,418 @@ +LINK : warning L4021: no stack segment + + Start Stop Length Name Class + 00000H 00616H 00617H CODE CODE + 00617H 00617H 00000H ENDCODE ENDCODE + 00620H 0171FH 01100H RCODE_ALIGN RCODE + 01720H 02692H 00F73H RCODE RCODE + 026A0H 027AFH 00110H RESUMECODE RESUMECODE + 027B0H 031DFH 00A30H RESBIOS RESBIOS + 031E0H 03905H 00726H ICODE ICODE + 03910H 0391FH 00010H IDATA IDATA + 03920H 064F5H 02BD6H INITCODE INITCODE + 06500H 06637H 00138H STACKS STACKS + 06640H 079A6H 01367H INITDATA INITDATA + 079B0H 07A1FH 00070H INITPSP INITDATA + 07A20H 07B9DH 0017EH INITENV INITDATA + 07BA0H 07BA0H 00000H DATAEND INITDATA + + Origin Group + 0000:0 CGROUP + + Address Publics by Name + + 0000:0000 A20ENABLE + 0000:4043 ALLOCHMA + 0000:417C ALLOC_HISEG + 0000:414F ALLOC_INSTSEG + 0000:41A4 ALLOC_SEG + 0000:77C4 BAD_BREAK + 0000:77EA BAD_BUFFERS + 0000:7746 BAD_COMMAND + 0000:7931 BAD_COUNTRY + 0000:787F BAD_DRIVPARM + 0000:7948 BAD_EXEC + 0000:782E BAD_FCBS + 0000:776B BAD_FILENAME + 0000:7806 BAD_FILES + 0000:7848 BAD_FOPEN + 0000:78E8 BAD_HISTORY + 0000:779A BAD_LASTDRIVE + 0000:7781 BAD_SHELL + 0000:396E BIOSINIT + 0000:7BA0 BIOSINIT_END + 0000:66B8 BIOS_SEG + 0000:667A BIOS_TARGET_SEG + 0000:6C08 BLKDEV_TABLE + 0000:474E BLOCK_DEVICE + 0000:6BE7 BOOT_DEVICE + 0000:6BEB BOOT_DRV + 0000:7B80 BOOT_OPTIONS + 0000:0434 BPB160 + 0000:0491 BPB360 + 0000:04CF BPB720 + 0000:31E0 BPBS + 0000:0537 BPBTBL + 0000:6BE2 BUFFERSIN + 0000:4BCA BUILD_CMD_TAIL + 0000:7203 CFG_FILE + 0000:724F CFG_FILE_END + 0000:001A CLEANUP + 0000:6BF0 CLKDEV_OFF + 0000:6BF2 CLKDEV_SEG + 0000:17DC CLOCKTABLE + 0000:669C CODE_PAGE + 0000:668F COMSPEC_DRV + 0000:6BF4 CONDEV_OFF + 0000:6BF6 CONDEV_SEG + 0000:443B CONFIG + 0000:4978 CONFIG_FINISH + 0000:4400 CONFIG_INIT + 0000:4C50 CONFIG_PROCESS + 0000:1900 CONSOLETABLE + 0000:022A CONTROLBREAK + 0000:669A COUNTRY_CODE + 0000:4401 COUNTRY_INIT + 0000:5A4A CRLF + 0000:7175 CTRY_INFO + 0000:6676 CURRENT_DOS + 0000:1722 DATASEGMENT + 0000:0232 DAYCOUNT + 0000:7171 DBCS_TBL + 0000:0184 DEBLOCKSEG + 0000:71CA DEBLOCKSETBYUSER + 0000:461C DEVICE_INIT + 0000:4947 DEVICE_INSERT + 0000:6684 DEVICE_ROOT + 0000:6BE3 DEV_COUNT + 0000:6D6C DEV_EPB + 0000:6D6C DEV_LOAD_SEG + 0000:6D1C DEV_NAME + 0000:6D6E DEV_RELOC_SEG + 0000:1B97 DISKTABLE + 0000:262A DISK_MSGA + 0000:2647 DISK_MSGB + 0000:266E DIV_BY_ZERO_MSG + 0000:7A00 DOSVERSION + 0000:66BC DOS_DSEG + 0000:798F DOS_MSG + 0000:669E DOS_NAME + 0000:6678 DOS_TARGET_SEG + 0000:61E3 DOS_VERSION_CHECK + 0000:6664 DRDOS_PTR + 0000:1724 DRIVERFUNCTION + 0000:0602 ENDBIOS + 0000:668A EXT_MEM_SIZE + 0000:020C FASTCONSOLE + 0000:6660 FUNC52_PTR + 0000:66D0 HIDOS + 0000:6ADA HISTORY_FLG + 0000:6ADB HISTORY_SIZE + 0000:3F43 HOOKINT2F + 0000:00B4 I13OFF_SAVE + 0000:00B4 I13POINTER + 0000:00B6 I13SEG_SAVE + 0000:0610 I13_AX + 0000:6670 ICODE_LEN + 0000:31F4 INIT0 + 0000:6420 INITSTACKS + 0000:6BE0 INIT_BUF + 0000:668E INIT_DRV + 0000:66BA INIT_DSEG + 0000:668C INIT_FLAGS + 0000:391A INIT_RUNIT + 0000:46D2 INIT_STATIC_REQUEST + 0000:1A11 INT13DEBLOCK + 0000:01C0 INT13TRAP + 0000:1A04 INT13UNSURE + 0000:1B2D INT2FHANDLER + 0000:01F7 INT2FTRAP + 0000:01B6 INTDISKTABLE + 0000:6CF6 INTERRUPT + 0000:6CF6 INTERRUPT_OFF + 0000:6CF8 INTERRUPT_SEG + 0000:66D5 LAST_DRV + 0000:0537 LAYOUT_TABLE + 0000:0234 LOCAL_BUFFER + 0000:0600 LOCAL_CHAR + 0000:0601 LOCAL_FLAG + 0000:0432 LOCAL_ID + 0000:052C LOCAL_PARMS + 0000:03F2 LOCAL_PT + 0000:6BEE MAX_CLSIZE + 0000:6BEC MAX_SECSIZE + 0000:66C2 MEM_CURRENT + 0000:66C0 MEM_CURRENT_BASE + 0000:66C4 MEM_MAX + 0000:6688 MEM_SIZE + 0000:0008 Abs NBPBS + 0000:6BE4 NEXT_DRV + 0000:5EF0 NLS_HOOK + 0000:6D70 NLS_TEMP_AREA + 0000:5F0C NLS_UNHOOK + 0000:7743 NO_CHAR + 0000:0178 NUMDISKUNITS + 0000:6BE5 NUM_BLKDEV + 0000:6696 NUM_FCBS + 0000:6694 NUM_FILES + 0000:6698 NUM_FOPEN + 0000:6BE1 NUM_READ_AHEAD_BUF + 0000:6690 NUM_STACKS + 0000:0106 ORGINT13 + 0000:0533 PARMS_GPL + 0000:0530 PARMS_SPT + 0000:71D2 PRELOAD_DRV + 0000:6674 RCODE_FIXUPS + 0000:6672 RCODE_LEN + 0000:666C RCODE_OFFSET + 0000:666E RCODE_SEG + 0000:6132 READ_DOS + 0000:18E0 READ_SYSTEM_TICKS + 0000:6C06 REL_UNIT + 0000:6CFE REQUEST_HDR + 0000:00B8 REQ_OFF + 0000:00B8 REQ_PTR + 0000:00BA REQ_SEG + 0000:6C00 RESDEV_CHAIN + 0000:462F RESIDENT_DEVICE_INIT + 0000:26A0 RESUMEHANDLER + 0000:6668 RES_DDSC_PTR + 0000:6D70 SECTOR_BUFFER + 0000:001F SERPARCHAR + 0000:24CE SERPARCOMMONTABLE + 0000:001B SERPARFLAG + 0000:40B8 SETUPHMA + 0000:48AE SETUP_LDT + 0000:45C2 SETUP_STACKS + 0000:7A22 SHELL + 0000:670F SHELL_CLINE + 0000:6692 STACK_SIZE + 0000:267F STARTING_DOS_MSG + 0000:00BC STRAT + 0000:6CF2 STRATEGY + 0000:6CF2 STRATEGY_OFF + 0000:6CF4 STRATEGY_SEG + 0000:3F68 UNHOOKINT2F + 0000:43E8 VERIFY386 + 0000:4BBF WHITESPACE + 0000:7740 YES_CHAR + 0000:77C4 _BAD_BREAK + 0000:77EA _BAD_BUFFERS + 0000:7746 _BAD_COMMAND + 0000:7931 _BAD_COUNTRY + 0000:787F _BAD_DRIVPARM + 0000:7948 _BAD_EXEC + 0000:782E _BAD_FCBS + 0000:776B _BAD_FILENAME + 0000:7806 _BAD_FILES + 0000:7848 _BAD_FOPEN + 0000:78E8 _BAD_HISTORY + 0000:779A _BAD_LASTDRIVE + 0000:7781 _BAD_SHELL + 0000:262A _DISK_MSGA + 0000:2647 _DISK_MSGB + 0000:266E _DIV_BY_ZERO_MSG + 0000:798F _DOS_MSG + 0000:7743 _NO_CHAR + 0000:267F _STARTING_DOS_MSG + 0000:7740 _YES_CHAR + + Address Publics by Value + + 0000:0000 A20ENABLE + 0000:0008 Abs NBPBS + 0000:001A CLEANUP + 0000:001B SERPARFLAG + 0000:001F SERPARCHAR + 0000:00B4 I13OFF_SAVE + 0000:00B4 I13POINTER + 0000:00B6 I13SEG_SAVE + 0000:00B8 REQ_PTR + 0000:00B8 REQ_OFF + 0000:00BA REQ_SEG + 0000:00BC STRAT + 0000:0106 ORGINT13 + 0000:0178 NUMDISKUNITS + 0000:0184 DEBLOCKSEG + 0000:01B6 INTDISKTABLE + 0000:01C0 INT13TRAP + 0000:01F7 INT2FTRAP + 0000:020C FASTCONSOLE + 0000:022A CONTROLBREAK + 0000:0232 DAYCOUNT + 0000:0234 LOCAL_BUFFER + 0000:03F2 LOCAL_PT + 0000:0432 LOCAL_ID + 0000:0434 BPB160 + 0000:0491 BPB360 + 0000:04CF BPB720 + 0000:052C LOCAL_PARMS + 0000:0530 PARMS_SPT + 0000:0533 PARMS_GPL + 0000:0537 LAYOUT_TABLE + 0000:0537 BPBTBL + 0000:0600 LOCAL_CHAR + 0000:0601 LOCAL_FLAG + 0000:0602 ENDBIOS + 0000:0610 I13_AX + 0000:1722 DATASEGMENT + 0000:1724 DRIVERFUNCTION + 0000:17DC CLOCKTABLE + 0000:18E0 READ_SYSTEM_TICKS + 0000:1900 CONSOLETABLE + 0000:1A04 INT13UNSURE + 0000:1A11 INT13DEBLOCK + 0000:1B2D INT2FHANDLER + 0000:1B97 DISKTABLE + 0000:24CE SERPARCOMMONTABLE + 0000:262A DISK_MSGA + 0000:262A _DISK_MSGA + 0000:2647 DISK_MSGB + 0000:2647 _DISK_MSGB + 0000:266E _DIV_BY_ZERO_MSG + 0000:266E DIV_BY_ZERO_MSG + 0000:267F _STARTING_DOS_MSG + 0000:267F STARTING_DOS_MSG + 0000:26A0 RESUMEHANDLER + 0000:31E0 BPBS + 0000:31F4 INIT0 + 0000:391A INIT_RUNIT + 0000:396E BIOSINIT + 0000:3F43 HOOKINT2F + 0000:3F68 UNHOOKINT2F + 0000:4043 ALLOCHMA + 0000:40B8 SETUPHMA + 0000:414F ALLOC_INSTSEG + 0000:417C ALLOC_HISEG + 0000:41A4 ALLOC_SEG + 0000:43E8 VERIFY386 + 0000:4400 CONFIG_INIT + 0000:4401 COUNTRY_INIT + 0000:443B CONFIG + 0000:45C2 SETUP_STACKS + 0000:461C DEVICE_INIT + 0000:462F RESIDENT_DEVICE_INIT + 0000:46D2 INIT_STATIC_REQUEST + 0000:474E BLOCK_DEVICE + 0000:48AE SETUP_LDT + 0000:4947 DEVICE_INSERT + 0000:4978 CONFIG_FINISH + 0000:4BBF WHITESPACE + 0000:4BCA BUILD_CMD_TAIL + 0000:4C50 CONFIG_PROCESS + 0000:5A4A CRLF + 0000:5EF0 NLS_HOOK + 0000:5F0C NLS_UNHOOK + 0000:6132 READ_DOS + 0000:61E3 DOS_VERSION_CHECK + 0000:6420 INITSTACKS + 0000:6660 FUNC52_PTR + 0000:6664 DRDOS_PTR + 0000:6668 RES_DDSC_PTR + 0000:666C RCODE_OFFSET + 0000:666E RCODE_SEG + 0000:6670 ICODE_LEN + 0000:6672 RCODE_LEN + 0000:6674 RCODE_FIXUPS + 0000:6676 CURRENT_DOS + 0000:6678 DOS_TARGET_SEG + 0000:667A BIOS_TARGET_SEG + 0000:6684 DEVICE_ROOT + 0000:6688 MEM_SIZE + 0000:668A EXT_MEM_SIZE + 0000:668C INIT_FLAGS + 0000:668E INIT_DRV + 0000:668F COMSPEC_DRV + 0000:6690 NUM_STACKS + 0000:6692 STACK_SIZE + 0000:6694 NUM_FILES + 0000:6696 NUM_FCBS + 0000:6698 NUM_FOPEN + 0000:669A COUNTRY_CODE + 0000:669C CODE_PAGE + 0000:669E DOS_NAME + 0000:66B8 BIOS_SEG + 0000:66BA INIT_DSEG + 0000:66BC DOS_DSEG + 0000:66C0 MEM_CURRENT_BASE + 0000:66C2 MEM_CURRENT + 0000:66C4 MEM_MAX + 0000:66D0 HIDOS + 0000:66D5 LAST_DRV + 0000:670F SHELL_CLINE + 0000:6ADA HISTORY_FLG + 0000:6ADB HISTORY_SIZE + 0000:6BE0 INIT_BUF + 0000:6BE1 NUM_READ_AHEAD_BUF + 0000:6BE2 BUFFERSIN + 0000:6BE3 DEV_COUNT + 0000:6BE4 NEXT_DRV + 0000:6BE5 NUM_BLKDEV + 0000:6BE7 BOOT_DEVICE + 0000:6BEB BOOT_DRV + 0000:6BEC MAX_SECSIZE + 0000:6BEE MAX_CLSIZE + 0000:6BF0 CLKDEV_OFF + 0000:6BF2 CLKDEV_SEG + 0000:6BF4 CONDEV_OFF + 0000:6BF6 CONDEV_SEG + 0000:6C00 RESDEV_CHAIN + 0000:6C06 REL_UNIT + 0000:6C08 BLKDEV_TABLE + 0000:6CF2 STRATEGY + 0000:6CF2 STRATEGY_OFF + 0000:6CF4 STRATEGY_SEG + 0000:6CF6 INTERRUPT_OFF + 0000:6CF6 INTERRUPT + 0000:6CF8 INTERRUPT_SEG + 0000:6CFE REQUEST_HDR + 0000:6D1C DEV_NAME + 0000:6D6C DEV_LOAD_SEG + 0000:6D6C DEV_EPB + 0000:6D6E DEV_RELOC_SEG + 0000:6D70 NLS_TEMP_AREA + 0000:6D70 SECTOR_BUFFER + 0000:7171 DBCS_TBL + 0000:7175 CTRY_INFO + 0000:71CA DEBLOCKSETBYUSER + 0000:71D2 PRELOAD_DRV + 0000:7203 CFG_FILE + 0000:724F CFG_FILE_END + 0000:7740 YES_CHAR + 0000:7740 _YES_CHAR + 0000:7743 _NO_CHAR + 0000:7743 NO_CHAR + 0000:7746 _BAD_COMMAND + 0000:7746 BAD_COMMAND + 0000:776B _BAD_FILENAME + 0000:776B BAD_FILENAME + 0000:7781 _BAD_SHELL + 0000:7781 BAD_SHELL + 0000:779A BAD_LASTDRIVE + 0000:779A _BAD_LASTDRIVE + 0000:77C4 _BAD_BREAK + 0000:77C4 BAD_BREAK + 0000:77EA BAD_BUFFERS + 0000:77EA _BAD_BUFFERS + 0000:7806 _BAD_FILES + 0000:7806 BAD_FILES + 0000:782E BAD_FCBS + 0000:782E _BAD_FCBS + 0000:7848 BAD_FOPEN + 0000:7848 _BAD_FOPEN + 0000:787F _BAD_DRIVPARM + 0000:787F BAD_DRIVPARM + 0000:78E8 _BAD_HISTORY + 0000:78E8 BAD_HISTORY + 0000:7931 _BAD_COUNTRY + 0000:7931 BAD_COUNTRY + 0000:7948 _BAD_EXEC + 0000:7948 BAD_EXEC + 0000:798F _DOS_MSG + 0000:798F DOS_MSG + 0000:7A00 DOSVERSION + 0000:7A22 SHELL + 0000:7B80 BOOT_OPTIONS + 0000:7BA0 BIOSINIT_END + +Program entry point at 0000:0000 diff --git a/IBMBIO/BIN/BIOSGRPS.OBJ b/IBMBIO/BIN/BIOSGRPS.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..22e96023f6ff554c3403e4a4541acc477e4b4ce1 GIT binary patch literal 307 zcmXBJu};G<5C-78B(~$kP5T6$nHX4^Okx#_Hi_btm6ZozU}WwCREV8-LI{Zk5TXxp z#JS<_zWe{D6wqEC9|2^&8M=L+)m`IMV@K=SMoklc;d#e6_pKk}J0m74Ca%4mZy$Ow z#JZgKo!$CPs|FXYd>4x8?sqQMGK{vq39ruz&H&OBFIYn0`J{V*g~88B*8s*KaJF3H zJFBYjgIg)laHbUgvGN>$S*sPkv9!h?R;lreRcQQXWg1T}Ye)zwp_DQbBuP@6`!6T|L$o0RF44(&iT+o={$cd}szSlFPR zb3Yl<*?-#U%GOW!dG7C=d(OG{`$j9Etkdlex_$0m+fPnE3jmTW=xyG#!L-)0ewS(O zx@PaL;pR;ntN-#_0BSMZE7??bze7|9du{e@Du=DtrlrZ$#tTnc{x=1hCD>h(zc0Y0 zYDkpm3-RATFrXnJqR;Wn_cYLTR8^s2r?GV4-^wcm23TqY&?(sq)Fwey8B0>>5a_k+ z5S0L`%h|vGwGI{)l|@C771c#mQP`SPp_-$=K6{HXR!%EMoF1DixEfeRuuJrKB6g44 zC!PmZ=IirDoNkX8T)$B92Snc{V3lZzh*$JRg6;wFMPNFIKN#t?NiMNB5)@svz{g+JRb=F^45&kS4v8iOdL<~k4yBLxD{@#@+ULwmx{7z?3?5)IZyWblOi1vs> z3bo)=-W#yF#I3jxk>ra7*8tNKDSMwJiN4-Qr!6S%#MxhI+l{l`e7Z;U>49me&ua_s z0j4E7KATr;FO?mr$q+4G5{LZ;T+i9(v%j>ChyxDfis8WU6V^_5xGxZ_!G&ZkaG}Ld zDmYSyv$$dHoxu$_%kJ;<^-BE_Vzq_n(T>pC1HjZ>Zd~;c&R8&ZBdsF_BMwKi}?Ok5ma~f9G<@axM`+C~jrzfOqoM|tbUSDlORhmo zk+aPaaiZZ^CGM^RZRYjbd=9pV*T_|A1JSp{5cZ*6na1uBZN9z$`H;`)cA<_W$43r~ zCS%$NZM!$UiMDO5EYgprw|Cj3()yi!PA4kE7SR~m z2AYNIbL&Msj$XE?w5$`?4R)~#8i)q!^-KM-WFB8kyu{bg%DF+e$AMYe$E ziM5_sLdUzGD$kiL7)FrQFPUpWaap3Qxi+$(`ofm-aA1|P4duvY@(kG&rP^~4SHNLXSw083*>*}?eH*YZ6cOBfbcX-!oll%2oEGFB*gC>bajhLjp zBYTJ6+`GpV#!vGa{4{Ugv~j~r>#gh7hJXKX{A%(>^5Y*LRXxgtAz^5QZtF~PX8Olq z&ey+lOnIprE-K;f_hZhBYS5&XKz@4-WBEaX2*DwQed%MM_%@Bw#*Gq;3%!sPy60Lt zTT$LfQ+Idriuoe}V8A?!*<1_nv}=I`tKjar&Qmz13BTsJK?xI$&?ZgI!5ai`Avn`-gW^6U1sx=Gdbs;u<^W_($mn|E{tczj2p0h^`5^JQ z>F3FryYC6v=M{mUp8X?!uBKK&UO{xYQWaFv)i5DnOQo+-$ymb_`4gEWeYi^%}upf+GY+5qxB_{R&)Q!T`9p$r~3` z6GpHw!3ft2mdrAk&{Az5)m8}yfMR08M72}GtJL!kMwg2V{Bh&i{w5KA2huCz!J~uOdnsf@cVx zC1@aMB-lXEN+2S2cKvon3voj^ zg;c`$Dx5J`;9=4@1eT(4A6SyY5KNoFoN(2BQjq`5$M@G&ftk6MJ<`=D1p{`rH)0G7 z!34nj^j($;LcT1d&MziP1_DlaIh9rsG!v{LSWm#CuZ>Eb1TKR81e7)MBcYo7kieWA&^M!pmOK7{b1=_2yi|loATR5wgX_(`v9@v;Naui%ye;ZPR}RxW>5gUHneq z_Z$>bBJhnkQSCJ6>xde+{%R_%BjD^EAtB#IHJ&RD)-aWcxC9*?pmgSccP0San{K^`p z&ZA0d+8=cucSU`o!?`@~Ci*-j2B@@yU>Ct20!oQNitm6*rft0x&;8~g79}xn1;f;Fxft>#F0569fLe7W8UI2 z9Z{LjxJ>5Lu7(S$$?&~ja;N^lQ+Q4JRIwkXY(NQ+<*NxOzn@s@tj=@KL(RVGehZ$b zlJmZgdL@Kk()RpJr6I?{|0D=WVJF7MZfG*@gvoAHVE0@@GG|Wc*5T>bz88p>VnzEe{!3G6g~D>kvbL$CsLSx;HWfq{C2pWIPC8Kt4$qO>zDb>WY-hav zq5_VjR=^2`Q-4D3Y|1YpUR;|cRPqpzXLXXbU1}1=#k@^oNWAi?c%v}ZUJJ!oRiRN~ zy><#SPGPaSa8p(As0vHb*-z|`A&E5=9V0cSGEY=O5AHS}S2(En4(EWG*IG7mx9kNe{WOwUFG zSnqxEtGnk=4IvP;yb<$A#v?599^SiDUX~v6!4WS&Y`06FU@%S=@!^KQA`TDjzi6IHI=R z{IFOoO)lB`m>vi3YJGTQ2hLoR(t~_xZ6spk0rkXbqb50HPKXL~;-$o`v0T;h&rs&A zrrdDn*lgAD|NOkzdU<$bw5I7YMhv?2E#<$O;~UYoip1R>NnR*^L?5P|M+K5s68}O5 z>qaklkV8hv+27>^dDz%7J;Ywmf_<)K>uBs)R&W1xssi%uL}xF8f`aIRX09b}Jct?d zb(qAH;UJ7XWU>8|424sz4Ug;oN##P(CySnS>2Cu!Plq{k83osQw)Wf9~b`kG_ z=Zwi4muBFdZ|l#Ud#|3)nZjYM+x4+Z3aEmp7*=LXaE*e9AMaXX#go@ED!o9kmVl=w zqMN7q;Wv{}vSYJWlM4iUF0$(E=nHc#b1f&Y^$&()&tjXD`1qny&6@}M2Zz;TdBuZV zSPrs=!Y&wImg|wmuGEv^S`EA5O;sH618+eI1N}K;PvUBaQrHcx!X6k|dkRa*8y%y(%}E~V;0X2*k_9}G{g$p?_iN{f2~b1e7;0*&gOeRx?~RaTt`s2n;gp8GMk-vhd&A@MsUx!IBD46?0zr z-Ql`cp%IRh3(1*D_gsT!zC3dn{tPF!P{i=8-$ZufM>N0V(+!YcmE}#=2krGW17;lj(MydA9-%klM~+9S$+ipUfbo2zm{y7DvK?(&Scb(DOuBw zSGi0j;B$^FGg>)5(_vN$O1yB+pV#F0vyW~uoV*rexv|St$3OkNI8g^DXQDz!w7hHn zdHHlu7n;8uX-r&RxZo|M;_1gD%0l>Ya>iQx#KUxE2vcX4J3MoK{djE@zN6AB;ve%N51RZ|A@D#mjdbWJ&Q+}p}oP42TLLJtqF zW3<^-#E9RJ`Sr|9Rc=JS_xySmq&7;Am(m_k{6%><@c>T*J>FQ7x%YW$?~x`XsKAHQ zX!XLa5T7nm4~zKBihGRtzc<{Pk5y)2P2kr2^t0b UVB0cOdhKN)qbxatSIOvq1JsD_TL1t6 literal 0 HcmV?d00001 diff --git a/IBMBIO/BIN/BIOSMSGS.OBJ b/IBMBIO/BIN/BIOSMSGS.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..cabc1859d3bed800f75e167f5e7924ed27101394 GIT binary patch literal 575 zcmZvYF-yZh7>2*INzb`#v3GO0M} z;C~VkbWjof1x|X`TT~o!_k7R$@h0RX2gqJMKL*G*yfA1twMO8$hGVyE*LMu@$XO@q zl)6BC(vsr@q%ov%{q4!!q)k1PadC1+_9pRsBXnt<1k@6Dd&`w^p0@192EDyBU!xC}=%_QVCrsSE-rMW%^f z6%|eNtjIFaiz3ZLA6FVoeQA5whoFhqTckf^JjHP`?6EXucz?ig%##tru!1}NxNKpJ zhbd2bOpIgPV`F^OWqr(9CmxqAOLREND2W+%IUn${6g2JdH0d8;C!n=jO}NLb3ZR(| zp&QW_^=tsR`K{^;0H@ik*s3^WJF4$QyKWfBWe32{=0s2xzcXwR--|@AOxggS*^Ef6 f=x6iVA1A99RfE|3+x?Wyi-wu#pYqGIDS-4FQE-U? literal 0 HcmV?d00001 diff --git a/IBMBIO/BIN/BIOSSTUB.LIB b/IBMBIO/BIN/BIOSSTUB.LIB new file mode 100644 index 0000000000000000000000000000000000000000..51a8f91cd9f888aba2b6a03e67e79fcfbdd79f4a GIT binary patch literal 1024 zcmeys%fP_Iz`)1=1r1yb97!qp#l ze(}y8uFl?!42-f1*gy_HeE4z~&AG7oPC2xL{O>_8|ZObFp)0 literal 0 HcmV?d00001 diff --git a/IBMBIO/BIN/CLOCK.OBJ b/IBMBIO/BIN/CLOCK.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..588d30553b953160f5a3d8168c95b2566744c992 GIT binary patch literal 1235 zcma)+e`s4(6vxlWdoQo~(e!nz{Smu%LkwcIGW(wmvh?NAg{4VMQduWhko=*-V1&$y z|Cq2?^>xf9f~-=cqX@zfBFi6bvp*wcemo^?3zE0*m8vl;ifC(F3URaY0@;Yv~P7FQMv-sZ|? z!5UXq3x3a)XuCQt+z z9UdK_s}n5nAHNMDS#}w(I_>~m0k|68kf8N#<_yDk!e<5BkF7>%qS$JjDV!TE;E8Ye`%O*t#xnp2g<2aGtiU6qm+IQ}tiQz8t$TuD=D4JQzN2 z{%2CH|8PRpcj>{|Yn?SoW%5$R>00udn0DzgDF-Z{7b?zN%+-uZS(ok=FALi%1uC%d zcFs+vz)TaFTRD-6E?=ku)g5l_F5Nuc+7(JP&SvshaZOsXB4=jF6dH3XkmX9@SfA>Y-Vcx*P@w~fP%j%`hjKl-~qepqM;!GVRhvJ7) z2P;Px?5VqmadYbKq2n)^Hgx;s>a|R250Oqm@rg#Fe_Vf^>S70>L~~CdEuhwK>)TAQ?N~G-*TAjB2kp7K~2JEj5 zf(-0%8PA%i&8|169j=S>3LTNsYB!{jW(|WO_oGl)?gbRBsz0cnih8E}njPTW@*sJ= rVa?;6kIY4)+RS{^N1qG@;rHb}K&hL5O-_0OUcVNmF1@0g01|%zP5guq literal 0 HcmV?d00001 diff --git a/IBMBIO/BIN/CONFIG.OBJ b/IBMBIO/BIN/CONFIG.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..998c73d9e1c9b3b97df4d5d985d1a15ed837e6ed GIT binary patch literal 4810 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 YgBchYZ!TbCU}Ru8eE4z~69YpD09D2<0RR91 literal 0 HcmV?d00001 diff --git a/IBMBIO/BIN/CONSOLE.OBJ b/IBMBIO/BIN/CONSOLE.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..b52a748c484fc7a721d97df26d7052676f7d830b GIT binary patch literal 876 zcmaKqO=uHA6vzLwn`E>3*lvwRL~KD}DHJ>i9z-f^(=-i@*^*7glf8Nnk(y8sf&nAc zTGWFSEfpf@#a1X1;YL(w2ydCMwD7i57?4A%9M^!>u@C zXVR&xmP@+5X~zu_hmR*kJK*N+#Gw1&wuUZ1RoNkFem^@%b{dFA*k`hV?}$WLOxD`k z*hguG!9I!ZVFUu~gRE&9`z9?IWDRMi$yTN5I{PXutg|oDLOR=!=F{2cbP!6DHGNIZ zo$Ns*;bikUC)1lt+Jg|kLL33%e%qz6)AVGoL#(9EmguPSrdO^N_2mGKjaz^x478CaK43i(u=pjT z0X$s$qjlFjvO>ffPer8{e^sHhia)5cx!syEX=co@=4PgWb6DFJbNgqWfU})UnrDzJDTvy-c{i)TQI zFs&Lj>Si@WfuBi#KCnK5=!#{m9$BbV-1> I6AJy*zl8_z0RR91 literal 0 HcmV?d00001 diff --git a/IBMBIO/BIN/DISK.OBJ b/IBMBIO/BIN/DISK.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..21f2aad88edce1dc427dce8014b00a7bdc73930a GIT binary patch literal 6634 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 l<>1I(#`|8my?0Ekw{8dj`dTezxZ&1VZ& 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 literal 0 HcmV?d00001 diff --git a/IBMBIO/BIN/IBMBIO.COM b/IBMBIO/BIN/IBMBIO.COM new file mode 100644 index 0000000000000000000000000000000000000000..41b8a9fa5e4330499daa2da57dfa4f0884c771d5 GIT binary patch literal 27880 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�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 literal 0 HcmV?d00001 diff --git a/IBMBIO/BIN/INIT.OBJ b/IBMBIO/BIN/INIT.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..c04969a408ad13f8d0bf691a361ba28e06dccda2 GIT binary patch literal 5036 zcma)A3viUx6+ZXhe;>(ilFfr30!Tm}qTmVyp;ResHh;p(W_PoXKwxC8RjO92jlo){ zwy`V@kU)cDDZ|9N#m7t?t<+{T_`q2HAFVV{tW~R4@HMD$92CVuQ_}C;n*<`@@Xwrk z&iU@S_uPB#{qL*AK_YnB=3fxGLbZulI%#+~5?Gn8^B*vKo>OfV9zjk*(NvML-)=7Xo}OwM*CQ^C;UWW^RYP1Riv zhnUI|k<%#xkglWR!UFL(NQ<^pL4k-$jQoD_hLVbk#G9O3t+`xcx5C_R@rjZ=9`TWq zii^c-ER|4Ro_JMZ-aPSvlJfJ!hf31(MDLb-!q?d;d_o-B>LIOP^y~fZWZQGX!_DX3 zl5bGTAVkn&u~a4&PlaRAB;|)9vC!gFuqtAbHx#Q&#?4TsI?+JB5VB(tb1*BNNSM)7 zraG1+Z?)MF4w;z*Dx$pVaB`r$6f4Zr>D6?u71*6pwGeMpqk3KcbHQ}Y{c#`sz#(oDfVl_2M6CG0-Nwby;)Fc?J zsyJyT;z4BB)y1MJK7P!NL@FGu4kGXD&mnk1{Svqmbc{c2*SrK-_%h+S>YG%GO`?H!ux!# zoP>+erFgJDbn{KOe82hnt8cuPP4{$mxXALC3H>MA3Q3G19kp99|EQS*IbDjP&DEzF;$(k^4HfkwtzX zE+xwa_AFT*us;Z^1gw^v9Et5A2V^S_JkY zSy2VX!BBh|*ssaDN`Y5{Z57syV817;NrBB^_X{hlw7bC`6i?;qNOW?DMjfx*wbW{g8hrEaxjEo3>Z2#8LXGAX$rg; ztW{WZ!R{n$z5*A3wTl;X-{FDwb3;lw8No?8Cu2D2J6>3^VGhv_CslTD?0$6r!Tkq+ z`_M!0ebG}sy~9IR1!^I&GFMFEMxHMCs<2vOy=>|*$kLGgBQ-E+Tt2ivi+|_3NVJHz z3t^S}h;5MwPBcy&oamf5IdO3!O-?4C5WQX4(&ua*8+d@|KOKR7gtf`>vPLa^dCfi) zI0hN4_W%-U4Zf92?HbgE@p!UfN&0e6b3td}Gj8hfUzu64eCfWyvVj*dV2=KMM3;2z zq^ujg=n`3;a}1G}omVF0Jk)iv zY7J2+r(Y*!m&4{Wk>v>o_CvP1!4PHHn^|fy#0cwlLm1gRS#2@I*z6jX*7}8h4`m-< z`C-TzvK~VX{ zqnE!cFaJA3U%uVT2kd40FfV5qmxHP=SLMktACq3(3M*3V+r4zLmwm&$oIPSW=P6zs zs``O(`F1a_v6s(=c{zJu7J8+Z!?G^})t8)0Upm-Jfo$X8Og=+j4y&s0XYfoN=4H~k zcqz<1PGY+AfHqkxxu`#Ww8(>MH2g0h2S^7wK`xLRq6G4+elR;BJ7l5W}%W)LIkIsK) zJ#Xn+nQ+~iTco)eIsFUlhUuBxgq zcALj0Wg6S|vPtF9Kr2kVM^`P_Nwg%MtWRvfaz1Tuu=Uv22kts_xPM8*{*RA5lv(ju z>r3w&U%x;ttMnre_I`fXyZyg>zqhjc$RoWUE^A!AG{g0^9Pe)q+;xKdP1S*Q1~y16 z>Vb8rFR+%k%e82SY^Fmk#C*01aO0%iNfWtBQ}5_N8#kq!bMFakBg%F+Yuh!J#<`}w zwehV&_XZS}8`_lh&RX8lHe*NooXZn&;d7PT71$!+rgLr2h+DPFZipOCM^DN87P`&J zvhz=_e;fqf_R?k0R*mhF1)f0z-{7;rkibe81uNg`8PPOp9JbmwPBx-qps){xFP7y| zp{ht3p%yOR23ozKzuDcE(ON5dzeJpN5K)a>Y@1-mM{ zdq%guT;C~rjK)>|dR7~!?O%O-QWJ)0*L+&g?3_k6fD%QY7pNdQp)*5wfn?7oY_i+0(#uviaaNQ?t2sF0wBL z^O4QRD1etiDE5@vAmMH=1Lj*V3J@_Pubw{^JJV}qz@$Bk2X zs)LQ8SQbO0OaOaj$PjL&;gdwaYWKl~ zlW+es%7_lAXv!;pDiMr#3o0CfX4NqCwV+)p0SL z02&JgBmDkQVWHgTCU};d4fLSaFUxsM--t*KwQqog;a>pbJ&OSfW;T*~PuU?M&p!nlrWW zNTrh+Plb~4)C?yrQbUt4>obTtc88XeKs=QIaP3I|;eMLv4%NMZcMf#9g6N7jYVQdc8W+#72L#WttL)oJ4F=? z3>^@Y7Z8F4BnDvMKY$7NCtzh@0kL$2JKM=!QCWP-_uYH;qa{%=n&|Fa6ZL8z7P_x(VT5bzDE|PRj zQ5OZXZlbo+v4trpSS{4^P}lK&$6b$9G&M{$OLDm!iLTYPnLx+#1Jv@IZ5uT=EYE5N zwudhCeH)2_usqG&T=Q&e6Z!X?pt%v>&^7X+t|-&=A-CUM!xegMwAOF8ZO>;a&=~RT z$3^A@VRmkAI-5DDh9VWr|3pNyrdMSR*>2!DgJPFv=LO;N?A0st`wB8#iiUctDjF5E zg`4f#xLZGm`o6Vp=d+n%Z~@H}^DVS8Bdy|(l5dlvl;0qSMm}cVCr2$Gtg`+}Dt2Ym z4=g^2Eg)TcfT5w4oa?$Px#Z{SzCz7jANRF`N8TdS`e(Rw5wQO)k8~kqGu4i5;kjWT zcmNiPcZQHABggS6$YvzVJs+S>4=+nmAMVbJ@C0z&k%Cxk6bxCsxeK6#<5)TxNlS_% z8|FKJfQph{sfb!}1mGMiE@?HR{+olt;RH@UM$!jRZ*Z_19>;2$sPb)DO7p-|h0OXV zz*(B9sAX9bEAmBv57Z%1%`X6Zj6^me&B1$WC87O>gKBsRKbj?vmhsXMJMuEXX__AW zIYfZ%a17rZ#b6p0b5ZBvTP$dLLn?_z3gCKdw=SEJ0sue4lQ<{Sh(IOmzQ--Z+7R9Z zqf&aG_o)MXuVc?q1%}_5*mEQ&0ADduLhuul%pknOI2|y2!fFY`3gd`U{1r~(KF6Y` fS&Sc<3ImRlF{K6tc|TDo$*+lT2IZs2JYKQC=M`TN literal 0 HcmV?d00001 diff --git a/IBMBIO/BIN/NLSFUNC.OBJ b/IBMBIO/BIN/NLSFUNC.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..7ac77e9c7c4325fd900caeae2b961a460ba31c81 GIT binary patch literal 1045 zcmZ{iUr1AN6vxj`=e=hB4H;OvP0Z5F-_X_4T(&i*l{(klEG=0QWwSuI-jTid2UFCU z^bi%Xhm{Y3^kC4#99WCp{=$eJBB`h9#h`j_6s~i&$cJdK&;9<+z4x5&Ip>aT0@2>q z+3dDkk53l?fYZ|1UR`I@)$l!ix|-VR_CBe)ZePI-BS41jgv)7BSv#6+8J#YRwN=$* zaal5t*pIj<_E!kj7H5ask$li`ON8@>(nNvXLsbE=DV^=Ut%A%1>zP+!y|M4tN`SE} zG~sdE4|jC576Z$q6KMc;WiB6b=lllIbe?XyjL$}J@&$KCfqmayTMUl z=TiOWYKK^qFU$e18gtjHCGd&7UL%8iAv^+xmq`!q6`XGc_RuSxP6n3KAUq49N}8aZ zk2lW3lW#s->Q*6yr9Za}e4-JzC|6;22}@vF-hg%DftJ*sl>#!A{EA9QRTB0S%!D?A zn{blQPx#x0av6`K!Lz_VGT&RQG=-IL88{x_vyD+jldh5*h)0EEPK~(!Vpn2z_04DQ wzd8JGhdtd=Y%(IJ8c%h&B1T!D5|j+8pB#1}sUm`wP)9gO=t7uh@q3nk19bQ&5C8xG literal 0 HcmV?d00001 diff --git a/IBMBIO/BIN/SERPAR.OBJ b/IBMBIO/BIN/SERPAR.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..d2eb793002159f5e2c9892d907410537747df327 GIT binary patch literal 969 zcma))OK1~O6o${4NoF!hn@5u-Eh5H8M}w%K;Kq&9WK4t2gG^cx#i|>{Wt*To2O6Qa zUAQVDU9=QI#6=ca6m?OWiz~C}Mnn{$My(Al>>`4jc<$WVwZqK${`>#u&fK{(whU;T zTet_HB-6$GSizOdr%W|vlngVMQt9GjcSclhdosC9i4PsY9hEy~ZrowPD!7Y0_BnOJ z7|o<}YSFZYGkMEP9Lt(KR;-edyl6drtimw>S;o^sx!rh@)NO#?9{fyd`;EM19 z0sJ78-;W=8Is}S>--V~DxGj{&gIhucgZN%3O~Y?O`7~?^<<;=3P%aJIPdp%XvFqxp z*8CyhFV7bZUdt>NjAC-cDE`wIMvXMwSh|ibfH3^$u`1gQ`!ztfqRdtS+R?h)jC2^5 zLv^VcnIY>9U0wTaw{d)}ab`{QdbtUFLW8&2Eq_DN=kk4D`lq+$$>7|M&hGoS0IIEu z{Cu;c>WO?GO`rZFPll*tZilk6s?Vf*$z27>Nq+AoKSl49Yt?5r_FOkjYIi7do|IH{ zcGpkg)WPX>S$|Q7W~?UB$}91j)?x9=;Q0yD0U!TR-eVo^6vTwd*_eE4PY2SmB~SLC4jjFQ~`}J3Cu@W0M<*W0Sge; zfrSX4fQ1G62?=B|LIK$z9|7A(u#oL1j3YZB%!2}l1%?EU5-uY<6-AkyjiSUdykzN4R3R9^{f2)uK$BTETT0q6rwDYRFyw#GLCYAekMyCy9I=nvC= peSRWHyYO;R0X7gtyz^)P&=uPK6Z6?@K36h^M@{-QQnM0$;lI7X6%YUb literal 0 HcmV?d00001 diff --git a/IBMBIO/BIN/STACKS.OBJ b/IBMBIO/BIN/STACKS.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..b2ef364c243e7f4e5cd4c92b27b8800fb47431a8 GIT binary patch literal 1230 zcmbW%Yluu?7zgnGd*(PZZnNvQa$EOF=p-vPBU)pvMZ1`tEwn>y67s=i6%uA^jk7ks ztW8TBOL7azEorjPAgxP8k}oc0L+it;EoA)PIj4N_$*I%tJ?A{{+y9*B?d3wC-uz-rh;8xVcN-R!}(elH|rlaytJKatJ%)1Qg#EM zIMoKrSgR+*t5!ZubO!7&$6GJNtJ?IdjN++ZLC4q8b!;73$JJ4FOdV0j)6sM+2K!Zz zYDfh~9^z6Lk6vs%eY#Oc{QkL`4;MC@N&---P)Q$`Aeo{hH%sjRvLCg>T*kUgaw%{L zyF^?TxkO!7x~z5C=(5#iR~9)yav{fEp18areIOr59^@0rhkPL+$Twm`y2x}$H<=Cj zN#;W`qzq{vsYKdO;z;)<>yXYNn~@$sYLFgG_8>i;yhCxz8yG;oHFw|p-n%SBinQv z|NrP{o};8^u2Kf1FR>tlhzS`&f{+n}9T-glkPu`P?LsDc7 interrupt vectors + mov ax,ds:DOS_DATA ; get # of bytes of DOS data + shr ax,cl ; get para size of DOS data + xchg ax,cs:free_seg ; get seg for DOS data + add cs:free_seg,ax ; remember how much we used + mov es:INT31_SEGMENT,ax ; update the segment value of INT31 + mov es,ax ; so ROMMED systems can find PCM_DSEG + mov cs:dos_dseg,ax ; we need to remember where too... + + mov si,ds:DOS_CODE ; offset of DOS Data + xor di,di ; destination offset + + test DOS_FLAG,1 ; has the DOS Data been compressed + jnz dos_r20 ; yes so call the decompress routine + mov cx,ds:DOS_DATA ; otherwise just copy the data. + rep movsb + jmps dos_r40 + +; +; This routine will decompress the DOS data area which has +; been compressed after linking using Andy Wightmans data +; compression algorithm. +; +dos_r20: + lodsw ; get control word + mov cx,ax ; as a count + jcxz dos_r40 ; all done + test cx,8000h ; negative ? + jnz dos_r30 ; yes do zeros + rep movsb ; else move in data bytes + jmps dos_r20 ; and to the next + +dos_r30: + and cx,7fffh ; remove sign + jcxz dos_r20 ; none to do + xor ax,ax + rep stosb ; fill with zeros + jmps dos_r20 + +dos_r40: + push cs ! pop ds + push cs ! pop es + + mov cl,4 ; reserve space for resident DDSC's + mov ax,DDSC_LEN + mul dev_count ; AX byte are required + add ax,15 + shr ax,cl ; AX para are required + xchg ax,free_seg + add free_seg,ax ; we have allocated the space + mov res_ddsc_seg,ax ; point res_ddsc_ptr at the space + mov dx,dos_dseg + sub ax,dx ; DOS resident DDSC_'s use DOS data seg + cmp ax,1000h ; surely we must fit ? + jae dos_r50 + shl ax,cl ; offset within pcmode data segment + mov res_ddsc_off,ax + mov res_ddsc_seg,dx ; setup pointer to resident DDSC's +dos_r50: + +; +; Call the DOS INIT Code passing all the information setup +; by the BIOS. +; + mov ax,mem_size ; pass the Memory Size, the first free + mov bx,free_seg ; segment and the initial + mov dl,init_drv ; drive to the DOS init routine + cli + mov ds,dos_dseg ; DS -> DOS data segment + callf cs:dos_init + + mov es,cs:dos_dseg + mov bx,26h ; ES:BX -> list of lists + mov ax,es:word ptr F52_FCBPTR[bx] + shr ax,1 ! shr ax,1 + shr ax,1 ! shr ax,1 + and es:word ptr F52_FCBPTR[bx],15 + add es:word ptr F52_FCBPTR+2[bx],ax + sti + push cs ! pop ds + mov es,current_dos ; internationalise the yes/no chars + mov di,es:NO_YES_CHARS + mov es,dos_dseg ; ES:DI -> internal table + mov ax,word ptr no_char + stosw ; replace default no chars + mov ax,word ptr yes_char + stosw ; replace default yes chars + push cs ! pop es + add dos_coff,3 ; next dos_init call just fixes up + ; segment relocations + + mov dx,2 ; phase two of RPL initialisation + call rploader ; inform RPLoader if present + + call config_start ; get free memory + call config ; read and process CONFIG.SYS + call config_end ; relocate DOS code and free memory + + mov ax,(MS_X_OPEN*256)+2 ; Open for Write + mov dx,offset idle_dev ; Get the IDLE Device Name# + int DOS_INT ; Open the device + jc dos_r70 ; Quit on Error + push ax ; Save the Handle + mov ax,4458h ; Get the address of the IDLE data + int DOS_INT ; area in ES:AX + pop bx ; Restore the Handle + mov idle_off,ax ; Save the data area offset and + mov idle_seg,es ; segment + mov ax,4403h + mov dx,offset idle_off + mov cx,DWORD + int DOS_INT + mov ah,MS_X_CLOSE + int DOS_INT + +dos_r70: + call mark_system_memory ; ensure any memory we have allocated + ; is marked as system + mov bios_offset,offset cleanup + callf bios ; execute BIOS cleanup code + + mov ax,(MS_M_STRATEGY*256)+3 + xor bx,bx ; unlink in upper memory region + int 21h + + mov dx,3 ; phase three of RPL initialisation + call rploader ; inform RPLoader if present + + mov ax,12ffh ; magic cleanup call to MemMAX + mov bx,5 ; to do any tidy ups it wishes + xor cx,cx + xor dx,dx + int 2fh + + push cs ! pop es +load_e10: + mov ax,(MS_X_EXEC * 256)+0 ; Exec the Command Processor + mov bx,offset exec_env ; Get the Parameter Block Address + mov dx,offset shell ; and the Command Processor + mov exec_clseg,ds + mov exec_fcb1seg,ds + mov exec_fcb2seg,ds + int DOS_INT ; Go for it + mov ah,MS_C_WRITESTR ; Print an error message and wait for + mov dx,offset bad_exec ; the user to enter new name + int DOS_INT + mov ah,MS_C_READSTR ; get user to input new COMMAND + mov dx,offset shell_ask ; location + int DOS_INT + call crlf ; tidy up with CR/LF + xor bx,bx + mov bl,shell_end + mov shell[bx],bh ; replace CR with NULL + jmps load_e10 + +eject +; +; Initialise the PSP and inform DOS of the +; location of the BIOSINIT PSP. The MS_P_SETPSP *MUST* be the first +; INT21 function call because the PSP Address is used during the +; entry code except when the INDOS flag is set and certain function +; calls are made. +; +; Then open the Resident character devices so that the dynamically +; devices can output messages to the screen etc. +; +config_start: + mov cl,4 + mov bx,ds + mov ax,offset psp ; Now force DOS Plus to use the + shr ax,cl ; internal PSP for all disk and + add bx,ax ; character I/O + mov xftbl_seg,bx ; Update the Handle Table Pointer + mov parent_psp,bx ; and make this the root process + mov ah,MS_P_SETPSP ; Set the current PSP + int DOS_INT +if DOS5 + mov ax,3306h + int 21h ; get true version + mov dosVersion,bx ; and plant in initial PSP +endif + call dos_version_check ; make sure we are on correct DOS + + mov ax,4458h + int DOS_INT ; we need to access local data + mov drdos_off,bx ; so save a pointer to it + mov drdos_seg,es + mov ax,ext_mem_size + mov es:DRDOS_EXT_MEM[bx],ax ; save extended memory size in DOS + mov ax,5200h + int DOS_INT + mov func52_off,bx + mov func52_seg,es ; save pointer to internal data +if DOS5 + mov ax,ext_mem_size + mov es:F52_EXT_MEM[bx],ax ; save extended memory size in DOS +endif + mov ax,(offset TEMP_LDT)/16 ; use our temporary LDT's + add ax,init_dseg ; during system init + mov es:F52_PATHOFF[bx],0 ; point at the LDT's + mov es:F52_PATHSEG[bx],ax + push cs ! pop es + + mov ah,MS_M_ALLOC ; Allocate all available memory + mov bx,0FFFFh ; BX is returned with the maximum + int DOS_INT ; available block size + + mov ah,MS_M_ALLOC + int DOS_INT + mov mem_first_base,ax ; Base of 1st allocated block + mov mem_current_base,ax ; Base of allocated memory + mov mem_current,ax ; Next available Segment + + call config_finish ; Update DOS with the information + ; obtained from loading the resident + ; drivers. + mov ah,MS_DRV_SET ; Select the Default Drive + mov dl,init_drv ; passed to us by the BIOS + int DOS_INT + + mov ah,MS_F_DMAOFF ; Initialise the DMA address for + mov dx,offset search_state ; the Search First State data + int DOS_INT + + mov al,init_drv ; get the boot drive then check + test init_flags,INIT_COMSPEC ; flags to see if this is the + jz config_s05 ; default COMSPEC drive. + mov al,comspec_drv + +config_s05: + add shell,al ; update the drive letter of shell + add shell_drv,al ; and the reload path + + call open_stdaux ; Open STDAUX as internal handle #0 + call open_stdcon ; Open Standard CON Devices as #1 + mov ah,MS_X_CLOSE ; now close AUX again + mov bx,STDAUX ; for CONFIG processing + int DOS_INT + ret + + +; +; Relocate the DOS CODE from high memory to immediately above +; the device drivers, buffers etc. Then call the DOS_CLEANUP code +; so that any self segment pointers maintained in the DOS DATA +; can be updated. Then free all the unused memory and reopen the +; standard devices. +; +config_end: + push es + mov al,last_drv ; get lastdrive value + les bx,func52_ptr + cmp al,es:F52_PHYDRV[bx] ; less than the # of Physical drives ? + ja config_end10 + mov al,es:F52_PHYDRV[bx] ; ensure minimum of # physical drives +config_end10: + mov es:F52_LASTDRV[bx],al ; set # of drives installed + mov cl,4 ; we will be converting byte-paras + mov ah,LDT_LEN ; we need this many bytes per drive + mul ah ; *lastdrive + add ax,15 ; round LDT's size up to para + shr ax,cl + mov dl,'L' ; allocate LDT's + call alloc_instseg ; Allocate memory AX is destination + mov es:F52_PATHOFF[bx],0 ; point at the LDT's + mov es:F52_PATHSEG[bx],ax ; save seg we just allocated + pop es + + call setup_ldt ; initialise LDT structures + + call setup_stacks ; allocate stacks + + call relocate_system ; relocate system as requested + + push es ; Free all of the unused memory + mov es,mem_current_base ; ES: Base Allocated Memory + mov bx,mem_current ; Get the currently allocated memory + sub bx,mem_current_base ; and subtract mem_current_base to + mov ah,MS_M_SETBLOCK ; give the number of paragraphs used + int DOS_INT ; and modify block accordingly + +; Kludge - if the CONFIG file has had a line of the form INSTALL= to load a TSR +; then that TSR will have inherited the handles, so bumping the open count, but +; the func 31 exit leaves all these files open. As a result we will get the +; wrong internal file numbers unless we force complete closure. So we keep +; trying to close each internal handle until we get an error. + + mov ah,MS_P_GETPSP + int DOS_INT ; get current PSP + mov es,bx + mov cx,PSP_XFNMAX ; Close all the standard handles + les di,PSP_XFTPTR ; and then reopen them in case a + mov bx,0 ; dynamicly loadable device has +cfg_e10: ; replaced the BIOS driver + mov dl,es:[di+bx] ; save old internal handle + mov ah,MS_X_CLOSE + int DOS_INT ; try and close this handle + mov es:[di+bx],dl ; put the internal handle back + jnc cfg_e10 ; and try and close it again + mov es:byte ptr [di+bx],0ffh + inc bx ; mark as closed and try next handle + loop cfg_e10 + pop es +;; jmps open_std + +open_std: + call open_stdaux ; open AUX device as STDAUX + call open_stdcon ; now STDIN, STDOUT, STDERR +; jmp open_stdprn ; finally STDPRN + +open_stdprn: + mov ax,(MS_X_OPEN * 256) + 1 + mov dx,offset printer ; Open the PRN device + int DOS_INT + jc open_sp10 ; No PRN device + cmp ax,STDPRN ; If all the previous Opens were + jz open_sp10 ; successful then this is STDPRN + mov bx,ax ; otherwise force this to STDPRN + mov cx,STDPRN + mov ah,MS_X_DUP2 + int DOS_INT + mov ah,MS_X_CLOSE + int DOS_INT +open_sp10: + ret + +open_stdcon: + mov ax,(MS_X_OPEN * 256) + 2 + mov dx,offset console ; Open the CON device + int DOS_INT + jc open_sc10 ; No CON device + mov bx,ax ; First Open should be STDIN + mov cx,STDOUT ; Force Duplicate to STDOUT + mov ah,MS_X_DUP2 + int DOS_INT + mov cx,STDERR ; Then Force Duplicate to STDERR + mov ah,MS_X_DUP2 + int DOS_INT +open_sc10: + ret + +open_stdaux: + mov ax,(MS_X_OPEN * 256) + 2 + mov dx,offset auxilary ; Open the AUX device + int DOS_INT ; to get internal handle 0 + jc open_sa10 ; No AUX device + mov bx,ax ; Force DUP to STDAUX + mov cx,STDAUX + mov ah,MS_X_DUP2 + int DOS_INT + mov ah,MS_X_CLOSE + int DOS_INT +open_sa10: + ret + + +eject +relocate_system: + push ds ! push es + cmp dos_target_seg,0FFFFh ; is the OS going high ? + jne relocate_system10 + call SetupHMA ; make sure HMA chain is established + xor cx,cx + xchg cx,systemHMA ; free up any space reserved for the OS + call FreeHMA + call ReserveCommandHMA ; reserve space for COMMAND.COM +relocate_system10: + call reloc_bios ; move down relocatable drivers + call reloc_dos ; move DOS above drivers if RAM based + xor cx,cx + xchg cx,commandHMA + call FreeHMA ; return command.com HMA space to pool + cli + mov ds,dos_dseg ; DS -> DOS data segment + callf cs:dos_init ; (in case of CS relative fixups) + sti + pop es ! pop ds + ret + +eject +reloc_dos: ; move DOS down to just above drivers +;---------- + push ds + push es + test init_flags,INIT_ROMCODE ; Run the DOS code in ROM + jz $+5 ! jmp reloc_dos90 ; at CURRENT_DOS - No Code Reloc + mov es,current_dos + mov cx,es:DOS_CODE ; get DOS code size in bytes + mov ax,dos_target_seg ; get DOS target + cmp ax,0FFFFh ; it it seg FFFF ? + jne reloc_dos10 + mov es,current_dos + mov dx,es:DOS_OFFSET + call AllocHMA ; allocate CX bytes, offset < DX + jnc reloc_dos50 ; if we can use high memory + xor ax,ax ; can't, so try auto-allocation +reloc_dos10: + test ax,ax ; has a specific address been + jnz reloc_dos40 ; specified ? + push cx ; save DOS code size + xchg ax,cx + mov cl,4 + shr ax,cl ; convert to paragraphs + pop cx + cmp hidos,0 ; do we want to relocate DOS ? + je reloc_dos20 ; no, allocate conventionally + call alloc_upper ; else allocate space for the DOS + jnc reloc_dos40 ; in upper memory if possible +reloc_dos20: + mov es,current_dos ; if conventional memory we + mov ax,es:INIT_CODE ; can discard INIT code + cmp history_flg,0 ; is history enabled ? + jne reloc_dos30 + mov ax,es:HISTORY_CODE ; no, discard history code as well +reloc_dos30: + push cx + add ax,15 + mov cl,4 ; convert to paragraphs + shr ax,cl + pop cx + call alloc_seg_with_padding ; allocate in conventional memory +reloc_dos40: + xchg ax,dx ; save segment address + mov es,current_dos ; point at code + mov ax,es:DOS_OFFSET ; get offset of code start + xor di,di + mov es,dx ; ES:DI -> destination address + push cx ; save DOS size + mov cl,4 + shr ax,cl ; AX = header size in para's + sub dx,ax ; adjust DOS segment accordingly + pop cx ; CX = DOS size in bytes +reloc_dos50: +; At this point +; CX = # bytes to move +; ES:DI -> destination +; DX = segment to fixup +; + mov dos_cseg,dx ; new code segment for DOS + mov ds,current_dos ; DS -> DOS code + xor si,si + shr cx,1 ; CX = # of words in DOS + rep movsw ; copy DOS down + +reloc_dos90: ; fixups performed + pop es + pop ds + ret + + + + Public HookInt2F + +HookInt2F: +;--------- +; Hook Int 2F during device driver initialisation so we can intercept +; some broadcasts +; On Entry: +; None (beware DS/ES can be anything) +; On Exit: +; None (All regs preserved) +; + push es + push ax + push bx + les bx,cs:drdos_ptr + mov bx,es:DRDOS_INT2F[bx] ; ES:BX -> Int 2F hooks + mov ax,offset Int2FHandler + xchg ax,es:4[bx] ; get Int 2F offset + mov cs:int2FOff,ax + mov ax,cs + xchg ax,es:6[bx] ; get Int 2F segment + mov cs:int2FSeg,ax + pop bx + pop ax + pop es + ret + + Public UnhookInt2F + +UnhookInt2F: +;----------- +; Device driver initialisation has finished, so unhook from Int 2F +; On Entry: +; None (beware DS/ES can be anything) +; On Exit: +; None (All regs preserved) +; + push es + push ax + push bx + les bx,cs:drdos_ptr + mov bx,es:DRDOS_INT2F[bx] ; ES:BX -> Int 2F hooks + mov ax,cs:int2FOff + mov es:4[bx],ax ; restore Int 2F offset + mov ax,cs:int2FSeg + mov es:6[bx],ax ; restore Int 2F segment + pop bx + pop ax + pop es + ret + + +; During device driver init we provide some services on Int 2F +; eg. 12FF for EMM386.SYS and 4A01/4A02 for Windows HIMEM.SYS + +Int2FHandler: +;------------ +; On Entry: +; callers DS on stack +; On Exit: +; if not handled pass on to BIOS, callers DS on stack, all regs preserved +; + pop ds ; pop DS from stack + cmp ax,4A01h ; Query Free HMA Space ? + je HMAQueryFree + cmp ax,4A02h ; Allocate HMA Space ? + je HMAAlloc + cmp ax,12FFh ; is it a relocation service ? + jne OldInt2F + sti ; if we RETF don't leave IF disabled + cmp bx,9 ; register upper memory link + je DOSUpperMemoryRoot + cmp bx,1 ; Relocate BDOS + jb DOSQuerySize ; what's the size of DOS + je DOSRelocate ; where to put it + cmp bx,3 ; Relocate BIOS + jb BIOSQuerySize ; what's the size of BIOS + je BIOSRelocate ; where to put it + +OldInt2F: + push ds ; DS on stack as expected + db JMPF_OPCODE +int2FOff dw 0 +int2FSeg dw 0 + + +; Enquire DOS size +DOSQuerySize: +;------------ +; On Entry: +; None +; On Exit: +; AX = 0 +; DX = DOS Size in para's +; + mov dx,cs:dosCodeParaSize ; DX = para's required for DOS code + jmps RelocExit + +; Relocate DOS +DOSRelocate: +;----------- +; On Entry: +; DX = para to reloacte to (FFFF=HMA) +; On Exit: +; AX = 0 +; + mov cs:dos_target_seg,dx ; save where + jmps RelocExit + + +; Enquire BIOS size +BIOSQuerySize: +;------------- +; On Entry: +; None +; On Exit: +; AX = 0 +; DX = BIOS Size in para's +; + mov dx,cs:rcode_len ; DX = bytes required for BIOS code + add dx,15 + mov cl,4 + shr dx,cl ; DX para's required + jmps RelocExit + +; Relocate BIOS +BIOSRelocate: +;------------ +; On Entry: +; DX = para to reloacte to (FFFF=HMA) +; On Exit: +; AX = 0 +; + mov cs:bios_target_seg,dx ; save where +; jmps RelocExit + +RelocExit: + xor ax,ax ; indicate success + retf 2 + + +DOSUpperMemoryRoot: +;------------------ + les bx,cs:drdos_ptr + mov es:DRDOS_DMD_UPPER[bx],dx ; remember upper memory link +if DOS5 + les bx,cs:func52_ptr + mov es:F52_DMD_UPPER[bx],dx ; remember upper memory link +endif + xor ax,ax + retf 2 + +HMAAlloc: +;-------- +; On Entry: +; BX = # bytes to allocate +; On Exit: +; ES:DI -> start of allocated block +; BX trashed +; + push ds + push ax + push cx + push dx + push si + push bp + push cs ! pop ds ; establish data seg + mov cx,bx ; CX = bytes wanted + mov dx,0FFFFh ; anywhere is OK + call AllocHMA ; ES:DI -> allocated data + pop bp + pop si + pop dx + pop cx + pop ax + pop ds + iret + + +HMAQueryFree: +;------------ +; On Entry: +; None +; On Exit: +; BX = Size of block remaining (0 if no HMA) +; ES:DI -> start of available HMA (FFFF:FFFF if no HMA) +; + push ds + push ax + push cx + push dx + push si + push bp + push cs ! pop ds ; establish data seg + call SetupHMA ; allocate the HMA for OS use + les bx,cs:drdos_ptr + mov di,es:DRDOS_HIMEM_ROOT[bx] + mov ax,0FFFFh ; get offset of HMA entry + mov es,ax + test di,di ; do we have a himem root ? + jz HMAQueryFree10 ; no, return failure + mov bx,es:2[di] ; BX = size of region + mov ax,di ; para align the base + add ax,15 ; because the allocation will + and ax,not 15 + sub ax,di ; AX bytes left in the para + add di,ax ; bias the starting location + sub bx,ax ; that many less available + ja HMAQueryFree20 ; if non-zero, return it +HMAQueryFree10: + xor bx,bx ; BX = zero on failure + mov di,0FFFFh ; ES:DI -> FFFF:FFFF +HMAQueryFree20: + pop bp + pop si + pop dx + pop cx + pop ax + pop ds + iret + + + Public AllocHMA + +AllocHMA: +;-------- +; On Entry: +; CX = bytes to allocate +; DX = offset of allocation +; On Exit: +; CY set if no can do and ES:DI = FFFF:FFFF +; else +; ES:DI -> memory allocated (para aligned) +; CX preserved +; DX = segment to fixup +; + les bx,cs:drdos_ptr + mov di,es:DRDOS_HIMEM_ROOT[bx] + test di,di ; have we a HIMEM chain ? + jz AllocHMA20 + cmp di,dx ; low enough for us + ja AllocHMA20 + mov ax,0FFFFh ; relocate to magic segment + mov es,ax ; lets examine high memory + mov ax,es:2[di] ; get size of himem entry + mov si,es:[di] ; and get himem link + mov bx,di + add bx,15 + and bx,not 15 ; BX is now para aligned + sub bx,di ; BX is bytes left in para + sub ax,bx ; so we only have this much + jc AllocHMA20 ; less than a para ? + add di,15 ; para align the base, dropping + and di,not 15 ; non-aligned bit on floor + cmp ax,cx ; is himem entry big enough ? + jb AllocHMA20 ; no, allocate from 1st MByte + je AllocHMA10 ; just made it! + sub ax,cx ; how much is left + cmp ax,2*WORD ; is it to small to keep ? + jb AllocHMA10 ; no, discard the remainder + mov bx,di ; point to new entry + add bx,cx ; this many byte up + mov es:[bx],si ; fill in link field + mov es:2[bx],ax ; and length + mov si,bx ; make this new root +AllocHMA10: + push cx ; save length of CODE + push dx ; and offset of CODE + les bx,cs:drdos_ptr + mov es:DRDOS_HIMEM_ROOT[bx],si + pop ax ; AX = offset of CODE + mov cl,4 + shr ax,cl ; make it paras + mov dx,0ffffh + mov es,dx ; ES:DI -> destination of CODE + mov dx,di + mov cl,4 + shr dx,cl ; DX = offset from FFFF in para's + dec dx ; DX = offset from 10000 + sub dx,ax ; DX = fixup segment + pop cx ; CX = bytes to move + clc ; made it! + ret + +AllocHMA20: + mov di,0FFFFh ; set ES:DI = FFFF:FFFF + mov es,di + stc ; can't do it + ret + + Public SetupHMA + +SetupHMA: +;-------- +; We have a client for the high memory area at segment FFFF +; We should try and setup a high memory free chain +; XMS only supports allocation of the complete area, so try and grab +; it all and do our own sub-allocations within it. +; + push es + les bx,cs:drdos_ptr + cmp es:DRDOS_HIMEM_ROOT[bx],0; do we already have a chain ? + jnz SetupHMA10 ; if so skip XMS allocation + mov ax,4300h ; check for XMS installation + int 2fh + cmp al,80h + jne SetupHMA20 + mov ax,4310h ; get address of XMS driver + int 2fh + mov word ptr xms_driver,bx + mov word ptr xms_driver+2,es + mov ah,0 ; version number check + callf xms_driver + cmp dx,1 ; does HiMem exist ? + jne SetupHMA20 + mov ah,1 ; allocate whole HiMem + mov dx,0ffffh + callf xms_driver + cmp ax,1 ; did we succeed ? + jne SetupHMA20 + mov ah,3 ; enable a20 gate + callf xms_driver + cmp ax,1 ; did we succeed ? + jne SetupHMA20 + les bx,cs:drdos_ptr + mov es:DRDOS_HIMEM_ROOT[bx],COMMAND_BASE + mov ax,0FFFFh ; one entry of FFF0 bytes covers + mov es,ax ; the complete HMA + inc ax + mov es:word ptr .COMMAND_BASE,ax + mov es:word ptr .COMMAND_BASE+2,-COMMAND_BASE + mov di,10h ; copy a dummy VDISK header + mov si,offset dummyVDISK + mov cx,10h + rep movsw ; copy up 0x20 bytes + push ds ; now fixup JMPF in hi-memory for CALL5 + mov ds,ax ; link for PC-NFS + mov si,4*30h ; DS:SI -> Int 30 vector + lea di,10h[si] ; ES:DI -> himem alias + movsw ! movsw ! movsb ; copy the JMPF + pop ds +SetupHMA10: + les bx,cs:drdos_ptr ; private data area in ES:BX + mov dx,COMMAND_BASE + cmp dx,es:DRDOS_HIMEM_ROOT[bx] + jne SetupHMA20 ; should we be reserving space for OS? + mov cx,systemSize ; we should reserve this much + call ReserveHMA ; for the OS in the HMA + jc SetupHMA20 + mov systemHMA,ax ; save for re-use +SetupHMA20: + pop es + ret + + + Public alloc_instseg + +alloc_instseg: +; allocate AX paragraphs for data that will have to be instanced during +; multitasking. if Vladivar kernel available ask that, or else just +; try for normal upper memory + push ax + push bx ; save registers + push cx + mov cx,F_Version ; is the multi-tasker loaded ? + mov ax,OS386_FUNC + int OS386_INT + int 2Fh ; check for Vladivar + test cx,cx ; CX=0 if it's there + pop cx + pop bx + pop ax + jnz alloc_hiseg ; no, allocate normally + push ax + push bx + push cx + push dx + mov dx,ax ; DX = paragraphs required + mov cx,F_RealAllocI ; ask nicely for memory + mov ax,OS386_FUNC + int OS386_INT + pop dx + pop cx + pop bx + jc alloc_intseg10 ; did we get any ? + add sp,WORD + clc ; we've done it !! + ret + +alloc_intseg10: + pop ax ; we didn't manage it... +; jmp alloc_hiseg + + Public alloc_hiseg +alloc_hiseg: +; allocate AX paragraphs in high memory if possible, otherwise allocate +; it in conventional memory + cmp hidos,0 ; do we want to relocate DOS ? + je alloc_seg ; no, allocate conventionally + call alloc_upper ; try to allocate some upper memory + jc alloc_seg ; can't, so allocate conventional + ret ; else return address of allocated mem + +alloc_seg_with_padding: +; On Entry: +; AX = para's required +; DX = minimum acceptable offset +; On Exit: +; AX = base para +; +; If gate A20 is enabled we can't use negative offset's for DOS/BIOS so +; we pad conventional memory to avoid this. Avoid seg=0 while here. + push cx + push dx + add dx,15+16 ; DX is the offset we will be using + mov cl,4 ; so make sure base is high enough + shr dx,cl ; convert "offset" to a segment value + cmp dx,mem_current ; make sure we don't generate a + jbe alloc_seg_nopad ; negative segement value as this + mov mem_current,dx ; will crash if a20 enabled +alloc_seg_nopad: ; pad if necessary + mov dl,'M' ; allocate for DOS + call alloc_seg ; now we can allocate OK + pop dx + pop cx + ret + + Public alloc_seg +alloc_seg: +;--------- +; On Entry: +; AX = para's required +; DL = subsegment type +; On Exit: +; AX = base para +; + push ds + push cx + mov cx,ax ; remember how much was wanted + inc ax ; allow an extra para for a header + add ax,mem_current ; Return a pointer to AX paragraphs + cmp ax,mem_max ; of memory to the calling routine. + jae alloc_s10 + xchg ax,mem_current + mov ds,ax ; DS:0 -> header + inc ax ; AX:0 -> buffer + mov ds:DMD_ID,dl ; remember the type + mov ds:DMD_PSP,ax ; owner = itself + mov ds:DMD_LEN,cx ; size in para + xor cx,cx ; zero rest for cosmetic reasons + mov ds:word ptr DMD_NAME-3,cx + mov ds:word ptr DMD_NAME-2,cx + mov ds:word ptr DMD_NAME,'S'+256*'D' + mov ds:word ptr DMD_NAME+2,cx + mov ds:word ptr DMD_NAME+4,cx + mov ds:word ptr DMD_NAME+6,cx + pop cx + pop ds + ret + +alloc_s10: + hlt ; ##jc## + jmps alloc_s10 + +alloc_upper: +;----------- +; On Entry: +; AX = paragraphs required +; On Exit: +; CY clear: AX = paragraphs address of allocated memory +; CY set: cannot allocate memory (All regs preserved) +; + push bx + push ax ; save para required + cmp himem_base,0 ; we have already allocated some ? + je alloc_upper10 ; nothing to grow, allocate new block + mov bx,himem_size ; himem was this big + add bx,ax ; try and extend it + push es + mov es,himem_base ; point at existing himem + mov ah,MS_M_SETBLOCK ; and try and set to new size + int DOS_INT + pop es + jc alloc_upper10 ; can't grow, so allocate new block + mov ax,himem_base + add ax,himem_size ; return seg above old alloc + pop bx ; recover para required + add himem_size,bx ; add into himem size + pop bx + clc ; success.. + ret ; return AX = seg + +alloc_upper10: + mov ax,(MS_M_STRATEGY*256)+1; set allocation strategy + mov bl,41h ; to best fit, high only + int DOS_INT + pop bx ! push bx ; recover para required in BX + mov ah, MS_M_ALLOC ; and try to allocate them + int DOS_INT + pushf ! push ax ; save CF and possible address + mov ax,(MS_M_STRATEGY*256)+1; set allocation strategy + mov bl,0 ; to first fit + int DOS_INT + pop ax ! popf ; restore CF and possible address + jc alloc_upper20 ; can't allocate, use conventional + cmp ax,mem_size ; is it from upper memory ? + ja alloc_upper15 ; yes, we can use it + push es ; it's conventional, free it up + mov es,ax ; seg address in ES + mov ah,MS_M_FREE + int DOS_INT ; free up this memory + pop es + jmps alloc_upper20 ; try again with XMS + +alloc_upper15: + mov himem_base,ax ; save base value + pop himem_size ; save size + pop bx ; and return seg in AX + clc ; success.. + ret + +alloc_upper20: + pop ax + pop bx ; restore regs + push ds ! push es + push bx ! push cx ! push dx ! push si ! push di ! push bp + push ax ; save allocation size + mov ax,4300h ; check for XMS installation + int 2fh + cmp al,80h + jne alloc_upper30 + mov ax,4310h ; get address of XMS driver + int 2fh + mov word ptr xms_driver,bx + mov word ptr xms_driver+2,es + pop dx ! push dx ; DX = allocation size + mov ah,10h ; allocate upper memory block + callf xms_driver + cmp ax,1 ; did we succeed ? + jne alloc_upper30 + pop ax ; recover allocation size + mov ax,bx ; return para address of himem + pop bp ! pop di ! pop si ! pop dx ! pop cx ! pop bx + pop es ! pop ds + clc ; success + ret + +alloc_upper30: + pop ax ; recover allocation size + pop bp ! pop di ! pop si ! pop dx ! pop cx ! pop bx + pop es ! pop ds + stc ; failure.... + ret + + +mark_system_memory: +;------------------ +; ensure any memory we have allocated is owned by PSP 0008, a magic value +; used to indicate system memory + push es + les bx,func52_ptr ; get internal data in ES:BX + mov es,es:F52_DMDROOT[bx] ; get 1st DMD entry + mov ah,MS_P_GETPSP + int DOS_INT ; get our PSP in BX +mark_sm10: + cmp es:DMD_ID,'M' + je mark_sm20 ; check we have a valid DMD + cmp es:DMD_ID,'Z' + jne mark_sm50 ; stop if we don't +mark_sm20: + cmp bx,es:DMD_PSP ; is it ours ?? + jne mark_sm30 + mov es:DMD_PSP,0008 ; mark as system +mark_sm30: + cmp es:DMD_PSP,0008 ; if system mark as SC + jne mark_sm40 + xor ax,ax ; zero rest for cosmetic reasons + mov ds:word ptr DMD_NAME-3,ax + mov ds:word ptr DMD_NAME-2,ax + mov ds:word ptr DMD_NAME,'S'+256*'C' + mov ds:word ptr DMD_NAME+2,ax + mov ds:word ptr DMD_NAME+4,ax + mov ds:word ptr DMD_NAME+6,ax +mark_sm40: + cmp es:DMD_ID,'Z' ; is it the last DMD ? + je mark_sm50 ; then stop + mov ax,es + inc ax ; skip DMD header and add + add ax,DMD_LEN ; length to find next DMD + mov es,ax + jmps mark_sm10 ; now go and look at that +mark_sm50: + pop es + ret + +; Relocate the BIOS code from top of memory +reloc_bios: + mov dx,rcode_offset + mov cx,rcode_len ; we need to relocate this much + test cx,cx ; do we need to move anything ? + jnz reloc_bios10 + ret +reloc_bios10: + add cx,15 ; round rcode size up to a para + and cx,not 15 + mov ax,bios_target_seg ; where do we go + test ax,ax + jz reloc_bios20 ; zero - do it ourselves + inc ax ; FFFF - unlikely as it's not + jz reloc_bios25 ; currently supported + dec ax ; else we've been given a seg + jmps reloc_bios40 +reloc_bios20: + cmp dos_target_seg,0FFFFh ; if DOS goes up, so does BIOS + jne reloc_bios30 +reloc_bios25: + call AllocHMA ; in HIGH memory + jnc reloc_bios50 +reloc_bios30: + mov ax,cx ; allocate conventionally + shr ax,1 ! shr ax,1 ; in para's of course + shr ax,1 ! shr ax,1 + cmp hidos,0 ; do we want to relocate DOS ? + je reloc_bios35 ; no, allocate conventionally + call alloc_upper ; try to allocate some upper memory + jnc reloc_bios40 ; can't, so allocate conventional +reloc_bios35: ; padding out if required + call alloc_seg_with_padding +reloc_bios40: + mov es,ax + xor di,di ; ES:DI -> destination + shr dx,1 ! shr dx,1 ; convert offset to para's + shr dx,1 ! shr dx,1 + sub ax,dx ; bias segment appropriately + xchg ax,dx ; and have in DX +reloc_bios50: + push es + push cx + push di + + push ds + mov si,rcode_offset + mov ds,rcode_seg + rep movsb + pop ds + mov rcode_seg,dx ; new RCODE location + + call dd_fixup ; fixup any device drivers + + pop di + pop cx + pop es + ret + + +; +; The following code performs the fixups necessary for RELOCATABLE executable +; internal device drivers. + +dd_fixup: +; On Entry: +; None +; On Exit: +; None + + push es + mov di,rcode_seg ; fixup to this segment + mov si,rcode_fixups ; get fixup table + test si,si ; is there one ? + jz dd_fixup20 + mov es,bios_seg +dd_fixup10: + lodsw ; get a fixup offset + test ax,ax ; last of the fixups ? + jz dd_fixup20 + xchg ax,di ; point to the fixup + stosw ; do the fixup + xchg ax,di ; save segment again + jmps dd_fixup10 +dd_fixup20: + pop es + ret + + +ReserveOSHMA: +;------------ +; reserve space in HMA for OS +; On Entry: +; None +; On Exit: +; None +; + +ReserveCommandHMA: +;---------------- +; reserve space in HMA for COMMAND.COM +; On Entry: +; None +; On Exit: +; None +; + cmp commandHMA,0 ; been here already ?? + jne ReserveCommandHMA10 + mov cx,COMMAND_SIZE + mov dx,COMMAND_BASE + call ReserveHMA ; reserve the space in HMA + jc ReserveCommandHMA10 ; if we can + mov commandHMA,ax ; save for re-use +ReserveCommandHMA10: + ret + +ReserveHMA: +;---------- +; reserve some space in the HMA +; On Entry: +; CX = size require +; DX = maximum offset acceptable +; On Exit: +; AX = offset of reserved space +; + push es + call AllocHMA ; allocate space in HIGH memory + jc ReserveHMA10 + mov es:word ptr [di],0 ; no link, it's this big + mov es:word ptr 2[di],cx + mov bx,es + mov ax,0FFFFh + sub ax,bx ; AX = para offset adjustment required + mov cl,4 + shl ax,cl ; convert to byte offset + add ax,di ; AX = offset from FFFF:0 +ReserveHMA10: + pop es + ret + + +FreeHMA: +;------- +; Return reserved HMA space to pool +; On Entry: +; CX = offset of HMA block to relink (0 = noblock) +; On Exit: +; None +; + jcxz free_himem10 ; no block, don't recycle + push es + push cx ; save offset + les bx,cs:drdos_ptr + pop ax ; recover offset + mov di,ax ; remember offset for later + xchg ax,es:DRDOS_HIMEM_ROOT[bx]; become new head of HMA + mov bx,0FFFFh + mov es,bx ; point ES:DI at our section + stosw ; chain on rest of HMA + pop es +free_himem10: + ret + + +rploader: +;-------- +; On Entry: +; DX = phase code +; On Exit: +; None, All regs preserved + push es + push ax + push bx + push cx + push dx + mov ax,rpl_off ; do we have an RPL sitting on + or ax,rpl_seg ; Int 13h + jz rploader10 + mov ax,12ffh ; magic cleanup call to RPL + mov bx,5 ; to do any tidy ups it wishes + xor cx,cx ; following resident BIOS + mov dx,1 ; initialisation + pushf + cli + callf rpl_entry ; fake an INT +rploader10: + pop dx + pop cx + pop bx + pop ax + pop es + ret + + Public Verify386 + +Verify386: +;--------- +; On Entry: +; None +; On Exit: +; CY clear if 386 or above +; + push sp ; really old CPU's inc SP + pop ax ; before pushing + cmp ax,sp ; newer ones push original SP + jne Verify386fail + mov ax,3000h ; now try to set IOPL = 3 + push ax + popf + pushf + pop bx + and ax,bx ; any IOPL bits set ? + jz Verify386fail +; clc ; it's at least a 386 + ret +Verify386fail: + stc ; it's not a 386 + ret + + +INITDATA dseg 'INITDATA' + + +include initmsgs.def ; Include TFT Header File + + + extrn history_flg:byte + extrn next_drv:byte + extrn dev_count:byte + +; +; PUBLIC Variables which are initialised by the BIOS before the +; BIOSINIT code has been executed. +; +data_start rb 0 ; used to para-align PSP & ENV + + Public func52_ptr +func52_ptr rd 0 ; address of internal BDOS variables +func52_off dw 0 ; offset " " " +func52_seg dw 0 ; segment " " " + + Public drdos_ptr +drdos_ptr rd 0 ; address of internal BDOS variables +drdos_off dw 0 ; offset " " " +drdos_seg dw 0 ; segment " " " + + + Public res_ddsc_ptr +res_ddsc_ptr rd 0 +res_ddsc_off dw 0 +res_ddsc_seg dw 0 + + Public rcode_offset, rcode_seg, icode_len, rcode_len, rcode_fixups + +rcode_offset dw 0 ; current offset of relocated code +rcode_seg dw 0 ; current segment of relocated code +icode_len dw 0 ; initial size of relocated code +rcode_len dw 0 ; final size of relocated code +rcode_fixups dw 0 ; offset of rcode fixup table + + Public current_dos +current_dos dw 0 ; Current Segment Address of DOS Code + + Public dos_target_seg, bios_target_seg +dos_target_seg dw 0 ; target address for DOS relocation +bios_target_seg dw 0 ; 0000 - auto-relocate + ; FFFF - high memory (not allocated) + ; xxxx - driver allocated address + +dosCodeParaSize dw 0 ; Size of DOS code in para's + +systemSize dw COMMAND_SIZE ; BIOS+DOS code sizes are added to + ; give total size to reserve in HMA + +systemHMA dw 0 ; offset of area in HMA reserved + ; for SYSTEM (BIOS/DOS/COMMAND) +commandHMA dw 0 ; offset of area in HMA reserved + ; for COMMAND.COM + + + Public device_root +device_root rd 1 ; Root of Resident Device driver Chain + + Public mem_size, ext_mem_size, comspec_drv + Public init_flags, init_drv + +mem_size dw 0 ; Total Memory Size (in Paragraphs) +ext_mem_size dw 0 ; Total Extended Memory Size (in KB.) +init_flags dw 0 ; BIOS INIT Flags +init_drv db 0 ; Boot Drive (A is 0 .....) +comspec_drv db 0 ; Default COMSPEC Drive + + Public num_stacks, stack_size + +num_stacks dw DEF_NUM_STACKS +stack_size dw DEF_SIZE_STACK + + Public num_files, num_fcbs, num_fopen + Public country_code, code_page + +num_files dw DEF_NUM_FILES ; # of file handles +num_fcbs dw DEF_NUM_FCBS ; # of fcb file handles +num_fopen dw -1 ; "unset" value for fast open +country_code dw DEF_COUNTRY ; Country Code +code_page dw DEF_CODEPAGE ; Code Page + + Public dos_name +IF DRDOS35 +dos_name db 'DRBDOS SYS',0 +ELSE +dos_name db 'IBMDOS COM',0 ; default DOS filename +ENDIF + +rpl_name db 'RPLOADER' + +rpl_entry rd 0 ; remember RPL entry point for +rpl_off dw 0 ; startup broadcasts +rpl_seg dw 0 + +eject +; +; Internal variables used by the BIOSINIT code +; + Public bios_seg +bios rd 0 ; Far pointer to the BIOS Cleanup +bios_offset rw 1 ; routines. +bios_seg rw 1 + + Public init_dseg +init_dseg dw 0 ; Init data segment + + Public dos_dseg +dos_dseg dw 0 ; DOS Data Segment Address + + Public mem_current_base, mem_current, mem_max +mem_first_base rw 1 ; Base of First Allocated Memory +mem_current_base rw 1 ; Base of Current Allocated Memory +mem_current rw 1 ; Next Free Paragraph +mem_max rw 1 ; Last available Paragraph + + +dos_init rd 0 ; DOS Initialization Code +dos_coff dw 0 ; DOS Init Code Offset +dos_cseg rw 1 ; DOS Init Code Segment + +free_seg rw 1 ; First available paragraph. + +xms_driver rd 1 ; address of himem driver + + Public hidos +hidos db 0 ; set true if HIDOS requested +himem_base dw 0 ; base of HIMEM seg allocations +himem_size dw 0 ; length of HIMEM seg allocations + + Public last_drv + +last_drv db 5 ; default is "E:" + +console db 'CON',0 ; Default Console Device +printer db 'PRN',0 ; Default Printer Device +auxilary db 'AUX',0 ; Default Auxilary Device + +idle_dev db '$IDLE$',0 ; Idle Device Name +idle_off rw 1 ; Idle Data Area Offset +idle_seg rw 1 ; Idle Data Area Segment + +dummy_fcb db 0,' ' + +exec_env dw 0 ; Environment Segment +exec_cloff dw shell_cline ; Command Line Offset +exec_clseg dw 0 ; Command Line Segment + dw dummy_fcb +exec_fcb1seg dw 0 ; FCB 1 Offset and Segment + dw dummy_fcb +exec_fcb2seg dw 0 ; FCB 2 Offset and Segment + rd 1 ; SS:SP + rd 1 ; CS:IP + + Public shell_cline +shell_cline db length shell_drv; Initial Command Line +shell_drv db 'A: /P' + db 0Dh + rb 126 - length shell_drv + +dummyVDISK db 0, 0, 0 ; jump instruction + db 'VDISK3.3' ; OEM name + dw 128 ; bytes per sector + db 1 ; sectors per allocation unit + dw 1 ; number of reserved sectors + db 1 ; number of FATs + dw 40 ; number of root directory entries + dw 512 ; total number of sectors + db 0FEh ; media descriptor byte + dw 6 ; sectors per FAT + dw 8 ; sectors per track + dw 1 ; number of heads + dw 0 ; number of hidden sectors + dw 1024+64 ; KB of extended memory used + +search_state rb 43 ; Search First/Next State + + rw 384 ; big stack for ASPI4DOS.SYS driver +stack rw 0 + + +INITPSP DSEG PARA 'INITDATA' + db 'Z' ; dummy DMD header + dw 0008h ; owner is system + dw 0010h ; length of PSP + rb 3 ; pad to 8 bytes + db 'DOS',0,0,0,0,0 ; name field (must be 8 bytes) +psp rb 16h ; Zero Fill PSP Header +parent_psp dw 0 ; parent, patched to itself + db 0FFh, 0FFh, 0FFh ; STDIN, STDOUT, STDERR + db 0FFh, 0FFh ; STDAUX, STDPRN + db 0FFh, 0FFh, 0FFh ; Remainder CLOSED + db 0FFh, 0FFh, 0FFh + db 0FFh, 0FFh, 0FFh + db 0FFh, 0FFh, 0FFh + db 0FFh, 0FFh, 0FFh + dw 0000 ; PSP Environment Pointer + dw 0000, 0000 ; DOS User SS:SP + dw 20 ; Maximum of 20 Handles + dw offset PSP_XFT ; Handle Table Offset +xftbl_seg dw 0 ; Handle Table Segment + rb offset PSP_VERSION - offset PSP_RES1 + Public dosVersion +dosVersion dw 7 ; DOS version is 7.0 + rb PSPILEN - offset PSP_VERSION - 2 + ; PAD to Partial PSP Size + +INITENV DSEG PARA 'INITDATA' + +shell_ask db 79 ; max len +shell_end db 0 ; end of the line + Public shell +shell db 'A:\COMMAND.COM', 0 + rb 80-length shell + +DATAEND DSEG PARA 'INITDATA' + + Public biosinit_end +biosinit_end rb 0 + + end diff --git a/IBMBIO/BIOSMSGS.ASM b/IBMBIO/BIOSMSGS.ASM new file mode 100644 index 0000000..d74aa36 --- /dev/null +++ b/IBMBIO/BIOSMSGS.ASM @@ -0,0 +1,36 @@ +NUL equ 0 +BS equ 8 +TAB equ 9 +LF equ 10 +CR equ 13 + +include BIOSGRPS.EQU + +CGROUP group RCODE + + +RCODE segment word public 'RCODE' + +; Source .TFT file: 'TMP1.$$$' + public _disk_msgA + public disk_msgA +disk_msgA label byte +_disk_msgA db CR, LF, "Insert diskette for drive ", NUL + public _disk_msgB + public disk_msgB +disk_msgB label byte +_disk_msgB db ": and", CR, LF, " strike any key when ready", CR, LF, LF, NUL + public _div_by_zero_msg + public div_by_zero_msg +div_by_zero_msg label byte +_div_by_zero_msg db CR, LF, "Divide Error", CR, LF, NUL + public _starting_dos_msg + public starting_dos_msg +starting_dos_msg label byte +_starting_dos_msg db CR, LF, "Starting DOS...", CR, LF, NUL + +RCODE ends + + + end + \ No newline at end of file diff --git a/IBMBIO/BIOSMSGS.DEF b/IBMBIO/BIOSMSGS.DEF new file mode 100644 index 0000000..898ab92 --- /dev/null +++ b/IBMBIO/BIOSMSGS.DEF @@ -0,0 +1,8 @@ + extrn _disk_msgA : byte + extrn disk_msgA : byte + extrn _disk_msgB : byte + extrn disk_msgB : byte + extrn _div_by_zero_msg : byte + extrn div_by_zero_msg : byte + extrn _starting_dos_msg : byte + extrn starting_dos_msg : byte diff --git a/IBMBIO/BIOSMSGS.H b/IBMBIO/BIOSMSGS.H new file mode 100644 index 0000000..ae9ec90 --- /dev/null +++ b/IBMBIO/BIOSMSGS.H @@ -0,0 +1,4 @@ +extern char near disk_msgA[]; +extern char near disk_msgB[]; +extern char near div_by_zero_msg[]; +extern char near starting_dos_msg[]; diff --git a/IBMBIO/BIOSSTUB.LIB b/IBMBIO/BIOSSTUB.LIB new file mode 100644 index 0000000000000000000000000000000000000000..132e656f798d9ca23dc9216b87a30b7111be48d1 GIT binary patch literal 1024 zcmeys%fP_Iz`)1=1r1yb98NC&!NDP+P8=PQK+zz_U|(GeGX+CElSBnWBVFIbB3%n} z!D(g;46LpZAwiBT&i*d0tid6U&fY98jvP6$NDhq(p?d;0su zJA1e~dowaH$}V67IsEY9%UwV(lz@Eza=){`pBu>iT(ok32H5>C@w%Va*+0}TBq%c8 zH7LkG2jMz47$P~VHE~RM^0FhP-JAl j8W#*`z5}KzPFOT3@-mkMya literal 0 HcmV?d00001 diff --git a/IBMBIO/BPB.EQU b/IBMBIO/BPB.EQU new file mode 100644 index 0000000..b9f16b4 --- /dev/null +++ b/IBMBIO/BPB.EQU @@ -0,0 +1,50 @@ +; File : $BPB.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; ENDLOG + +BPB struc +BPB_SECSIZ dw ? ; # of bytes per sector +BPB_ALLOCSIZ db ? ; # of sectors per allocation unit +BPB_FATADD dw ? ; # of reserved sectors (1) +BPB_NFATS db ? ; # of fats +BPB_DIRMAX dw ? ; # of directory entries +BPB_TOTSEC dw ? ; # of sectors total in image +BPB_FATID db ? ; holds a copy of the fat id byte +BPB_FATSEC dw ? ; # of sectors in a fat +BPB_SPT dw ? ; # of sectors per track +BPB_HEADS dw ? ; # of heads +BPB_HIDDEN dd ? ; disk offset (32 bit) +BPB_SIZE dd ? ; disk size (32 bit) +BPB_RESRVD2 db 6 dup (?) +BPB ends + +BPB_LENGTH equ size BPB diff --git a/IBMBIO/CHAR.DEF b/IBMBIO/CHAR.DEF new file mode 100644 index 0000000..82723db --- /dev/null +++ b/IBMBIO/CHAR.DEF @@ -0,0 +1,74 @@ +; File : $CHAR.DEF$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +;************************************************; +;* *; +;* Character Definitions *; +;* *; +;************************************************; + +CTLA equ 'A' - '@' +CTLB equ 'B' - '@' +CTLC equ 'C' - '@' +CTLD equ 'D' - '@' +CTLE equ 'E' - '@' +CTLF equ 'F' - '@' +CTLG equ 'G' - '@' +BELL equ 'G' - '@' +CTLH equ 'H' - '@' +CTLI equ 'I' - '@' +TAB equ 'I' - '@' +CTLJ equ 'J' - '@' +LF equ 'J' - '@' +CTLK equ 'K' - '@' +CTLM equ 'M' - '@' +CR equ 'M' - '@' +CTLP equ 'P' - '@' +CTLQ equ 'Q' - '@' +CTLR equ 'R' - '@' +CTLS equ 'S' - '@' +CTLT equ 'T' - '@' +CTLU equ 'U' - '@' +CTLV equ 'V' - '@' +CTLW equ 'W' - '@' +CTLX equ 'X' - '@' +CTLY equ 'Y' - '@' +CTLZ equ 'Z' - '@' +ESC equ '[' - '@' +CTLBS equ '\' - '@' +CTLUB equ '_' - '@' +CTLUP equ '^' - '@' +DEL equ 07Fh +RUBOUT equ DEL + +CTL equ '^' diff --git a/IBMBIO/CLOCK.ASM b/IBMBIO/CLOCK.ASM new file mode 100644 index 0000000..15a6a55 --- /dev/null +++ b/IBMBIO/CLOCK.ASM @@ -0,0 +1,467 @@ +; File : $CLOCK.ASM$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; CLOCK.ASM 1.12 93/07/22 19:43:10 +; switch over to REQUEST.EQU +; ENDLOG + + include BIOSGRPS.EQU + include DRMACROS.EQU ; standard DR macros + include IBMROS.EQU ; ROM BIOS equates + include REQUEST.EQU ; request header equates + include DRIVER.EQU ; device driver equates + +page +CGROUP group CODE, RCODE, RESUMECODE, ICODE + +CG equ offset CGROUP + +TIME struc +DAYS dw ? +MINUTES db ? +HOURS db ? +HUNDREDTHS db ? +SECONDS db ? +TIME ends + + Assume CS:CGROUP, DS:CGROUP, ES:Nothing, SS:Nothing + +CODE segment 'CODE' + + extrn endbios:word ; for device driver INIT function + extrn daycount:word + +; There are 1193180/65536 ticks per second, or 0E90Bh/10000h ticks per 5/100th. + +CONVERSION_FACTOR equ 0E90Bh + +CODE ends + +RCODE segment 'RCODE' + + extrn DataSegment:word + +monlen db 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + + + Public ClockTable + +ClockTable: + db 9 ; Last supported function + dw CG:dd_init ; 0-initialize driver + dw CG:dd_error ; 1-media change check (disks only) + dw CG:dd_error ; 2-build BPB (disks only) + dw CG:dd_error ; 3-IOCTL string input + dw CG:dd_input ; 4-input + dw CG:dd_error ; 5-nondestructive input (char only) + dw CG:dd_error ; 6-input status (char only) + dw CG:dd_error ; 7-input flush + dw CG:dd_output ; 8-output + dw CG:dd_output ; 9-output with verify + +page +driver proc near + +dd_error: ; used for all unsupported driver functions +;-------- + mov ax,RHS_ERROR+3 ; "invalid command" error + ret + +dd_input: ; 4-input +;-------- + les di,es:RH4_BUFFER[bx] ; ES:DI -> requested date/time buffer + call read_system_ticks ; read system tick counter + mov ax,daycount ; AX = date + stosw ; return date + push dx ; save low word of ticks + mov ax,5 + mul cx ; multiply high word of ticks by 5 + xchg ax,cx ; save result in CX + pop dx + mov ax,5 + mul dx ; multiply low word of tick by 5 + add dx,cx ; and add in high word + mov bx,CONVERSION_FACTOR + div bx ; convert to centi-secs + push ax ; save high word of result + xor ax,ax + div bx ; divide remainder + pop dx ; recover high word of result + ; giving us time in centi-secs + mov bx,60*100 ; BX = centi-secs/minute + div bx ; AX = # minutes + push dx ; save centi-secs remainder + cwd ; DX = 0 + mov bx,60+(256*100) ; BL = minutes/hour,BH = centi-secs/sec + div bl ; AL = hours, AH = minutes remainder + xchg al,ah + stosw ; return minutes then hours + pop ax ; recover centi-secs remainder + div bh ; AL = secs, AH = centi-secs remainder + xchg al,ah + stosw ; return centi-secs then secs + sub ax,ax + ret + + page + +dd_output: ; 8-output +;--------- + les si,es:RH4_BUFFER[bx] + +; First we'll convert the date & set the RTC if present: + + mov ax,es:DAYS[si] ; # of days since 1/1/1980 + mov daycount,ax + + mov dx,1980 ; get initial year +output1: + mov cx,365 ; assumed year size + test dl,3 ; test for leap years + jnz output2 ; skip if not a leap year + inc cx ; leap years have 366 days +output2: + cmp ax,cx ; more days than this year? + jb output3 ; skip if less - same year + sub ax,cx ; else date in future year + inc dx ; subtract from total, next year + jmps output1 ; check again + +output3: ; DX = binary year, AX = day in year + sub bx,bx ; start with January + sub cx,cx ; CH = 0 +output4: + mov cl,cs:monlen[bx] ; CX = # of days in next month + cmp cl,28 ; is it february ? + jne output5 + test dl,3 ; is it a leap year ? + jnz output5 + inc cx ; leap years have 29 days in february +output5: + cmp ax,cx ; remaining day count >= month length? + jb output6 ; skip if right month found + sub ax,cx ; else subtract days in that month + inc bx ; move on to next month + jmps output4 ; repeat until month found + +output6: ; DX = binary year + inc ax ; AX = day-1 => convert to day + inc bx ; BX = month-1 => convert to month + mov ah,bl ; high byte is month + call bin2bcd ; convert to month + + xchg ax,dx ; DL, DH = day, month of date + ; AX = binary year + + mov bl,100 + div bl ; AL = century, AH = year + xchg al,ah ; AH = century, AL = year + call bin2bcd ; convert AL, AH from binary to BCD + xchg ax,cx ; CL, CH = year, century for date + + mov ah,5 ; set real time clock date + int RTC_INT ; on AT, XT-286, PS/2, etc. + +; Now we'll convert the time & set the RTC if present + +; mov ah,es:HOURS[si] +; mov al,es:MINUTES[si] ; get binary hours & minutes + mov ax,es:word ptr MINUTES[si] + call bin2bcd ; convert to BCD values + xchg ax,cx ; CH, CL = hh:mm in BCD + mov ah,es:SECONDS[si] + mov al,0 ; get binary seconds & no daylight saving + call bin2bcd ; convert to BCD values + xchg ax,dx ; DH, DL = ss.000 in BCD + + mov ah,3 ; set real time clock time + int RTC_INT ; on AT, XT-286, PS/2, etc. + + mov al,100 + mul es:SECONDS[si] ; AX = seconds in hundredths + xchg ax,dx ; save in DX + mov al,es:HUNDREDTHS[si] + cbw ; AX = hundredths + add ax,dx ; AX = secs and hundredths in 1/100ths + cwd ; make the a dword + mov bx,5 + div bx ; AX = secs and hundredths in 5/100ths + xchg ax,bx ; save in BX + mov al,60 ; convert hours into minutes + mul es:HOURS[si] ; AX = hours in mins + xchg ax,dx + mov al,es:MINUTES[si] + cbw ; AX = minutes value + add ax,dx ; AX = hours and mins in mins + mov dx,60*20 + mul dx ; DX:AX = hours and mins in 5/100ths + add ax,bx + adc dx,0 ; DX:AX = total in 5/100ths + mov bx,CONVERSION_FACTOR ; load up our magic value + push dx ; save high word + mul bx ; DX = low word result + mov cx,dx ; save for later + pop ax ; recover high word + mul bx ; DX:AX = result from high word + add ax,cx ; add low and high word results + adc dx,0 ; together in DX:AX + xchg ax,dx ; DX = low word of result + xchg ax,cx ; CX = high word of result + + mov ah,1 ; set system timer + int RTC_INT ; CX = high word, DX = low word + + sub ax,ax ; return successfully when done + ret + + + Public read_system_ticks + +read_system_ticks: +;----------------- + mov ah,0 ; read system tick counter + int RTC_INT + test al,al ; have we passed midnight ? + jz read_st10 ; if so a new day has dawned + inc daycount +read_st10: + ret + +bin2bcd: ; convert AL and AH to BCD values +;------- + call bin2bcd1 ; swap AL, AH, convert to BCD +; call bin2bcd1 +; ret +bin2bcd1: + push cx + mov ch,ah ; save AH in scratch register + aam ; AL = AL % 10; AH = AL/10; + mov cl,4 + shl ah,cl ; shift tens into high nibble + or ah,al ; combine the nibbles + mov al,ch ; restore the high byte into low byte + pop cx + ret + +driver endp + +RCODE ends ; end of device driver code + +RESUMECODE segment 'RESUMECODE' + +; If the system ROM BIOS supports RESUME mode then it will call Int 6C +; when returning from sleep mode. We take this over and reset the clock +; based upon the RTC value. To save space we only relocate the code if +; required. +; + + Public ResumeHandler +ResumeHandler proc far + sti + mov ax,cs:DataSegment ; we have been asleep and are being + mov ds,ax ; woken by the BIOS + mov es,ax ; lets re-read the RTC before + call set_clock ; we return to them + clc + ret 2 +ResumeHandler endp + +set_monlen db 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + + +set_clock: +;--------- +; We may also be called after a RESUME when we have to reset the time. + + mov ah,2 ; read real time clock + xor cx,cx + xor dx,dx ; assume it won't work + stc + int RTC_INT ; CH = hours, CL = mins, DH = secs + jc set_clock40 ; (all in BCD remember) + + xchg al,dh ; AL = secs + call bcd2bin ; AL = secs in binary + cmp al,59 + ja set_clock40 ; reject invalid seconds + mov ah,100 + mul ah ; AX = seconds in hundredths + cwd ; make it a dword + mov bx,5 + div bx ; AX = secs and hundredths in 5/100ths + xchg ax,bx ; save in BX + + mov al,ch ; AL = hours in BCD + call bcd2bin ; AL = hours in binary + cmp al,23 + ja set_clock40 ; reject invalid hours + mov ah,60 ; convert hours into minutes + mul ah ; AX = hours in mins + xchg ax,dx ; save in DX + + mov al,cl ; AL = mins in BCD + call bcd2bin ; AL = mins in binary + cmp al,59 + je set_clock40 ; reject invalid mins + cbw ; AX = minutes value + add ax,dx ; AX = hours and mins in mins + mov dx,60*20 + mul dx ; DX:AX = hours and mins in 5/100ths + add ax,bx + adc dx,0 ; DX:AX = total in 5/100ths + mov bx,CONVERSION_FACTOR ; load up our magic value + push dx ; save high word + mul bx ; DX = low word result + mov cx,dx ; save for later + pop ax ; recover high word + mul bx ; DX:AX = result from high word + add ax,cx ; add low and high word results + adc dx,0 ; together in DX:AX + xchg ax,dx ; DX = low word of result + xchg ax,cx ; CX = high word of result + + mov ah,1 ; set system timer + int RTC_INT ; CX = high word, DX = low word + +set_clock40: + mov ah,4 ; read RTC (if present) + int RTC_INT ; validate date - CMOS may be corrupt + cmp cx,1980h ; Too low? + jb set_clock45 ; Yes so skip + cmp cx,2099h ; Too high ? + ja set_clock45 ; Yes so skip + cmp dx,0101h ; Too low? + jb set_clock45 ; Yes so skip + cmp dx,3112h ; Too high ? + jbe set_clock50 ; No its okay so scram +set_clock45: + mov cx,1980h ; assume the year 1980 + mov dx,0101h ; assume 1st of January of that year +set_clock50: + xchg ax,cx ; AL, AH = year, century in BCD + call bcd2bin ; convert values to binary + xchg ax,cx + xchg ax,dx ; AL, AH = day, month in BCD + call bcd2bin ; convert values to binary + xchg ax,dx + + mov daycount,0 ; zero the daycount in case of RESUME + mov ax,19*256 + 80 ; assume 1980 +set_clock55: + cmp ax,cx ; same year? + je set_clock65 + mov bx,365 ; assume 365 days in that year + test al,3 ; test for leap year + jnz set_clock60 ; (this works til 2400 A.D.) + inc bx ; add FEB 29 if divisible by four +set_clock60: + add daycount,bx ; add days in previous year to total + inc al ; next year + cmp al,100 ; end of century? + jb set_clock55 ; skip if same century + mov al,0 ; continue with XX00 + inc ah ; ...next century + jmps set_clock55 ; check year again + + +set_clock65: ; same year by now + xchg ax,cx ; CX = year + sub dx,0101h ; make month, day 0 relative + sub bx,bx ; assume January + sub ax,ax ; AH = 0 +set_clock70: + cmp dh,bl ; does current month match? + je set_clock80 ; skip if it does + mov al,cs:set_monlen[bx] ; get length of that month + cmp al,28 ; is it february ? + jne set_clock75 + test cl,3 ; is it a leap year ? + jnz set_clock75 + inc ax ; leap year, 29 days in february +set_clock75: + add daycount,ax ; add it to total day count + inc bx ; move on to next month + jmps set_clock70 + +set_clock80: + mov al,dl ; get days in that month + add daycount,ax ; add them to day count + ret + +bcd2bin: +;------- +; entry: AL, AH = BCD values +; AL, AH = binary equivalents + + call bcd2bin1 ; swap AL, AH, convert AL to binary +; call bcd2bin1 ; swap AL, AH, convert AL to binary +; ret + +bcd2bin1: ; convert BCD to binary + xchg al,ah ; swap the two values + push bx + mov bl,0 ; start off without tens +bcd2bin2: + cmp al,10h ; check if more tens + jb bcd2bin3 ; all tens done + sub al,10h ; else subtract 10 in BCD + add bl,10 ; ...and add it in binary + jmps bcd2bin2 ; repeat for all tens +bcd2bin3: ; AL = ones, BL = tens + add al,bl ; AL = binary value + pop bx ; restore BX + ret + + +RESUMECODE ends + + +ICODE segment 'ICODE' ; initialization code + + Assume CS:CGROUP, DS:CGROUP + +dd_init: ; 0-initialize driver +;------- + call set_clock ; set elapsed ticks + + les bx,REQUEST[bp] ; ES:BX -> request header + + mov ax,endbios + mov es:RH0_RESIDENT[bx],ax ; set end of device driver + mov es:RH0_RESIDENT+2[bx],ds + + sub ax,ax ; initialization succeeded + ret ; (BIOS init always does...) + + +ICODE ends + + end diff --git a/IBMBIO/CONFIG.A86 b/IBMBIO/CONFIG.A86 new file mode 100644 index 0000000..fcd9fce --- /dev/null +++ b/IBMBIO/CONFIG.A86 @@ -0,0 +1,1404 @@ +; File : $CONFIG.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; CONFIG.A86 1.35 93/12/01 18:30:29 +; nls_temp_area grows to 258 bytes +; CONFIG.A86 1.34 93/11/28 15:30:27 +; Support HIBUFFERS in UMB's +; CONFIG.A86 1.32 93/11/22 15:02:14 +; Bus Master checks do Int 21/0D before/after to discard any buffers +; CONFIG.A86 1.30 93/11/18 18:02:26 +; Add primitive multi-master checking +; CONFIG.A86 1.27 93/11/04 16:34:24 +; Extra callout to STACKER to determine if a drive is valid +; CONFIG.A86 1.26 93/11/03 17:00:19 +; Stop dblspace phantom drives from appearing (FATsize=0) +; CONFIG.A86 1.25 93/09/14 20:12:24 +; Initialise LFLG_PHYSICAL better - allow for zero FAT's meaning phantom drive +; CONFIG.A86 1.24 93/09/02 22:34:50 +; Add header to system allocations +; CONFIG.A86 1.23 93/08/06 20:55:23 +; re-arrange device init order for SCREATE.SYS on a VDISK.SYS +; CONFIG.A86 1.22 93/08/02 14:45:55 +; hide preload drives from func_device +; CONFIG.A86 1.20 93/07/28 19:19:08 +; call to SetupHMA before AllocHMA in setup_buffers allows buffers to go high +; on novell memory managers +; ENDLOG + + include config.equ + include i:msdos.equ + include i:char.def + include i:reqhdr.equ + include i:driver.equ + include i:fdos.equ + include i:f52data.def ; Function 52 DOS Data Area + include i:doshndl.def ; DOS Handle Structure Definition + include i:country.def + +TRUE equ 0FFFFh ; value of TRUE +FALSE equ 0 ; value of FALSE + +CGROUP group INITCODE, INITDATA + +INITCODE CSEG PARA 'INITCODE' + + extrn AllocHMA:near + extrn SetupHMA:near + extrn alloc_instseg:near ; Allocate "Segment" Instance Memory + extrn alloc_hiseg:near ; Allocate "Segment" High Memory + extrn alloc_seg:near ; Allocate "Segment" Memory + extrn config_process:near + extrn InitStacks:near + extrn HookInt2F:near + extrn UnhookInt2F:near + extrn Verify386:near + + Public config_init +config_init: ; Initialize the CONFIG data + ret + + + Public country_init +country_init: +;------------ + push ds + push es + push di + push si + +; Obtain the address of the DBCS table in the BDOS. + mov ax, 06507h ; Extended Country Info: get DBCS ptr + mov bx, 0FFFFh ; codepage number: -1 for global cp + mov cx, 00005h ; size of info. buffer + mov dx, 0FFFFh ; country code: -1 for current country + mov di, offset dbcs_buf + push ds + pop es ; es:di -> 5 byte buffer + int DOS_INT ; returns with buffer filled in + +; Get the current country information. + mov dx, offset ctry_info ; ds:dx -> buffer to be filled in + mov ax, 03800h ; get current country info + int DOS_INT + jnc ctry_info_done ; no carry = no error + +; Failed to get country info. Place dummy uppercase routine in table. + mov si, offset ctry_info + mov CI_CASEOFF[si], offset myretf + mov CI_CASESEG[si], cs + mov bx, country_code + +ctry_info_done: + mov country_code, bx + + pop si + pop di + pop es + pop ds + ret + +myretf: retf + +; +; CONFIG is called after the BIOS INIT code has been relocated to high +; memory, the BIOS and BDOS have been initialised. +; + Public config ; Process CONFIG.SYS, loading and +config: ; initialising device drivers + call country_init ; initialise DBCS tbl and country info + mov ax,max_secsize ; get maximum sector size in BIOS + les bx,func52_ptr + cmp ax,es:F52_SECSIZE[bx] ; larger than default? + jbe cfg_skip ; skip if not + mov es:F52_SECSIZE[bx],ax ; else update sector size +cfg_skip: + call cpu_init ; initialise CPU type + push ds ! pop es + + call config_process ; Process CONFIG.SYS + + cmp num_files,MIN_NUM_FILES ; Ensure the Minimum number of File + jae cfg_ex10 ; have been allocated. + mov num_files,MIN_NUM_FILES +cfg_ex10: + xor ax,ax + mov al,init_buf ; now ensure we have allocated + mov num_buf,ax ; the correct number of buffers + + call SetupDeblocking ; do our thing with deblocking + + call config_finish ; clean up configuration + call setup_fopen ; allocate disk hashing + call setup_history + ret + +cpu_init: +; If we are on a 386 or above set CPU flag + call Verify386 ; make sure it's a 386 + jc cpu_init10 ; skip setting falg if not + les bx,func52_ptr + mov es:F52_CPU_TYPE[bx],1 ; we have a 386 ! +cpu_init10: + stc ; it's not a 386 + ret + + +SetupDeblocking: +;--------------- +; Some types of hard disk controller give us problems with disk access of +; mapped memory (eg. upper memory, LIM pages). +; We can force single sector deblocking in the disk driver to avoid these +; problems. On DRDOS 5/6 our default was single sector I/O above A000, but +; this gives performance problems when devices/tsr's are loaded into upper +; memory (eg. STACKER, SERVER). To avoid this we use the following strategy. +; +; Default for CONFIG is A000, and may be updated at any time by a DEBLOCK= +; statement. If this happens the user setting has priority. +; +; At the end of CONFIG, assume no user supplied setting, we do some simple +; tests for multi-master controllers. If these fail we leave the settings +; at A000. If they succeed we go ahead and change the default setting to +; deblock at FFFF. The test is to read the 1st sector into low memory, and +; again into upper memory. If we read the same thing then assume all is well. +; If we can't do this leave the deblocking set at A000. +; +; NB. We will still have problems from LIM, and from DMA crossing page +; boundaries on some memory managers (eg. DRDOS 5.0) +; + les bx,func52_ptr + lea bx,F52_DEVROOT[bx] ; ES:BX -> NUL device link + cmp DeblockSetByUser,FALSE + je SetupDeblocking20 ; the user is king +SetupDeblocking10: + push cs ! pop es ; ES -> local data again + ret + +SetupDeblocking20: ; get next device driver + les bx,es:[bx] ; we want resident disk device + cmp bx,0FFFFh ; end of the chain ? + je SetupDeblocking10 + test es:word ptr 4[bx],8000h + jnz SetupDeblocking20 ; we assume one disk device at 70:xxxx + mov ax,es + cmp ax,cs:bios_seg ; scan for resident disk in IO.SYS + jne SetupDeblocking20 + cmp es:word ptr 18[bx],0EDCh + jne SetupDeblocking20 ; is it our disk driver ? + lea ax,22[bx] ; deblocking variable is here + mov deblockOffset,ax ; remember that for fixups + mov deblockSeg,es + mov ax,es:DH_STRATEGY[bx] ; Set up the STRATEGY Entry Point + mov strategy_off,ax + mov strategy_seg,es + + mov ax,es:DH_INTERRUPT[bx] ; Set up the INTERRUPT Entry Point + mov interrupt_off,ax + mov interrupt_seg,es + mov al,es:DH_NAME[bx] ; get # supported units + cbw + mov numUnits,ax ; remember for later + + mov ax,(MS_M_STRATEGY*256)+1; set allocation strategy + mov bl,42h ; to last fit, upper only + int DOS_INT + mov bx,512/16 ; we need a 512 byte buffer + mov ah, MS_M_ALLOC ; try to allocate on in upper memory + int DOS_INT + jc SetupDeblocking50 + mov UpperMemoryBuffer,ax ; use this for deblocking checks + mov cx,numUnits ; CX = # of drives supported + mov dx,'C'-'A' ; start with drive C: + sub cx,dx ; CX = # of potential hard disks + jbe SetupDeblocking40 ; skip tests if none +SetupDeblocking30: ; DX = next drive, CX = drive count + push cx ! push dx + call BusMasterCheck ; check if drive DL bus master disk + pop dx ! pop cx + jc SetupDeblocking40 ; is so leave deblocking alone + inc dx ; else move to next drive + loop SetupDeblocking30 ; repeat for all drives + les bx,deblockPointer + mov es:word ptr [bx],0FFFFh ; safe to disable deblocking +SetupDeblocking40: + mov es,UpperMemoryBuffer + mov ah,MS_M_FREE + int DOS_INT ; free the upper memory buffer +SetupDeblocking50: + mov ax,(MS_M_STRATEGY*256)+1; set allocation strategy + mov bl,0 ; to first fit + int DOS_INT + push cs ! pop es ; ES -> local data again + ret + + +BusMasterCheck: ; determine if we have an old troublesome controller +;-------------- +; On Entry: +; DL = drive to check (zero based) +; On Exit: +; CY set if troublesome drive +; + call BusMasterRemovable ; is it a removable device ? + jnc BMCheck10 ; yes, skip the checks + mov ax,mem_current ; read into low memory + call BusMasterRead ; read one sector from disk + jc BMCheck10 ; give up if we couldn't read + + mov es,mem_current ; ensure at least the 1st word will + mov ax,es:.0 ; differ if the read doesn't happen + not ax + mov es,UpperMemoryBuffer + mov es:.0,ax + + mov ax,UpperMemoryBuffer ; read into upper memory + call BusMasterRead ; read one sector from disk + jc BMCheck10 ; give up if we couldn't read + + xor si,si + xor di,di + mov cx,512/2 + mov es,mem_current + mov ds,UpperMemoryBuffer + repe cmpsw ; does the sector match ? + push cs ! pop ds + je BMCheck10 ; yes, everything is fine + stc ; no, better leave DEBLOCK at A000 +BMCheck10: + ret + +BusMasterRemovable: +;------------------ +; On Entry: +; DL = drive +; On Exit: +; CY set if not a removable drive +; DL preserved +; + push cs ! pop es + mov bx,offset removableMediaRequest + mov es:RH_UNIT[bx],dl + callf cs:strategy + callf cs:interrupt + test es:RH_STATUS[bx],RHS_BUSY + jz BusMasterRemovable10 + stc ; busy bit set, it's a hard disk +BusMasterRemovable10: + ret + +BusMasterRead: ; Read first sector from drive BL +;------------- +; On Entry: +; AX = segment of buffer +; DL = 02 for C:, 03 for D:, etc. +; Exit: +; CY clear if deblocking not required +; DL preserved +; + les bx,deblockPointer + mov es:word ptr [bx],0FFFFh ; no deblocking during the test + push cs ! pop es + mov bx,offset readRequest + mov es:RH_UNIT[bx],dl + mov es:RH4_BUFOFF[bx],0 + mov es:RH4_BUFSEG[bx],ax + mov es:RH4_COUNT[bx],1 + callf cs:strategy + callf cs:interrupt + test es:RH_STATUS[bx],RHS_ERROR + jz BusMasterRead10 + stc ; error bit set, say we had a problem +BusMasterRead10: + les bx,deblockPointer + mov es:word ptr [bx],0A000h ; enable deblocking again + ret + + + Public setup_stacks + +setup_stacks: + mov cx,num_stacks ; we want this many stacks + jcxz setup_stacks10 ; skip if we don't want any + mov dx,stack_size ; they should be this big + call InitStacks ; initialise the stacks +setup_stacks10: + ret + +setup_history: + test history_flg,RLF_ENHANCED + jz setup_hist10 ; if history not enabled just exit + + push es + les bx,drdos_ptr ; Get the internal data area + + mov si,es:DRDOS_HIST1CTL[bx]; Get the address of History Control + mov ax,history_size ; Get Offset buffer for History data + call setup_hist20 ; Allocate Buffer 1 + + mov si,es:DRDOS_HIST2CTL[bx]; Get the address of History Control 2 + mov ax,history_size ; Get Offset buffer for History data + call setup_hist20 ; Allocate Buffer 2 + + mov al,history_flg ; copy history state + mov es:DRDOS_HISTFLG[bx],al ; into DRDOS data area + + pop es +setup_hist10: + ret + +setup_hist20: + and ax,not 15 ; round to a complete paragraph + add ax,16 ; always be a para bigger + mov es:word ptr 02[si],ax ; Buffer Tail Address + mov cl,4 + push ax ; save buffers size in bytes + shr ax,cl ; convert to para's + mov dl,'H' ; History buffer + call alloc_instseg ; Allocate Buffer + mov es:word ptr 00[si],ax ; Buffer Start Address + pop cx ; recover buffer size in bytes + push es + mov es,ax ; point ES at buffer seg + xor di,di ; ES:DI -> buffer + xor ax,ax ; zero it + rep stosb ; before use + pop es + ret + + + Public device_init, resident_device_init + +; DEVICE_INIT will initialise the device with the Device Header at +; ES:BX +; +; Entry: +; ES:DI Address of First Device Header +; DS:SI Command Line Parameters +; +; Exit: +; AX Top bit set on error, error code in AL +; +device_init: +;----------- + push es ! push di + call build_cmd_tail ; point DS:SI to dos style cmd line + pop di ! pop es + call HookInt2F ; hook the Int 2F vector + call resident_device_init + call UnhookInt2F ; get off the Int 2F vector + test ax,ax ; set the flags + ret + +resident_device_init: +;-------------------- + mov rel_unit,0 ; set rel unit to zero for block devices + mov dev_count,0 + mov bx,offset request_hdr ; ds:bx -> command block +if TRUE + mov ax,mem_max ; AX:0 -> top of available memory + mov ds:RH0_RESIDENT,0 ; pass to the device driver + mov ds:RH0_RESIDENT+2,ax ; in the RESIDENT field +else + mov ds:RH0_RESIDENT,di ; Force the default RESIDENT field + mov ds:RH0_RESIDENT+2,es ; to be the error condition +endif +dev_i10: + push si + push es ! push di + call save_vecs ; save interrupt vectors + mov bx,offset request_hdr ; ds:bx -> command block + call dev_init ; initialise the device driver + test es:DH_ATTRIB[di],DA_CHARDEV + jnz dev_i18 ; skip if a character device + cmp ds:RH0_NUNITS,0 ; no drives installed for disk device? + je dev_i_err ; failed if no drives found +dev_i18: + mov ax,ds:RH0_RESIDENT ; Calculate the address of + mov cl,4 ; last paragraph used by the + shr ax,cl ; device driver. If this is the + add ax,ds:RH0_RESIDENT+2 ; device driver CS then error + test ds:RH0_RESIDENT,15 ; allow for partial para ? + jz dev_i19 + inc ax ; round it up +dev_i19: + cmp ax,strategy_seg + jbe dev_i_err + + cmp ax,mem_max ; Check for Memory Overflow + jb dev_i30 ; if it does then we can't install + call restore_vecs ; so replace interrupt vectors +dev_i_err: ; device initialization failed! + les di,cs:func52_ptr ; ES:DI -> internal data + mov ax,es + or ax,di ; DOS data area present yet? + pop di ! pop es ; recover the device header + + les di,es:DH_NEXT[di] ; try next device driver + jz dev_i60 ; if it's resident initialisation + mov di,0FFFFh ; else stop now + jmps dev_i60 + +; The device driver initialised OK so now build/update internal +; tables based on the device driver type. +; +; AX = next available paragraph +; DS:BX = request header +; ES:DI = device driver header +; +dev_i30: ; DEV_INIT OK so update the Top of + mov mem_current,ax ; memory field + test es:DH_ATTRIB[di],DA_CHARDEV + jz dev_i40 + + call char_device ; Handle Initialization of all + jmps dev_i50 ; character devices + +dev_i40: + call block_device ; Handle Initialization of all +; jmps dev_i50 ; Block Devices + +dev_i50: + pop di ! pop es ; Retrieve the current device header + push es:DH_NEXTSEG[di] ; save next entry on the list + push es:DH_NEXTOFF[di] ; while we deal with existing one + mov es:DH_NEXTOFF[di],0FFFFh; terminate the list + call device_insert ; and insert into the list + pop di + pop es ; go round till the end +dev_i60: + pop si ; recover cmdline for next device + cmp di,0FFFFh ; was that the last device to + jne dev_i10 ; initialise, no do next + mov bx,offset request_hdr ; ds:bx -> command block + mov ax,ds:RH_STATUS ; return Status Register + and ax,80FFh ; is there an error ? + js dev_i70 + xor ax,ax ; no, return success +dev_i70: + ret + + + public init_static_request +init_static_request: + ; Set up request header for INIT command. + sub ax,ax ; get a convenient zero + mov ds:RH_LEN,RH0_LEN ; Init Request Length + mov ds:RH_UNIT,al ; relative drive always 0 + mov ds:RH_CMD,CMD_INIT ; Init Command + mov ds:RH_STATUS,ax ; Zero Status Register + + mov ds:RH0_BPBOFF,si ; Save the command line offset and + mov ds:RH0_BPBSEG,ds ; Segment in the BPB Pointer + + mov al,next_drv ; the first drive for this device + sub al,preload_drv ; (not including preloaded devices) + mov ds:RH0_DRIVE,al ; will be allocated as NEXT_DRV +;;; mov es:DH_NEXTSEG[di],0 ; force seg to zero (386max 4.05) + ret + +dev_init: +;-------- +; On Entry: +; ES:DI -> device driver header +; DS:BX -> req header +; DS:SI -> command line +; On Exit: +; ES:DI/DS:BX +; + mov ax,es:DH_STRATEGY[di] ; Set up the STRATEGY Entry Point + mov strategy_off,ax + mov strategy_seg,es + + mov ax,es:DH_INTERRUPT[di] ; Set up the INTERRUPT Entry Point + mov interrupt_off,ax + mov interrupt_seg,es + call init_static_request + + push ds ! push es ; Save Segment registers + push bx ! push si ! push di ; and pointers (not all preserve them) + push ds ! pop es ; ES -> Points at the Data Segment + mov ds,strategy_seg ; DS == Device Drive Segment + mov si,di ; DS:SI -> device driver header + callf cs:strategy ; Call Device Strategy Routine + callf cs:interrupt ; Call Device Interrupt Routine + pop di ! pop si ! pop bx ; recover the pointers + pop es ! pop ds ; Restore Segment Registers + mov es:DH_NEXTSEG[di],es ; ignore segment - it MUST be same one + ret + +; +; Character Device Driver Initialised OK so now build/update internal +; tables based on the device driver type. +; +; DS:BX Request Header +; ES:DI Device Driver Header +; +char_device: + test es:DH_ATTRIB[di],DA_ISCIN + jz char_d10 ; is this the standard console device? + mov condev_off,di ; save console device driver address + mov condev_seg,es + ret + +char_d10: + test es:DH_ATTRIB[di],DA_ISCLK + jz char_d20 ; is this the standard clock device? + mov clkdev_off,di ; save clock device driver address + mov clkdev_seg,es +char_d20: + ret + + +; Block device driver initialised OK. Save the values +; returned from the INIT call so we can later build all the +; required internal tables. +; +; entry: DS:BX -> request header +; ES:DI -> device driver header +; + public block_device +block_device: + mov al,BLKDEV_LENGTH ; bytes per block device table entry + mul byte ptr num_blkdev ; * # of block devices installed + add ax,offset blkdev_table ; AX -> block dev init result table + xchg ax,si ; pointer to next block device struct + mov devoff,di + mov devseg,es ; point to device driver header + mov 0[si],di + mov 2[si],es ; save device driver address for later + mov ax,ds:RH0_BPBOFF + mov 4[si],ax ; save BPB table address (offset) + mov ax,ds:RH0_BPBSEG + mov 6[si],ax ; save BPB table address (segment) + mov cl,ds:RH0_NUNITS + mov 8[si],cl ; get # of units supported by driver + mov es:DH_NAME[di],cl ; set # of units in device name + inc num_blkdev ; we've installed another block device + add next_drv,cl ; update drive base for next driver + add dev_count,cl ; number of new units + + mov ax,boot_device ; now for Andy's bit about boot device + or ax,boot_device+2 ; have we already got a boot device? + jnz not_boot_dev + mov ch,init_drv + sub ch,next_drv ; is sub unit in this driver + ja not_boot_dev ; no, skip it + add ch,cl ; work out which sub unit it is + mov boot_drv,ch ; and remember it + mov boot_device,di + mov boot_device+2,es +not_boot_dev: + + push si ! push es ! push di + mov cl,8[si] + mov ch,0 ; CX = # of drives found in driver + les si,4[si] ; ES:SI -> BPB array in BIOS + mov bpbseg,es ; remember the segment +blkdev_loop: + lods es:ax ; AX = offset of next BPB + push es ! push si ! push cx + mov bpboff,ax ; remember the offset + xchg ax,di ; ES:DI -> next BPB + mov ax,es:[di] ; AX = sector size for BPB + cmp ax,max_secsize ; new maximum for sector size + jbe blkdev_next1 ; skip if sector size not grown + mov max_secsize,ax ; else set new maximum +blkdev_next1: + mov dl,es:2[di] ; get sectors per cluster + mov dh,0 ; make this a word + mul dx ; AX = bytes per cluster + cmp ax,max_clsize ; more than previous maximum + jbe blkdev_next2 ; skip if no new high score + mov max_clsize,ax ; else record max. sector size +blkdev_next2: + les bx,func52_ptr ; ES:BX -> internal data + mov ax,es + or ax,bx ; DOS data area present yet? + jz blkdev_next3 ; skip if BDOS not present yet + call setup_drives ; update drives in BDOS data + mov es,mem_current ; MUST create a DDSC just after driver + add mem_current,(DDSC_LEN+15)/16 + xor bp,bp ; ES:BP points to the DDSC + call setup_ddsc ; add new DDSC_ to chain + call setup_ldt ; initialise LDT for that drive +blkdev_next3: + pop cx ! pop si ! pop es + loop blkdev_loop ; repeat for all BPBs in driver + pop di ! pop es ! pop si + ret + +resident_ddscs: +;-------------- +; Allocate DDSC's for the resident device drivers - we can only do this +; after the DOS data area is established. +; + sub bx,bx ; start with 1st block device + mov cx,num_blkdev ; get # of block devices + jcxz res_ddsc40 ; skip if no block devices +res_ddsc10: + push bx ! push cx + mov ax,BLKDEV_LENGTH + mul bx + add ax,offset blkdev_table + xchg ax,si ; SI -> block device table + sub cx,cx + mov cl,8[si] ; CX = # of units on device + sub bx,bx ; BX = relative unit # * 2 + mov rel_unit,bx ; start with relative unit # 0 + +res_ddsc20: ; CX = remaining units + push bx ! push cx ! push si ; BX = offset, SI -> drive structure + lodsw + mov devoff,ax ; save device header offset + lodsw + mov devseg,ax ; save device header segment + les si,[si] ; get offset of BPB array + mov ax,es:[bx+si] ; get offset for our BPB + mov bpboff,ax + mov bpbseg,es ; save pointer to BPB + + les bp,res_ddsc_ptr ; point to position for DDSC_ + add ds:word ptr res_ddsc_ptr,DDSC_LEN + call setup_ddsc ; setup one unit + pop si ! pop cx ! pop bx + inc bx ! inc bx ; increment (unit index*2) + loop res_ddsc20 ; repeat for next unit, same driver + + pop cx ! pop bx + inc bx + loop res_ddsc10 ; repeat for next driver +res_ddsc40: ; all block devices done + ret + + +setup_ddsc: +;---------- +; On Entry: +; ES:BP -> DDSC_ to initialise and link into chain +; bpbptr -> BPB to initialise from +; devseg:devoff -> device driver header +; abs_unit, rel_unit reflect drive +; On Exit: +; None +; + push ds + lds si,bpbptr ; DS:SI points to the BPB + mov ah,53h ; build DDSC from BPB call + int DOS_INT ; initialises the structure + pop ds + mov ax,devoff + mov es:DDSC_DEVOFF[bp],ax + mov ax,devseg + mov es:DDSC_DEVSEG[bp],ax + + mov ax,abs_unit + inc abs_unit + mov es:DDSC_UNIT[bp],al ; set absolute unit (global) + mov ax,rel_unit + inc rel_unit + mov es:DDSC_RUNIT[bp],al ; set relative unit (driver relative) + + mov ax,-1 ; set link to FFFFh:FFFFh + mov es:word ptr DDSC_LINK[bp],ax + mov es:word ptr DDSC_LINK+2[bp],ax + mov es:DDSC_FIRST[bp],al ; set drive never accessed flag + mov ax,es ; now link into device chain +; + les bx,func52_ptr ; ES:BX -> secret 52h data + lea bx,F52_DDSCPTR-(offset .DDSC_LINK)[bx] +setup_ddsc10: + cmp es:word ptr DDSC_LINK[bx],0FFFFh + je setup_ddsc20 ; is there another one ? + les bx,es:DDSC_LINK[bx] ; onto next DDSC_ + jmps setup_ddsc10 +setup_ddsc20: ; link new DDSC to end of chain + mov es:word ptr DDSC_LINK[bx],bp + mov es:word ptr DDSC_LINK+2[bx],ax + ret ; now RAF will be happy + + + Public setup_ldt + +setup_ldt: + push ds + push es + les bx,func52_ptr ; get internal data in ES:BX + mov al,LDT_LEN ; we need this many bytes per drive + mul es:F52_LASTDRV[bx] ; *lastdrive + xchg ax,cx ; CX = size to initialise + mov al,es:F52_LASTDRV[bx] ; lastdrive + push ax ; save for later + les di,es:F52_PATHPTR[bx] ; now initialise the CSD's + xor al,al ; to zero + rep stosb ; zero them + pop ax ; recover lastdrive + + xor bx,bx ; start with zero offset + xor cx,cx ; start with drive A + xchg al,cl ; AH = physical limit, CX logical limit +ldt_init: + push ax + push cx + push ax + lea di,LDT_NAME[bx] + add al,'A' ; make drive ASCII + stosb + mov ax,'\:' ; point at the root + stosw + mov ax,0FFFFh + lea di,LDT_BLK[bx] ; set to FFFF to force LDT_ rebuild + stosw ! stosw ! stosw ; next two words are FFFF too +; lea di,LDT_ROOTLEN[bx] + mov ax,2 + stosw ; set the length field + pop ax + lds si,cs:func52_ptr ; get internal data in DS:SI + sub si,offset .DDSC_LINK +ldt_init20: + lds si,ds:DDSC_LINK[si] ; point to next PDT + cmp si,-1 ; skip if there isn't one + je ldt_init40 + cmp al,ds:DDSC_UNIT[si] ; is this the DDSC for the drive + jne ldt_init20 ; if not try another + mov es:word ptr LDT_PDT[bx],si + mov es:word ptr LDT_PDT+2[bx],ds + cmp ds:DDSC_NFATS[si],0 ; no FATS, then it's a reserved drive + je ldt_init40 + push es + push bx + push ax ; save drive we are processing + mov ax,4A11h + xor bx,bx + int 2Fh ; do an STACKER installation check + pop dx ; DL = drive we are processing + test ax,ax + mov ax,LFLG_PHYSICAL ; assume a physical drive + jnz ldt_init30 ; no STACKER, it's physical + sub cl,'A' ; zero base STACKER drive returned + cmp cl,dl ; should we check this drive ? + ja ldt_init30 ; below 1st drive, it's physical + push ax + push dx + mov ax,4A11h + mov bx,1 ; ask STACKER for host drive + int 2Fh + pop dx + pop ax + cmp bl,dl ; is this the host drive ? + jne ldt_init30 + xor ax,ax ; drive is invalid +ldt_init30: + pop bx + pop es + mov es:LDT_FLAGS[bx],ax +ldt_init40: + add bx,LDT_LEN ; move onto next LDT_ + pop cx + pop ax + inc ax ; and next drive + loop ldt_init ; done to lastdrive ? no, do another + + pop es + pop ds + ret + + Public device_insert + +device_insert: +;------------- +; insert device drivers at ES:DI into global chain +; if we are initialising the resident device drivers then we don't have +; a global chain, so insert them on a local chain and try again later + push ds + lds bx,func52_ptr ; Internal Data Pointer + lea si,F52_DEVROOT[bx] ; DS:SI -> NUL device + mov ax,ds ; if BDOS data area isn't present + or ax,bx ; we are initialising resident + jnz dev_ins_next ; devices + push cs ! pop ds + mov si,offset resdev_chain ; it's resident devices +dev_ins_next: + cmp di,-1 ; end of device chain reached? + je devins_done ; yes, all devices inserted + mov ax,0[si] + mov dx,2[si] ; DX:AX = original chain + mov 0[si],di + mov 2[si],es ; link our device at head of chain + xchg ax,es:0[di] ; link old global chain to device + xchg dx,es:2[di] ; & get next device in local chain + mov di,ax ; point to next device in chain + mov es,dx + jmps dev_ins_next ; repeat until chain empty +devins_done: + pop ds + ret + + + public config_finish + +config_finish: ; finish off configuration +;------------- + cmp resdev_off,-1 ; are resident devices already + je cfg_fin10 ; installed + les di,resdev_chain ; insert all the resident device + call device_insert ; drivers into DOS chain + call resident_ddscs ; build DDSC's for resident devices + mov resdev_off,-1 ; only do this once... +cfg_fin10: + + les bx,func52_ptr ; ES:BX -> base of DOS variables + call setup_drives ; Update No of Physical Drives in case + ; this is the first pass + call setup_ldt ; setup the ldt's + les bx,func52_ptr + lea di,F52_CLKDEV[bx] ; ES:DI -> clock ptr, console ptr + mov si,offset clkdev_off ; DS:SI -> local pointer values + movsw ; set offset of clock device driver + movsw ; set segment of clock device driver + movsw ; set offset of console device driver + movsw ; set segment of console device driver + + call setup_doshndl ; Allocate DOS compatible Handles + ; NB must immediately follow devices ! + call setup_buffers ; allocate the requested # + ret + + +setup_buffers: +;------------- +; entry: num_buf = minimum # of buffers required +; 0 - use temporary high buffers +; + les bx,func52_ptr ; ES:BX -> internal data structure + mov ax,num_buf ; fill in info in DOS for diagnostic + mov es:F52_NUM_BUF[bx],ax ; programs + mov al,num_read_ahead_buf + mov es:F52_READ_AHEAD[bx],ax + mov ax,es:F52_SECSIZE[bx] ; get DOS data sector size + cmp ax,max_secsize ; has it been poked to a bigger value ? + ja setup_b10 ; if so we must discard anyway + mov ax,max_secsize ; get max. sector size found +setup_b10: + mov es:F52_SECSIZE[bx],ax ; update max. sector size in PCMODE + mov max_secsize,ax ; update max. sector size locally + add ax,offset .BCB_DATA ; add in the header size + + mov es,init_dseg ; ES:DI -> init buffers + mov di,offset INIT_BUFFERS + mov cx,NUM_BUFFS ; CX buffs, DX in size, at ES:DI + mov dx,SIZEOF_BUFFS ; size of init buffers + cmp num_buf,0 ; (zero at init time) + je setup_b70 ; go ahead and initialise + + push ax ; save size of buffer + mul num_buf ; AX = total bytes required + test dx,dx ; > 64 K ? + jz setup_b30 + mov ax,0FFFFh ; do the maximum +setup_b30: + pop bx ; BX = size of a buffer + mov cx,ax ; CX bytes required + xor dx,dx + div bx ; AX = # buffers + + push ax ; save # buffers + push bx ; save size of a buffer + push cx ; save bytes wanted + test buffersIn,BUFFERS_IN_HMA + stc ; do we want buffers at FFFF ? + jz setup_b40 + call SetupHMA ; make sure HMA chain is established + pop cx ! push cx ; CX = bytes wanted + mov dx,0FFFFh ; anywhere is OK + call AllocHMA ; ES:DI -> allocated data +setup_b40: + pop ax ; AX = bytes wanted + pop dx ; DX = size of a buffer + pop cx ; CX = number of buffer + jnc setup_b70 ; if CY clear ES:DI -> our space + + shr ax,1 ! shr ax,1 + shr ax,1 ! shr ax,1 + inc ax ; convert from bytes to para's + push dx + mov dl,'B' ; allocate as a Buffer + test buffersIn,BUFFERS_IN_UMB + jz setup_b50 ; allocation from UMB's OK ? + call alloc_hiseg ; yes, try and allocate memory there + jnc setup_b60 +setup_b50: + call alloc_seg ; allocate memory in bottom 640 K +setup_b60: + pop dx + mov es,ax ; ES = segment + xor di,di ; ES:DI -> start of buffer +setup_b70: +; Buffer space for CX buffers, of size DX, allocated at ES:DI + mov si,di ; remember where 1st buffer is +setup_b80: + push cx + mov bx,di ; BX = current buffer + mov cx,dx + xor ax,ax + rep stosb ; zero the buffer, ES:DI -> next buffer + mov es:BCB_DRV[bx],0FFh ; invalidate buffer + mov es:BCB_NEXT[bx],di ; point to where "next" will be + mov ax,bx + sub ax,dx ; work out what our previous was + mov es:BCB_PREV[bx],ax ; and point to it + pop cx + loop setup_b80 ; do them all + + mov es:BCB_NEXT[bx],si ; the last's "next" is our first buffer + mov es:BCB_PREV[si],bx ; the first's "previous" is our last + mov ax,es ; AX:SI -> 1st buffer + les bx,func52_ptr ; ES:BX -> internal data structure + mov es:F52_BCBOFF[bx],si + mov es:F52_BCBSEG[bx],ax ; fixup buffer pointers + mov es:word ptr F52_BUF_INFO[bx],si + mov es:word ptr F52_BUF_INFO+2[bx],ax + inc ax ; seg FFFF ? + jnz setup_b90 ; skip if not + mov es:F52_HMAFLAG[bx],1 ; buffers are in HMA + mov ax,es:F52_SECSIZE[bx] + add ax,15 + mov cl,4 + shr ax,cl ; convert to para size + mov dl,'B' ; allocate as a Buffer + call alloc_seg ; allocate a deblocking buffer + mov es:F52_DEBLOCK[bx],ax + les bx,drdos_ptr ; ES:BX -> data area + mov es:DRDOS_DEBLOCK[bx],ax ; of deblocking buffer +setup_b90: + ret + +setup_doshndl: + push es + les bx,func52_ptr ; Internal Data Pointer + lea bx,F52_FILEPTR[bx] ; Start of Handle List + mov cx,num_files ; Number of DOS Handles + add cx,num_fcbs ; + some for FCB's + cmp cx,255 + jbe setup_dh10 + mov cx,255 ; maximum IFN is 255 +setup_dh10: + cmp es:DCNTRL_DSOFF[bx],0FFFFh ; Last entry ? + je setup_dh20 ; no, loop round again + les bx,es:DCNTRL_DSADD[bx] ; Get the Next Entry + sub cx,es:DCNTRL_COUNT[bx] ; Update the count + jc setup_dh30 ; going negative isn't allowed + jmps setup_dh10 + +setup_dh20: + jcxz setup_dh30 ; any left to allocate ? + + mov ax,DHNDL_LEN ; How many bytes do we need + mul cx ; for the structure + mov dx,ax ; including the control + + add ax,DCNTRL_LEN+15 ; Ensure the new structure is + shr ax,1 ! shr ax,1 ; a paragraph value + shr ax,1 ! shr ax,1 ; allocate some memory + mov dl,'F' ; allocate for Files + call alloc_seg + + mov es:DCNTRL_DSOFF[bx],0 ; link the new seg + mov es:DCNTRL_DSSEG[bx],ax ; to the end of the list + +; We can now initialise the new structure + les bx,es:DCNTRL_DSADD[bx] ; Get the New Entry + mov es:DCNTRL_DSOFF[bx],0FFFFh ; terminate the list + mov es:DCNTRL_DSSEG[bx],0FFFFh ; with -1,-1 + mov es:DCNTRL_COUNT[bx],cx ; Number of elements +; Now zero the tables + mov ax,DHNDL_LEN ; How many bytes do we have + mul cx ; with this number of elements + mov cx,ax ; in the structure + lea di,DCNTRL_LEN[bx] ; Zero the contents of the + sub al,al ; structure + rep stosb + +setup_dh30: + pop es + ret + + +setup_drives: + mov al,next_drv ; AL = # of drives supported + push es ! push bx + les bx,func52_ptr ; ES:BX -> base of DOS variables + mov es:F52_PHYDRV[bx],al ; set # of Physical drives installed + mov es:F52_LASTDRV[bx],al ; set # of Logical drives installed + pop bx ! pop es + ret + + +setup_fopen: ; allocate file hashing information +;----------- + les bx,drdos_ptr + mov ax,num_fopen ; get # of hashed directory entries + cmp ax,-1 ; has it been set yet ? + jne setup_fopen10 ; yes, then leave it alone + mov ax,DEF_NUM_FOPEN + cmp es:DRDOS_HIMEM_ROOT[bx],0; do we have a high memory chain ? + jne setup_fopen10 ; high memory means no TPA hit + xor ax,ax ; keep things small otherwise +setup_fopen10: + xor dx,dx ; AX/DX = 32 bit # of entries + mov si,max_clsize ; max. cluster size + mov cl,5 ; 32 byte per directory entry + shr si,cl ; SI = directory entries per cluster + add ax,si ; round up count to multiple of cluster + dec ax + div si ; AX = # of hashed blocks + mov cx,ax + jcxz setup_fopen90 ; skip if hashing disabled + + mov es:DRDOS_HASHMAX[bx],si ; maximum # dir entries allowed + + shl si,1 ; SI = bytes required for data + lea si,HCB_DATA[si] ; + control information + mul si ; AX bytes of data required + test dx,dx + jnz setup_fopen90 ; overflow (shouldn't happen) + +; Allocate CX HCB_'s of size SI bytes, AX bytes in total + + mov bx,es:DRDOS_HIMEM_ROOT[bx]; do we have a high memory chain ? + test bx,bx ; zero indicates we don't + jz setup_fopen30 + mov dx,0FFFFh ; use the magic FFFF segment + mov es,dx + cmp ax,es:2[bx] ; is there enough room ? + ja setup_fopen30 ; no, forget try conventinal memory + sub es:2[bx],ax ; else allocate the memory + mov di,es:2[bx] ; get base+length + add di,bx ; = our allocation + mov ax,es:2[bx] ; if the section left is under + cmp ax,2*WORD ; 2 words discard it + jae setup_fopen20 ; as we may overwrite size/link + mov ax,es:[bx] ; get next entry + les bx,drdos_ptr ; and make it the new himem root + mov es:DRDOS_HIMEM_ROOT[bx],ax +setup_fopen20: + xchg ax,dx ; AX = FFFF + jmps setup_fopen40 ; AX:DI -> data block allocated + +setup_fopen30: + shr ax,1 ; convert size to para's + shr ax,1 + shr ax,1 + shr ax,1 + inc ax ; allow for rounding + mov dl,'E' + call alloc_hiseg ; allocate it para aligned + dec ax ; zero offset terminates the chain + mov di,10h ; so start with a non-zero offset +; jmps setup_fopen40 ; AX:DI -> data block allocated + +setup_fopen40: +; setup CX HCB_'s of size SI at AX:DI + les bx,drdos_ptr + mov es:DRDOS_HASHOFF[bx],di + mov es:DRDOS_HASHSEG[bx],ax + mov es,ax + +setup_fopen50: + mov es:HCB_DRV[di],-1 ; discard the HCB initially + mov bx,di ; remember where it is + add di,si ; onto next HCB_ + mov es:HCB_LINK[bx],di ; link it to previous HCB_ + loop setup_fopen50 ; allocate all hash control blocks + mov es:HCB_LINK[bx],0 ; zero terminate the list +setup_fopen90: ; all HCBs done, return + push cs + pop es ; back to 8080 model + ret + + + Public whitespace + +whitespace: + lodsb ; Skip any White Space in the + cmp al,' ' ! jz whitespace ; CR/LF terminated string + cmp al,TAB ! jz whitespace + dec si + ret + + Public build_cmd_tail +build_cmd_tail: + push ds ! pop es + mov cx,length cfg_buffer - 3 ; (leave room for 3 extra chars) + mov di,offset cfg_buffer +build_cl1: + lodsb ; Copy the device name + cmp al,' ' ; until a Control char (end of line) + jbe build_cl2 ; or a Space (end of name) + cmp al,'/' ; Also stop scanning when a switch + je build_cl2 ; character is detected + stosb + loop build_cl1 + mov al,CR ; indicate we can go no more.... +build_cl2: + cmp al,CR ; it it really the end ? + mov al,' ' ; now insert a space character + stosb + je build_cl_exit ; CR meant it's time to go + dec si ; rewind the source one character +build_cl3: + lodsb ; Copy the tail + cmp al,CR ; until we find a CR + je build_cl4 ; at the end of the line + stosb + loop build_cl3 + mov al,CR ; no more room, so terminate +build_cl4: + stosb +build_cl_exit: + mov al,LF ; now insert the terminating linefeed + stosb ; at the end of the buffer + mov si,offset cfg_buffer + ret + +save_vecs: +; save interrupt vectors so we can restore if device init fails + push ds ! push es + push si ! push di ! push cx + mov cx,(length vec_save_buf)*2 ; CX = words to save + xor si,si + mov ds,si ; DS:SI -> vectors to save + push cs ! pop es + mov di,offset vec_save_buf ; ES:DI -> save area + rep movsw ; save them + pop cx ! pop di ! pop si + pop es ! pop ds + ret + +restore_vecs: +; replace interrupt vectors after a dd_init fails + push ds ! push es + push si ! push di ! push cx + mov cx,length vec_save_buf ; CX = vectors to restore + push cs ! pop ds + mov si,offset vec_save_buf ; DS:SI -> save area + xor di,di + mov es,di ; ES:DI -> vectors to restore +rest_vec1: + mov ax,es:2[di] ; get updated vector + cmp ax,mem_current ; below attempted driver? + jb rest_vec2 ; yes, don't zap it + cmp ax,mem_max ; above attempted driver? + jae rest_vec2 ; yes, don't zap it + movsw ! movsw ; else restore vector + jmps rest_vec3 ; overwritten by driver +rest_vec2: + add si,dword ; skip vector in source + add di,dword ; and in destination +rest_vec3: + loop rest_vec1 ; next vector + pop cx ! pop di ! pop si + pop es ! pop ds + ret + + +INITDATA DSEG 'INITDATA' + + extrn shell:byte ; Default Command Processor + extrn shell_cline:byte ; Default Command Line + extrn num_files:word ; default # of file handles + extrn num_fcbs:word ; default # of fcb file handles + extrn num_fopen:word ; default value for fast open + extrn country_code:word ; Requested Country Code (Default US) + extrn num_stacks:word ; # hardware stacks wanted + extrn stack_size:word ; size of a hardware stack + + + extrn mem_current:word ; Current Load Address + extrn mem_max:word ; Top of Available Memory + extrn init_dseg:word ; Current init Data Segment + + extrn dos_dseg:word + extrn bios_seg:word + extrn func52_ptr:dword + extrn drdos_ptr:dword + extrn res_ddsc_ptr:dword + + + + +include initmsgs.def ; Include TFT Header File + + + extrn preload_drv:byte + extrn init_drv:byte ; the initial boot drive + + Public dev_load_seg, dev_reloc_seg, dev_epb, dev_name, dev_count + Public rel_unit, dev_epb + Public strategy_off, strategy_seg, interrupt_off, interrupt_seg, request_hdr + Public next_drv, strategy_seg, strategy, interrupt + Public strategy_seg, condev_off, condev_seg, clkdev_off, clkdev_seg + Public num_blkdev, blkdev_table, next_drv, max_secsize + Public max_clsize, init_buf, num_read_ahead_buf + Public buffersIn, history_flg, history_size + Public dbcs_tbl, ctry_info, boot_device, boot_drv, resdev_chain + + +history_flg db 0 ; Disable history buffers to save RAM +history_size dw 256 ; When enabled 2*history size are used for bufs + +cfg_buffer rb CFG_BUF_LEN ; extra termination for buggy Windows + db CR,LF,0 ; device driver - give it CR/LF to hit + +init_buf db MIN_NUM_BUFFS ; default # of buffers +num_read_ahead_buf db DEF_READ_AHEAD ; default # of read-ahead +buffersIn db 0 ; default is low + +dev_count db 0 ; count of new drives (used by preload) +next_drv db 0 ; Next Drive to Allocate +num_blkdev dw 0 ; # of block devices installed + +boot_device dw 0,0 ; ptr to boot device +boot_drv db 0 ; and the sub unit number + +max_secsize dw 0 ; max. sector size encountered +max_clsize dw 0 ; max. cluster size encountered + +; Do not change the order of the next four words: +clkdev_off rw 1 ; clock device driver +clkdev_seg rw 1 +condev_off rw 1 ; console device driver +condev_seg rw 1 + +bpbptr rd 0 ; temporary BPB pointer +bpboff rw 1 +bpbseg rw 1 + +devptr rd 0 ; temporary device header pointer +devoff rw 1 +devseg rw 1 + +resdev_chain rd 0 ; head of chain for resident device +resdev_off dw -1 ; drivers +resdev_seg dw -1 + +abs_unit dw 0 ; absolute unit # +rel_unit dw 0 ; relative unit # + +blkdev_table rb BLKDEV_LENGTH*26 ; save block device driver addr. here + +; +; Variable for the FUNC_DEVICE and DEV_INIT sub routines +; + +strategy rd 0 ; Device Strategy Entry Point +strategy_off rw 1 ; Offset +strategy_seg rw 1 ; Segment Address + +interrupt rd 0 ; Device Entry Point +interrupt_off rw 1 ; Offset +interrupt_seg rw 1 ; Segment Address + +dev_root rd 0 ; Pointer to Root of Device List +dev_offset rw 1 ; Offset of First Device +dev_segment rw 1 ; Segment of First Device + +request_hdr rb RH_SIZE ; DOS Request Header + +dev_name rb MAX_FILELEN + +dev_epb rw 0 +dev_load_seg rw 1 ; Load Segment for Device Driver +dev_reloc_seg rw 1 ; Relocation Factor to be Applied + +; +; A number of routines share this common buffer as they are never required +; at the same time. The current clients are - +; +; BDOSLDR.A86: a sector buffer for boot load of IBMDOS +; CONFIG.A86: vector save buffer (during devicehigh) +; NLSFUNC.A86: scratch area for country info + + Public sector_buffer +sector_buffer rb 0 +; rb 512 ; we need to read a single sector + + Public nls_temp_area +nls_temp_area rb 0 ; NLS buffer can be shared with +; rb 258 ; vec_save_buf as they are never + ; used together + + +vec_save_buf rd 256 ; reserve space to save int vectors + +dbcs_buf rb 1 ; BDOS puts a 7 here +dbcs_tbl rd 1 ; pointer to DBCS table in BDOS + +ctry_info rb CI_LENGTH ; country information + +num_buf dw 0 ; # of buffers allocated + + +; The following are used for detecting old bus master controllers: + +removableMediaRequest db 13 ; length of request + db 0 ; unit + db 15 ; removable media check command + dw 0 ; status + rb 8 ; reserved bytes + + +readRequest db 30 ; length of request + db 0 ; unit + db 4 ; read command + dw 0 ; status + rb 8 ; reserved bytes + db 0F8h ; media ID + dw 0,0 ; buffer address + dw 1 ; read one sector + dw 0FFFFh ; use big sector read + dw 0,0 ; Volume ID + dw 1,0 ; starting sector zero + + +UpperMemoryBuffer dw 0 + +numUnits dw 0 + +deblockPointer rd 0 +deblockOffset dw 0 +deblockSeg dw 0 + + Public DeblockSetByUser +DeblockSetByUser db FALSE + + + end diff --git a/IBMBIO/CONFIG.EQU b/IBMBIO/CONFIG.EQU new file mode 100644 index 0000000..68bdd99 --- /dev/null +++ b/IBMBIO/CONFIG.EQU @@ -0,0 +1,124 @@ +; File : $CONFIG.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG + + +DOS5 equ 0FFFFh + +if DOS5 +MOVE_DOWN equ 1800h ; start relocated code 96K down +else +MOVE_DOWN equ 2500h ; start relocated code 148K down +endif + +NUM_BUFFS equ 4 +SIZEOF_BUFFS equ 1024+32 ; allow for large sectors during init + +CONFIG_BUF equ ds:byte ptr .0 +CONFIG_BUF_SIZE equ 8*1024 ; CONFIG.SYS read in this size chunks +INIT_BUFFERS equ CONFIG_BUF+CONFIG_BUF_SIZE +if DOS5 +INIT_BUFFERS_SIZE equ NUM_BUFFS*SIZEOF_BUFFS + ; reserve space for init disk buffers +TEMP_LDT equ INIT_BUFFERS+INIT_BUFFERS_SIZE + ; space for temp LDT's at CONFIG time +TEMP_LDT_SIZE equ ((26*58h)/16)*16+20h +else +INIT_BUFFERS_SIZE equ NUM_BUFFS*(512+16) ; reserve space for init disk buffers +TEMP_LDT equ INIT_BUFFERS+INIT_BUFFERS_SIZE + ; space for temp LDT's at CONFIG time +TEMP_LDT_SIZE equ ((26*51h)/16)*16+20h +endif +DYNAMIC_DATA_END equ TEMP_LDT+TEMP_LDT_SIZE + +BLKDEV_LENGTH equ 9 ; # of bytes per block device init entry + +MAX_PATHLEN equ 65 ; Maximum Path Length +MAX_FILELEN equ 80 ; Maximum File Length +EOF equ 01ah ; End of File Marker + +MIN_NUM_BUFFS equ 3 ; minimum # of disk buffers required +MAX_NUM_BUFFS equ 99 ; maximum # of disk buffers supported +DEF_NUM_BUFFS equ 1 ; 1 during config to so most go hi + +MIN_READ_AHEAD equ 1 ; minimum read-ahead +MAX_READ_AHEAD equ 99 ; maximum read-ahead +DEF_READ_AHEAD equ 0 ; default no read-ahead +; +; DEF_NUM_FILES must be less than MIN_NUM_FILES in order to +; force two file structure allocations Windows will FAIL if this +; is not TRUE. +; +MIN_NUM_FILES equ 8 ; minimum # of files required +MAX_NUM_FILES equ 255 ; maximum # of files supported +DEF_NUM_FILES equ 1 ; default # of files (+4 FCBS) + +MIN_NUM_FCBS equ 0 ; minimum # of fcbs required +MAX_NUM_FCBS equ 255 ; maximum # of fcbs supported +DEF_NUM_FCBS equ 4 ; default # of fcb handles + +MIN_NUM_FOPEN equ 0 ; minimum # of hashed files required +MAX_NUM_FOPEN equ 32768 ; maximum # of hashed files supported +DEF_NUM_FOPEN equ 4096 ; default # of files on normal system + +MIN_NUM_STACKS equ 8 ; on hardware interrupts swap stacks +MAX_NUM_STACKS equ 64 ; to a dynamically allocated one +DEF_NUM_STACKS equ 0 ; zero is a special case - no swapping + +MIN_SIZE_STACK equ 32 ; the dynamic stacks are this size +MAX_SIZE_STACK equ 512 +DEF_SIZE_STACK equ 128 ; default size + +CFG_BUF_LEN equ 256 ; Length of CONFIG.SYS line buffer + +DEF_COUNTRY equ 1 ; USA +DEF_CODEPAGE equ 0 ; No codepage + +DELWATCH equ 0FFFFh + +RLF_ENHANCED equ 0000$0001b ; Enhanced features are on +RLF_INS equ 0000$0010b ; Insert Flag +RLF_SEARCH equ 0000$0100b ; Search mode on +RLF_MATCH equ 0000$1000b ; We are matching a command + +BUFFERS_IN_HMA equ 0000$0001b +BUFFERS_IN_UMB equ 0000$0010b + +DMD_ID equ es:byte ptr .0 ; id code ('M' or 'Z') +DMD_PSP equ es:word ptr .1 ; owner of memory block +DMD_LEN equ es:word ptr .3 ; length of memory block +DMD_NAME equ es:byte ptr .8 ; ASCIIZ name field +DMD_NAME_LEN equ 8 ; 8 Bytes long +IDM equ 'M' ; not last id code +IDZ equ 'Z' ; last id code + diff --git a/IBMBIO/CONFSTUB.A86 b/IBMBIO/CONFSTUB.A86 new file mode 100644 index 0000000..8dfd677 --- /dev/null +++ b/IBMBIO/CONFSTUB.A86 @@ -0,0 +1,45 @@ +; File : $CONFSTUB.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG + +CGROUP group INITCODE +INITCODE CSEG PARA 'INITCODE' + + Public config_process +config_process: ; Process CONFIG.SYS + ret + + Public country_error +country_error: + ret + end diff --git a/IBMBIO/CONSOLE.ASM b/IBMBIO/CONSOLE.ASM new file mode 100644 index 0000000..3644b94 --- /dev/null +++ b/IBMBIO/CONSOLE.ASM @@ -0,0 +1,307 @@ +; File : $Workfile$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; CONSOLE.ASM 1.8 93/07/22 19:43:16 +; switch over to REQUEST.EQU +; CONSOLE.ASM 1.7 93/07/19 18:57:15 +; Add header +; +; ENDLOG + + include BIOSGRPS.EQU + include DRMACROS.EQU ; standard DR macros + include IBMROS.EQU ; ROM BIOS equates + include REQUEST.EQU ; request header equates + include DRIVER.EQU ; device driver equates + +page +CGROUP group CODE, RCODE, ICODE + +CG equ offset CGROUP + + Assume CS:CGROUP, DS:CGROUP, ES:CGROUP, SS:CGROUP + +CODE segment 'CODE' + +INSERT_ACTIVE equ 2 ; set if cmdline insert active + + extrn endbios:word ; for device driver INIT function + extrn FastConsole:far ; console output vector + extrn ControlBreak:far ; ^C program abort + extrn local_flag:byte + extrn local_char:byte + +CODE ends + +RCODE segment 'RCODE' + +; Device driver function table + + Public ConsoleTable + +ConsoleTable: + db 14 ; Last supported command + dw CG:dd_init ; 0-initialize driver + dw CG:dd_error ; 1-media change check (disks only) + dw CG:dd_error ; 2-build BPB (disks only) + dw CG:dd_inioctl ; 3-IOCTL string input + dw CG:dd_input ; 4-input + dw CG:dd_poll ; 5-nondestructive input (char only) + dw CG:dd_instat ; 6-input status (char only) + dw CG:dd_inflush ; 7-input flush + dw CG:dd_output ; 8-output + dw CG:dd_output ; 9-output with verify + dw CG:dd_outstat ; 10-output status (char only) + dw CG:dd_outflush ; 11-output flush (char only) + dw CG:dd_outioctl ; 12-IOCTL string output + dw CG:dd_open ; 13-device open + dw CG:dd_close ; 14-device close + + + Assume DS:CGROUP, ES:Nothing, SS:Nothing + +page +driver proc near + +dd_outioctl: +;----------- + mov cx,es:RH4_COUNT[bx] ; get # of characters to output + cmp cx,2 ; is it what we expect ? + jne dd_error ; no, bail out + push ds + lds si,es:RH4_BUFFER[bx] ; DS:SI -> buffer + lodsw ; get the data + pop ds + xchg ax,si ; save data in SI + mov ah,3 ; read cursor position/type + mov bh,0 ; for page zero + int VIDEO_INT + and ch,0c0h ; make cursor start line = 0 + mov al,cl ; AL = bottom line of cursor + dec ax ; AL = bottom line - 1 + test si,INSERT_ACTIVE + jz dd_outioctl10 + shr al,1 ; Insert active is 1/2 size block +dd_outioctl10: + or ch,al ; cursor start line is now here + mov ah,1 ; set cursor type + int VIDEO_INT + ret + +dd_inioctl: +;---------- +; jmp dd_error ; input not supported + +dd_error: ; used for all unsupported driver functions +;-------- + mov ax,RHS_ERROR+3 ; "invalid command" error + ret + + +poll_c1: + mov ah,0 ; eat the next character + int KEYBOARD_INT ; take it out of ROS buffer + ; and check again +poll_char: +;--------- +; exit: ZF = 1 => no character ready +; ZF = 0 => AL = character + + mov al,local_char ; get the local character + cmp local_flag,TRUE ; do we have local character? + je poll_c4 ; no, check ROS keyboard status + mov ah,1 ; get keyboard status (and character) + int KEYBOARD_INT ; read character from keyboard + jz input9 ; skip if no character there + test ax,ax ; test if we got Ctrl-Brk + jz poll_c1 ; and eat it if we have +poll_c3: ; we've got a character + cmp ax,7200h ; is this Ctrl-PrtSc? + jne poll_c4 + mov al,'P'-40h ; convert to ^P character +poll_c4: ; return the character in AL + or ah,TRUE ; indicate "ready" status + ret + +char_read: +;--------- + cmp local_flag,TRUE ; do we have local character? + je rdchr3 ; handle that specially + mov ah,0 + int KEYBOARD_INT ; read character from keyboard + test ax,ax ; test if we got Ctrl-Brk + jz char_read ; retry in that case + cmp ax,7200h ; is this Ctrl-PrtSc? + jne rdchr1 ; skip if any other + mov al,'P'-40h ; convert to ^P character + ret ; and return it +rdchr1: ; else it is normal or function key + test al,al ; test if function key + jnz rdchr2 ; skip if normal character + mov local_flag,TRUE ; else return scan code as next + mov local_char,ah ; character from next INPUT +rdchr2: ; return the character in AL + ret +rdchr3: + mov local_flag,FALSE ; tell them buffer is invalid + mov al,local_char ; get the local charcater + ret ; and return it + + page +dd_input: ; 4-input +;-------- + mov cx,es:RH4_COUNT[bx] ; get # of characters to output + jcxz input9 ; return if nothing to input + push es ; save ES (-> request header!) + les di,es:RH4_BUFFER[bx] ; get address of string to input +input1: + call char_read ; read 8-bit character + stosb ; store it in input buffer + loop input1 ; repeat for all characters + pop es +input9: +; sub ax,ax +; ret + +dd_outstat: ; 10-output status (char only) +;---------- ; always ready, return no busy + +dd_outflush: ; 11-output flush (char only) +;----------- ; unbuffered, perform no operation + +dd_open: ; 13-device open +;------- ; no operation + +dd_close: ; 14-device close +;-------- ; no operation + sub ax,ax + ret + +dd_poll: ; 5-nondestructive input (char only) +;------- + call poll_char ; check keyboard status + jz dd_instat20 + mov es:RH5_CHAR[bx],al ; return the character +dd_poll10: + sub ax,ax + ret + +dd_instat: ; 6-input status (char only) +;--------- + call poll_char ; check keyboard status + jnz dd_poll10 +dd_instat20: + mov ax,RHS_BUSY + ret + + +dd_inflush: ; 7-input flush +;--------- + call poll_char ; check keyboard status + jz dd_poll10 ; skip if not ready + call char_read ; else read next character + jmps dd_inflush ; repeat until buffer empty + +dd_output: ; 8-output +;--------- + mov cx,es:RH4_COUNT[bx] ; get # of characters to output + jcxz output9 ; return if nothing to output + push es ; save ES (-> request header!) + les si,es:RH4_BUFFER[bx] ; get address of string to output +output1: + lods es:byte ptr [si] ; get next character to output + pushf ; stack as per Int 29 + db 09Ah ; CALLF to our fastconsole entry + dw CG:FastConsole + dw 70h + loop output1 ; repeat for all characters + pop es +output9: + sub ax,ax + ret + + +driver endp + +RCODE ends ; end of device driver code + +page + +ICODE segment 'ICODE' ; initialization code + +dd_init: ; 0-initialize driver +;------- + + push es + sub ax,ax + mov es,ax + mov ax,CG:FastConsole ; console output vector + mov di,FASTCON_INT*4 ; setup fast single character + stosw ; console output vector + mov ax,ds ; (identified by DA_SPECIAL) + stosw + mov di,CTRLBRK_INT*4 ; setup Ctrl-Break ROS vector + mov ax,CG:ControlBreak ; for ^C program abort + stosw ; when a character has already + mov ax,ds ; been typed into the ROS buffer + stosw + pop es + +ifdef JAPAN + + mov ax,05000H ; Japanese mode (AX machine) + mov bx,81 ; 081 : Japanese mode select + int VIDEO_INT ; + + mov ax,05000h ; Japanese mode (AX machine) + mov bx,81 ; 081 : Japanese mode select + int KEYBOARD_INT ; + +endif + + mov ax,14*256 + 13 ; output a carriage return + int VIDEO_INT + mov ax,14*256 + 10 ; output a line feed + int VIDEO_INT + + les bx,REQUEST[bp] ; ES:BX -> request header + + mov ax,endbios ; get last resident byte in BIOS + mov es:RH0_RESIDENT[bx],ax ; set end of device driver + mov es:RH0_RESIDENT+2[bx],ds + + sub ax,ax ; initialization succeeded + ret + +ICODE ends + +end diff --git a/IBMBIO/COUNTRY.DEF b/IBMBIO/COUNTRY.DEF new file mode 100644 index 0000000..3ea7880 --- /dev/null +++ b/IBMBIO/COUNTRY.DEF @@ -0,0 +1,73 @@ +; File : $COUNTRY.DEF$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG + +US_DATE equ 0 ; American Date Format mm/dd/yy +EURO_DATE equ 1 ; European Date Format dd/mm/yy +JAP_DATE equ 2 ; Japanese Date Format yy/mm/dd + +CLOCK_12 equ 0 ; 12 Hour Clock Time Format +CLOCK_24 equ 1 ; 24 Hour Clock Time Format + +CI_CODE equ word ptr 0FFFCh ; Country Code +CI_CODEPAGE equ word ptr 0FFFEh ; Code page +CI_DATEFMT equ word ptr 0 ; Date Format +CI_CURRENCY equ byte ptr 2 ; Currency Symbols +CI_THOUSANDS equ byte ptr 7 ; Thousands Separator +CI_DECIMAL equ byte ptr 9 ; Decimal Separator +CI_DATESEP equ byte ptr 11 ; Date Separator +CI_TIMESEP equ byte ptr 13 ; Time Separator +CI_CURFMT equ byte ptr 15 ; Currency Format +CI_CURDIGITS equ byte ptr 16 ; Significant Currency Digits +CI_TIMEFMT equ byte ptr 17 ; Time Format +CI_CASEOFF equ word ptr 18 ; Case Translation Offset +CI_CASESEG equ word ptr 20 ; Case Translation Segment +CI_DATASEP equ byte ptr 22 ; Data List Separator +CI_STATICLEN equ 24 ; Static Country Data Length +CI_LENGTH equ 32 ; Total Country Data Length + +EXI_ID equ byte ptr 0 ; Information ID +EXI_TBLOFF equ word ptr 1 ; Table Offset +EXI_TBLSEG equ word ptr 3 ; Table Segment + +EXI_ID1 equ byte ptr 0 ; 6501 Info ID (why move it?!) +EXI_LENGTH equ word ptr 1 ; 6501 Table Length +EXI_DATA_LEN equ 3 ; 6501 Country Data + +EXCI_CUR_COUNTRY equ word ptr 0 ; Current Country +EXCI_CUR_CP equ word ptr 2 ; Current Codepage +EXCI_CI_DATAOFF equ 4 ; Start of CI_ data + +EXCI_STATLEN equ CI_STATICLEN+4 ; Static Ext Country Info +EXCI_MAXLEN equ EXCI_STATLEN+10+EXI_DATA_LEN ; Max Ext Country Info + diff --git a/IBMBIO/DISK.ASM b/IBMBIO/DISK.ASM new file mode 100644 index 0000000..eaa16a2 --- /dev/null +++ b/IBMBIO/DISK.ASM @@ -0,0 +1,2618 @@ +; File : $DISK.ASM$ +; +; Description : +; +; Original Author : +; +; Last Edited By : $Author: RGROSS$ +; +;-----------------------------------------------------------------------; +; Copyright Unpublished Work of Novell, Inc. All Rights Reserved. +; +; THIS WORK IS AN UNPUBLISHED WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF NOVELL, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) NOVELL, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN NOVELL, INC. WHO +; HAVE ENTERED INTO APPROPRIATE LICENSE AGREEMENTS. NO PART OF THIS +; WORK MAY BE USED, PRACTICED, PERFORMED, COPIED, DISTRIBUTED, +; REVISED, MODIFIED, TRANSLATED, ABRIDGED, CONDENSED, EXPANDED, +; COLLECTED, COMPILED, LINKED, RECAST, TRANSFORMED OR ADAPTED +; WITHOUT THE PRIOR WRITTEN CONSENT OF NOVELL, INC. ANY USE OR +; EXPLOITATION OF THIS WORK WITHOUT AUTHORIZATION COULD SUBJECT +; THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log: $ +; DISK.ASM 1.1 93/11/18 17:20:12 RGROSS +; +; DISK.ASM 1.41 93/11/18 17:20:25 IJACK +; +; DISK.ASM 1.40 93/11/10 00:28:12 IJACK +; Format changes so you can format your hard disk +; DISK.ASM 1.39 93/11/08 21:47:25 IJACK +; Add hidden sectors to ioctl format etc of hard disks +; DISK.ASM 1.38 93/11/02 16:09:29 IJACK +; Always zero BPB_HIDDEN_SECTORS on floppies - problem with PCW free disk which +; has garbage in those fields. +; DISK.ASM 1.37 93/10/18 17:33:18 IJACK +; format c: fix +; DISK.ASM 1.36 93/10/11 18:37:24 IJACK +; media-change checks serial-numbers for 3.5" disks +; DISK.ASM 1.35 93/10/06 22:09:16 IJACK +; vec_save extrn replaced by orgInt13 extrn +; DISK.ASM 1.34 93/09/03 20:13:32 IJACK +; Fix bug in disk formatting +; DISK.ASM 1.33 93/09/01 17:40:31 IJACK +; update UDSC_TIMER after media check forced by drive change +; (DBASE IV slow installation problem) +; DISK.ASM 1.32 93/08/12 15:33:07 IJACK +; Handle DMA error from multi-track read (ancient PC-XT hard disk) +; DISK.ASM 1.31 93/08/03 15:29:01 IJACK +; use serial numbers for media change detection +; DISK.ASM 1.30 93/08/02 18:44:50 IJACK +; don't trust the changeline if switching drives +; DISK.ASM 1.29 93/08/02 18:38:19 IJACK +; +; DISK.ASM 1.28 93/08/02 14:47:38 IJACK +; +; DISK.ASM 1.27 93/07/29 21:00:24 IJACK +; get rid of genpb_ptr and genpb_minor +; DISK.ASM 1.26 93/07/26 21:18:25 IJACK +; Correctly return UDSC_ root from Int 2F/0803 +; DISK.ASM 1.25 93/07/26 18:07:21 IJACK +; Switch ms-windows to full screen when prompting for disk +; DISK.ASM 1.24 93/07/23 17:34:27 IJACK +; fix floppy/driver.sys support +; DISK.ASM 1.23 93/07/22 20:37:42 IJACK +; +; DISK.ASM 1.22 93/07/22 19:43:46 IJACK +; switch over to REQUEST.EQU +; change floppy drive order, add get/set serial number +; DISK.ASM 1.21 93/07/19 18:57:21 IJACK +; Add header +; +; ENDLOG + + include BIOSGRPS.EQU + include DRMACROS.EQU ; standard DR macros + include IBMROS.EQU ; ROM BIOS equates + include REQUEST.EQU ; request header equates + include BPB.EQU ; BIOS parameter block equates + include UDSC.EQU ; unit descriptor equates + include DRIVER.EQU ; device driver equates + + +int_____DISK_INT macro + call Int13 + endm + +FASTSETTLE equ FALSE ; disable "head settle == 0 ms" + +RETRY_MAX equ 3 ; do 3 retries if we get an error +MAX_SPT equ 40 ; maximum sectors per track + +SECSIZE equ 512 +IDOFF equ SECSIZE-2 ; last word in boot sector is ID +PTOFF equ IDOFF-40h ; 4*16 bytes for partition def's + +DOS20_ID equ 1 ; DOS 2.0 partition, < 4086 clusters +DOS30_ID equ 4 ; DOS 3.0 partition, < 65536 sectors +DOSEX_ID equ 5 ; DOS 3.3 extended partition +DOS331_ID equ 6 ; COMPAQ DOS 3.31 partition > 32 Mb + +; Now for the secure partition types +SEC_ID equ 0C0h ; New DR secure partition types +SEC_ID2 equ 0D0h ; Old DR secure partition types + +page +CGROUP group CODE, RCODE, ICODE, RESBIOS, IDATA + +CG equ offset CGROUP + + Assume CS:CGROUP, DS:CGROUP, ES:Nothing, SS:Nothing + +IVECT segment at 0000h + + org 0013h*4 +i13off dw ? +i13seg dw ? + + org 001Eh*4 +i1eptr dd ? + + org 002Fh*4 +i2Foff dw ? +i2Fseg dw ? + + org 0472h +reset_flag dw ? + + org 0504h +dual_byte db ? ; multiple drive byte at 50:4 + +IVECT ends + +ROS segment at 0F000h + org 0FFF0h +reset proc far +reset endp +ROS ends + +CODE segment 'CODE' + + extrn endbios:word ; for device driver INIT function + extrn read_system_ticks:near ; get system tick count in CX/DX + extrn Int13Trap:near + extrn Int2FTrap:near + extrn orgInt13:dword + extrn i13pointer:dword + extrn i13off_save:word + extrn i13seg_save:word + + extrn NumDiskUnits:byte + extrn DeblockSeg:word + extrn local_parms:byte + extrn parms_spt:byte + extrn parms_gpl:byte + extrn local_buffer:byte + extrn local_pt:word + extrn local_id:word + extrn layout_table:word + extrn bpbs:word + extrn bpb160:byte + extrn bpb360:byte + extrn bpb720:byte + extrn NBPBS:abs + extrn bpbtbl:word + extrn req_off:word + extrn req_seg:word + + +udsc_root label dword + dw -1,-1 + +orig_int1e_off dw 522h +orig_int1e_seg dw 0 + +new_int1e_off dw 522h +new_int1e_seg dw 0 + + + Public i13_AX +i13_AX label word +i13_size db ? ; number of sectors to xfer +i13_op db ? ; Int13 Operation +i13_dma_ptr label dword +i13_dma_off dw ? +i13_dma_seg dw ? + +activeRosUnit db ? ; currently active ROS unit + +include biosmsgs.def ; Include TFT Header File + + +ifdef JAPAN + extrn disk_msgA_jpn :byte + extrn disk_msgB_jpn :byte +endif + +;disk_msgA db 13,10,'Insert disk for drive ' +;disk_msgB db ': any press any key when ready ', 0 + +page + Assume DS:nothing, SS:nothing, ES:nothing + +CODE ends + +RCODE segment 'RCODE' + + extrn DataSegment:word + +even +Int13 proc near + clc + push bp + int DISK_INT + pop bp + ret +Int13 endp + +ros_errors db 03h, 80h, 08h, 10h, 40h, 04h, 06h, 00h +dos_errors db 00h, 02h, 04h, 04h, 06h, 08h, 0Fh, 0Ch +NUMROSERR equ dos_errors - ros_errors + +; The following code is required in order to cope with +; application programs invoking Int 13h directly. It +; handles applications that format floppies or access the +; disk via Int 13h after a floppy disk change. + + Assume CS:CGROUP, DS:Nothing, ES:Nothing, SS:Nothing + + + Public Int13Unsure +;---------- +Int13Unsure proc far +;---------- + sti + cld + push ds + mov ds,cs:DataSegment + Assume DS:CGROUP + call i13_unsure ; no longer sure of this drive + pop ds + ret +Int13Unsure endp + + Public Int13Deblock + +;----------- +Int13Deblock proc far +;----------- +; handle user programs formatting the disk + sti + cld + push ds + mov ds,cs:DataSegment + Assume DS:CGROUP + + pushx ; save work registers + mov i13_dma_off,bx + mov i13_dma_seg,es +i13_deblock10: + pushx + mov cl,4 + mov ax,i13_dma_seg ; get transfer address + shl ax,cl ; get A4..A15 from segment + add ax,i13_dma_off ; combine with A0..A15 from offset + not ax ; AX = # of bytes left in 64K bank + xor dx,dx + mov cx,SECSIZE + div cx ; convert this to physical sectors + mov dl,i13_size ; see if we can xfer amount wanted + cmp al,dl ; capable of more than requested? + jb i13_deblock20 ; skip if we can do it all + xchg ax,dx ; we can do them all +i13_deblock20: + les bx,i13_dma_ptr ; do the xfer to here + popx + mov ah,i13_op ; get read/write/verify operation + test al,al ; if zero length possible + jz i13_deblock30 ; then deblock + mov di,es ; get transfer address + cmp di,DeblockSeg ; is this in high memory ? + jb i13_deblock50 ; then force through deblock buffer +i13_deblock30: + push ds ; if deblocking then we'd better + pop es ; point at local buffer we + mov bx,CG:local_buffer ; will be using for actual I/O + cmp i13_op,ROS_WRITE + jne i13_deblock40 ; skip data copy if not writing to disk + push ds + push cx + mov di,bx ; ES:DI -> local buffer + lds si,i13_dma_ptr ; DS:SI -> data to write + mov cx,SECSIZE/2 + rep movsw ; copy to deblocking buffer + pop cx + pop ds +i13_deblock40: + mov al,1 ; do a single sector via buffer + clc + pushf ; fake an Int + call i13pointer ; to the track handler + jc i13_deblock90 ; stop on error + mov al,1 ; restore AL for buggy bios's + cmp i13_op,ROS_READ ; if we are reading then we'll + jne i13_deblock60 ; have to copy data out of + push cx ; the deblocking buffer + les di,i13_dma_ptr ; ES:DI -> dest for data + mov si,CG:local_buffer ; point at local buffer which + mov cx,SECSIZE/2 ; contains actual data + rep movsw ; copy from deblocking buffer + pop cx + jmps i13_deblock60 + +i13_deblock50: + push ax ; save # sectors in xfer + clc + pushf ; fake an Int + call i13pointer ; do the operation + pop bx + mov al,bl ; restore AL for buggy bios's + jc i13_deblock90 ; stop on error +i13_deblock60: ; we succeeded in doing AL sectors + sub i13_size,al ; forget about those we have done + jbe i13_deblock90 ; and do more if there are any + push ax + mov ah,SECSIZE/16 + mul ah ; AX = paras to inc DMA address + add i13_dma_seg,ax ; up DMA address by this amount + pop ax + call i13_point_unit ; ES:DI -> UDSC_ + jc i13_deblock90 ; exit if we can't find it + mov bx,cx ; get sector/cylinder in BX + and bx,0003Fh ; BX = sector + and cx,0FFC0h ; CX = mandled cylinder bits + add bl,al ; work out new sector +i13_deblock70: + mov ax,es:UDSC_BPB+BPB_SPT[di] + cmp bx,ax ; still on the same track ? + jbe i13_deblock80 ; easy if no overflow onto next track + sub bx,ax ; subtract a tracks worth + inc dh ; and move onto next head + mov al,dh ; isolate head from cylinder + and ax,003Fh ; bits 10/11 + cmp ax,es:UDSC_BPB+BPB_HEADS[di] + jb i13_deblock70 ; onto next track yet ? + and dh,0C0h ; back to head zero + add ch,1 ; onto next track (bits 0-7) + jnc i13_deblock70 ; overflow to bits 8-9 ? + add cl,040h ; yes, "inc" bits 8/9 of cylinder + jnc i13_deblock70 ; overflow to bits 10-11 ? + add dh,040h ; yes, "inc" bits 10/11 of cylinder + jmps i13_deblock70 + +i13_deblock80: + or cx,bx ; recombine sector/cylinder + jmp i13_deblock10 ; and do some more + +i13_deblock90: + popx ; restore work registers + pop ds ; recover user DS + ret 2 ; return to user with result + +i13_point_unit proc near +;------------- +; On Entry: +; DL = ROS unit +; On Exit: +; ES:DI -> UDSC_ for that unit +; All other regs preserved +; + les di,udsc_root ; ES:DI -> 1st es:UDSC_ +i13_point_unit10: + cmp dl,es:UDSC_RUNIT[di] ; find the physical unit + je i13_point_unit20 + les di,es:UDSC_NEXT[di] + cmp di,0FFFFh ; else try the next es:UDSC_ + jne i13_point_unit10 + mov ah,09h ; return DMA error to caller as we + stc ; don't know about this unit +i13_point_unit20: + ret +i13_point_unit endp + +Int13Deblock endp + +i13_unsure proc near +;--------- +; mark physical drive DL as unsure +; + pushx + lds si,udsc_root +i13_unsure10: + cmp dl,ds:UDSC_RUNIT[si] ; does it match ROS drive? + jne i13_unsure20 ; skip if not + or ds:UDSC_FLAGS[si],UDF_UNSURE +i13_unsure20: ; next drive + lds si,ds:UDSC_NEXT[si] + cmp si,0FFFFh + jne i13_unsure10 + popx ; restore registers + ret + +i13_unsure endp + + Assume DS:Nothing, SS:Nothing, ES:Nothing + + Public Int2FHandler + +Int2FHandler proc far +;----------- +; On Entry we have offset/seg of next in chain on the stack +; (ie. we can pass on by a RETF) +; + cmp ah,8 ; DRIVER.SYS support + je i2F_driver + cmp ah,13h ; int13 intercept + jne i2F_iret +; +; Int 13 interception support +; --------------------------- +; +; On Entry: +; DS:DX -> New Int 13 vector +; ES:BX -> Int 13 vector restored by Int 19 +; +; On Exit: +; DS:DX -> Old Int 13 vector +; ES:BX -> Old Int 13 vector restored by Int 19 +; +i2F_i13_intercept: + mov ax,ds + mov ds,cs:DataSegment + Assume DS:CGROUP + xchg dx,ds:i13off_save + xchg ax,ds:i13seg_save + push ax + xchg bx,ds:word ptr orgInt13 + mov ax,es + xchg ax,ds:word ptr orgInt13+2 + mov es,ax + pop ds + Assume DS:Nothing +i2F_iret: + iret + + +; +; DRIVER.SYS support +; ------------------- +; +; On Entry: +; AX=0800, installation check +; AX=0801, add new block device at DS:SI +; AX=0802, execute driver request at ES:BX +; AX=0803, return address of first es:UDSC_ +; +i2F_driver: + cmp al,1 + jb i2F_driver_check + je i2F_driver_add + cmp al,3 + jb i2F_driver_req + je i2F_driver_point + iret + +i2F_driver_check: +; +; Installation check +; + mov al,0ffh ; say we are installed + iret + +i2F_driver_add: +; +; Add new block device DS:DI +; + push ds + push es + push ds + pop es ; ES:DI -> unit + mov ds,cs:DataSegment + call add_unit + pop es + pop ds + iret + +i2F_driver_point: +; +; return DS:DI -> first UDSC_ +; + mov ds,cs:DataSegment ; DS -> our data + lds di,ds:udsc_root + iret +; +; Execute DRIVER.SYS request ES:BX +; +i2F_driver_req: + push ds + mov ds,cs:DataSegment + Assume DS:CGROUP + mov ds:req_off,bx ; fill in request pointer + mov ds:req_seg,es ; as if it was local + pop ds + Assume DS:Nothing + push cs:driverTable ; fiddle the table address + jmp DriverFunction ; then go to normal handler + + extrn DriverFunction:near + extrn IntDiskTable:word ; = DiskTable + +driverTable dw CG:IntDiskTable ; push address of table on + ; stack as DriverFunction + ; examines it + +Int2FHandler endp + + Assume DS:CGROUP, SS:Nothing, ES:Nothing + + Public DiskTable + +DiskTable label word + db 24 ; Last supported function + dw CG:dd_init ; 0-initialize driver + dw CG:dd_medchk ; 1-media change check + dw CG:dd_build_bpb ; 2-build BIOS Parameter Block + dw CG:dd_error ; 3-IOCTL string input + dw CG:dd_input ; 4-input + dw CG:dd_error ; 5-nondestructive input (char only) + dw CG:dd_error ; 6-input status (char only) + dw CG:dd_error ; 7-input flush + dw CG:dd_output ; 8-output + dw CG:dd_output_vfy ; 9-output with verify + dw CG:dd_error ; 10-output status (char only) + dw CG:dd_error ; 11-output flush (char only) + dw CG:dd_error ; 12-IOCTL string output + dw CG:dd_open ; 13-device open + dw CG:dd_close ; 14-device close + dw CG:dd_remchk ; 15-removable media check + dw CG:dd_error ; 16-n/a + dw CG:dd_error ; 17-n/a + dw CG:dd_error ; 18-n/a + dw CG:dd_genioctl ; 19-generic IOCTL + dw CG:dd_error ; 20-n/a + dw CG:dd_error ; 21-n/a + dw CG:dd_error ; 22-n/a + dw CG:dd_getdev ; 23-get logical drive + dw CG:dd_setdev ; 24-set logical drive + +driver proc near + +point_unit: ; get unit descriptor for work drive +;---------- +; On Entry: +; ES:BX -> Request Header +; On Exit: +; AL = logical drive +; ES:DI -> es:UDSC_ +; (All other registers preserved) +; + mov al,es:RH_UNIT[bx] ; get the unit number (0=A:, 1=B:, etc) + les di,udsc_root ; ES:DI -> 1st es:UDSC_ +point_unit10: + cmp al,es:UDSC_DRIVE[di] ; stop if the logical drive matches + je point_unit20 + les di,es:UDSC_NEXT[di] + cmp di,0FFFFh ; else try the next es:UDSC_ + jne point_unit10 + pop ax ; don't return to the caller + mov ax,RHS_ERROR+1 ; return "invalid unit" error +point_unit20: + ret + +add_unit: ; add a new unit to the list +;-------- +; On Entry: +; ES:DI -> UDSC to add +; On Exit: +; ES:DI preserved +; + mov al,es:UDSC_DRIVE[di] ; get the logical unit + cmp al,MAXPART ; is it too many ? + jae add_unit40 + push ds + mov es:word ptr UDSC_NEXT[di],0FFFFh + ; make sure it's terminated + and es:UDSC_FLAGS[di],UDF_HARD+UDF_CHGLINE + lea si,udsc_root ; DS:SI -> [first UDSC_] +add_unit10: + cmp ds:word ptr UDSC_NEXT[si],0FFFFh + je add_unit30 + lds si,ds:UDSC_NEXT[si] ; DS:SI -> UDSC_ we already have + mov al,es:UDSC_RUNIT[di] + cmp al,ds:UDSC_RUNIT[si] ; do the logical units match ? + jne add_unit10 + mov ax,ds:UDSC_FLAGS[si] ; inherit some flags + push ax + and ax,UDF_HARD+UDF_CHGLINE + mov es:UDSC_FLAGS[di],ax ; hard disk/changeline inherited + pop ax + test ax,UDF_HARD + jnz add_unit10 ; skip owner stuff on hard drive + test ax,UDF_VFLOPPY ; is this a multiple drive anyway ? + jnz add_unit20 + or ax,UDF_OWNER+UDF_VFLOPPY + mov ds:UDSC_FLAGS[si],ax ; no, 1st person becomes owner +add_unit20: + or es:UDSC_FLAGS[di],UDF_VFLOPPY + jmps add_unit10 ; go and try the next +add_unit30: + mov ds:word ptr UDSC_NEXT[si],di + mov ds:word ptr UDSC_NEXT+2[si],es + pop ds +add_unit40: + ret + +dd_error: ; 3-IOCTL string input +;-------- + mov ax,RHS_ERROR+3 ; "invalid command" error + ret + +dd_medchk: ; 1-media change check +;--------- +; entry: ES:BX -> request header +; exit: RH1_RETURN = 0, 1 or FF +; 00 = media may have changed +; 01 = media hasn't changed +; FF = media has been changed + + call point_unit ; get unit descriptor + test es:UDSC_FLAGS[di],UDF_HARD + jnz medchk2 ; "hasn't changed" if hard disk + call ask_for_disk ; make sure we've got correct floppy + mov ax,es:UDSC_FLAGS[di] ; get flags + test ax,UDF_UNSURE ; has format/diskcopy occurred? + jnz medchk6 ; may have changed to different format + test ax,UDF_CHGLINE + jz medchk3 ; skip ROS call if no change line + mov dl,es:UDSC_RUNIT[di] + mov al,dl ; don't trust changeline if we are + xchg al,activeRosUnit ; changing floppies + cmp al,dl ; return may have changed + jne medchk3 + mov ah,ROS_DSKCHG ; get disk change status function + int_____DISK_INT ; AH=0: DC low, AH=6: DC active + jc medchk5 ; disk change not active? +medchk2: + mov al,01h ; disk hasn't changed + jmps medchk_ret + + +medchk3: ; no changeline support, use timer + call read_system_ticks ; get system tick count in CX/DX + mov ax,dx + xchg ax,es:UDSC_TIMER[di] ; get previous time and update + sub dx,ax + mov ax,cx + xchg ax,es:UDSC_TIMER+2[di] + sbb cx,ax ; CX/DX = # ticks since last access + jne medchk5 ; media could have changed if > 64k + cmp dx,18*3 ; more than three seconds expired? + jb medchk2 ; "not changed" if access too recent +medchk5: + mov cx,1 ; read track 0, sector 1 (boot sector) + call login_read ; to check the builtin BPB + jc medchk6 ; may have changed if read error + mov al,local_buffer+11+BPB_FATID + cmp al,0F0h ; check if we find a BPB + jb medchk6 ; may have changed if not good BPB + cmp al,es:UDSC_BPB+BPB_FATID[di] + jne medchk8 ; has media byte changed ? + mov si,offset CGROUP:local_buffer+UDSC_BPB_LENGTH+11+2 + lodsb ; get extended boot + sub al,29h ; do we have an extended boot ? + je medchk7 ; no, test against our dummy value + push cs + pop ds ; DS:SI -> our dummy value + mov si,offset CGROUP:dummyMediaID +medchk7: + push di + lea di,UDSC_SERIAL[di] + mov cx,2 + repe cmpsw ; is serial number unchanged ? + pop di + je medchk6 ; then return may have changed +medchk8: + lea ax,UDSC_LABEL[di] ; ES:AX -> ASCII label + lds bx,REQUEST[bp] + mov ds:word ptr RH1_VOLID[bx],ax + mov ds:word ptr RH1_VOLID+2[bx],es + mov al,0FFH ; return disk changed + jmps medchk_ret + +medchk6: + mov al,00h ; disk may have changed + +medchk_ret: + and es:UDSC_FLAGS[di],not UDF_UNSURE + les bx,REQUEST[bp] + mov es:RH1_RETURN[bx],al ; set return value + sub ax,ax + ret + + + page +dd_build_bpb: ; 2-build BIOS Parameter Block +;------------ + call point_unit ; get unit descriptor + test es:UDSC_FLAGS[di],UDF_HARD + jnz bldbpb1 ; BPB doesn't change for hard disks + call login_media ; try to determine media type (BPB) + jc bldbpb_err +bldbpb1: + mov es:UDSC_OPNCNT[di],0 ; no files open at this time + and es:UDSC_FLAGS[di],not UDF_UNSURE + ; media is sure + lea si,UDSC_BPB[di] + mov ax,es + les bx,REQUEST[bp] + mov es:RH2_BPBOFF[bx],si ; return the current BPB + mov es:RH2_BPBSEG[bx],ax + + xor ax,ax + ret + +bldbpb_err: + jmp xlat_error ; return error code +; ret + + + +login_media: ; determine BPB for new floppy disk +;----------- + push ds + mov cx,1 ; read track 0, sector 1 (boot) + call login_read ; to determine media type + jc login_media_err ; abort if physical error + cmp local_buffer+11+BPB_FATID,0F0h + jb login_media10 ; fail unless FATID sensible + lodsw ; get JMP instruction from boot sector + xchg ax,bx ; save in BX + lodsb ; get next 3rd byte in AX + add si,8 ; skip JMP, OEM name, SI -> BPB + cmp bl,0E9h ; does it start with a JMP ? + je login_media40 + cmp bl,069h + je login_media40 + cmp bl,0EBh ; how about a JMPS ? + jne login_media10 + cmp al,090h ; then we need a NOP + je login_media40 +login_media10: + mov cx,2 ; read track 0, sector 2 (FAT) + call login_read ; try to read the sector + jc login_media_err ; abort if physical error + cmp word ptr 1[si],-1 ; bytes 1, 2 must be 0FFh, 0FFh + jne login_media30 ; default media if bad FAT + lodsb ; else get FAT ID byte + mov si,CG:bpb160 ; look through builtin BPB table + mov cx,NBPBS ; # of builtin BPBs +login_media20: + cmp al,BPB_FATID[si] ; does it match one we know? + je login_media40 ; yes, use builtin BPB + add si,BPB_LENGTH ; else move to next BPB + loop login_media20 ; repeat for all BPBs +login_media30: ; can't find that FAT ID + lea si,UDSC_DEVBPB[di] ; use the default type + push es + pop ds ; use BPB at DS:SI -> +login_media40: + push di + lea di,UDSC_BPB[di] ; ES:DI -> unit descriptor (UDSC) + mov cx,UDSC_BPB_LENGTH ; size of a BPB (less reserved stuff) + rep movsb ; copy into unit descriptor + pop di + mov es:UDSC_BPB+BPB_SECSIZ[di],SECSIZE +; mov cx,0 + mov es:word ptr (UDSC_BPB+BPB_HIDDEN)[di],cx + mov es:word ptr (UDSC_BPB+BPB_HIDDEN+2)[di],cx + cmp si,offset CGROUP:local_buffer+UDSC_BPB_LENGTH+11 + jne login_media50 ; is the BPB from the boot sector ? +; mov ax,ds ; if so then check for media id +; cmp ax,cs:DataSegment ; seg check redundant as UDSC_DEVBPB +; jne login_media50 ; is followed by 7 bytes of zero + lodsw ; skip 2 bytes + lodsb ; now get possible boot signature + cmp al,29h ; is it an extended boot sector ? + je login_media60 ; yes, use it +login_media50: + push cs + pop ds ; DS:SI -> our dummy value + mov si,offset CGROUP:dummyMediaID +login_media60: + call UpdateMediaID ; update UDSC_ with media info + clc +login_media_err: + pop ds + ret + +dummyMediaID dd 0 ; serial number 0 + db 'NO NAME ' + db 'FAT12 ' + +UpdateMediaID: +;------------- +; On Entry: +; DS:SI -> extended boot record info +; ES:DI -> UDSC_ to update +; On Exit: +; ES:DI preserved +; + push di + xor ax,ax ; AX = a handy zero + lea di,UDSC_SERIAL[di] + movsw + movsw ; copy serial number + pop di + push di + lea di,UDSC_LABEL[di] + mov cx,11 + rep movsb ; copy the volume label + stosb ; zero terminate it + pop di + push di + lea di,UDSC_FSTYPE[di] + movsw + movsw + movsw + movsw ; copy the file system type + stosb ; zero terminate it + pop di + ret + + +login_read: +; entry: CH, CL = cylinder/sector to read +; exit: CY = 1, AH = status if error +; else local_buffer filled in + + mov dl,es:UDSC_RUNIT[di] ; DL = ROS drive + mov dh,0 ; DH = head number + +login_read_dx: ; read on drive DL, head DH +;------------- ; (entry for hard disk login) + mov P_RETRY[bp],RETRY_MAX ; initialize retry count +logrd1: + push es + mov ax,ROS_READ*256 + 1 ; read one sector from ROS + push ds + pop es ; ES = DS = local segment + mov bx,CG:local_buffer + int_____DISK_INT ; call the ROM BIOS + pop es + jnc logrd3 ; skip if no disk error + push ax +; mov ah,ROS_RESET + xor ax,ax + int_____DISK_INT ; reset the drive + pop ax + dec P_RETRY[bp] + jnz logrd1 ; loop back if more retries +logrd2: + stc +logrd3: + mov si,CG:local_buffer + ret + + page +dd_output: ; 8-output +;--------- + mov P_ROSCMD[bp],ROS_WRITE ; write to floppy/hard disk + jmps io_common + +dd_output_vfy: ; 9-output with verify +;------------- + mov P_ROSCMD[bp],ROS_VERIFY ; write & verify floppy/hard disk + jmps io_common + +dd_input: ; 4-input +;-------- + mov P_ROSCMD[bp],ROS_READ ; read from floppy/hard disk +; jmps io_common + +io_common: ; common code for the above three + call point_unit ; get unit descriptor + call ask_for_disk ; make sure we've got correct floppy + call setup_rw ; setup for read/write operation + jc io_ret ; return if bad parameters +io_loop: + call track_rw ; read as much as possible on track + jc xlat_error ; return if physical disk error + cmp P_COUNT[bp],0 ; test if any more stuff to read + jne io_loop ; yes, loop back for more + + mov al,es:UDSC_RUNIT[di] ; remember the drive that is active + mov activeRosUnit,al + test es:UDSC_FLAGS[di],UDF_HARD+UDF_CHGLINE + jnz io_exit ; skip timer read for hard/changeline + + call read_system_ticks ; get system tick count in CX/DX + mov es:UDSC_TIMER[di],dx + mov es:UDSC_TIMER+2[di],cx ; save time of successful access +io_exit: + xor ax,ax ; all done, no error encountered +io_ret: + ret + +xlat_error: ; translate ROS error to DOS error +;---------- +; entry: AH = ROS disk error code, CY = 1 +; exit: AX = status to be returned to BDOS + + pushx ; save some registers + mov al,ah ; AL = ROS error code + push cs + pop es + mov di,CG:ros_errors ; ES:DI -> ROS error code table + mov cx,NUMROSERR + repne scasb ; scan for match + mov ax,RHS_ERROR ; get basic error indication + or al,cs:(CG:dos_errors-CG:ros_errors-1)[di] + ; combine with type of error + popx + stc + ret + + + +setup_rw: ; prepare for INPUT, OUTPUT or OUTPUT_VFY +;-------- +; On Entry: +; ES:DI -> UDSC +; On Exit: +; if CY == 0: +; P_CYL, P_HEAD, P_SECTOR, +; P_DMAOFF, P_DMASEG, P_COUNT initialized +; if CY == 1: invalid parameters detected +; ES:DI preserved + + push ds + lds bx,REQUEST[bp] + mov ax,ds:RH4_BUFOFF[bx] ; get offset of transfer buffer + mov P_DMAOFF[bp],ax ; set transfer offset + mov ax,ds:RH4_BUFSEG[bx] ; get segment of transfer buffer + mov P_DMASEG[bp],ax ; set transfer segment + mov ax,ds:RH4_COUNT[bx] ; get sector count from request header + mov P_COUNT[bp],ax ; save it locally for later + mov ax,ds:RH4_SECTOR[bx] ; get low 16 bit of sector # + sub dx,dx ; assume value is 16 bit only + cmp ds:RH_LEN[bx],22 ; check if small request + je setrw2 ; if so forget the rest + cmp ds:RH_LEN[bx],24 ; check if large request + jne setrw1 + mov dx,ds:RH4_SECTOR+2[bx] ; yes, get 32-bit record number + jmps setrw2 +setrw1: + cmp ds:RH_LEN[bx],30 + jne setrw2 + cmp ax,-1 ; magic number indicating it's + jne setrw2 ; a 32-bit record number + mov ax,ds:RH4_BIGSECTORLO[bx] + mov dx,ds:RH4_BIGSECTORHI[bx] +setrw2: + pop ds + + mov cx,P_COUNT[bp] ; get requested count + jcxz setrw3 ; invalid count + dec cx ; CX = count - 1 + cmp es:word ptr (UDSC_BPB+BPB_TOTSEC)[di],0 + jne setrw4 ; skip if < 65536 sectors on disk + add ax,cx + adc dx,0 ; AX/DX = # of last sector for I/O + jc setrw3 ; error if > 32 bits + cmp dx,es:word ptr (UDSC_BPB+BPB_SIZE+2)[di] + ja setrw3 ; skip if too large + jb setrw5 ; O.K. if small enough + cmp ax,es:word ptr (UDSC_BPB+BPB_SIZE)[di] + jb setrw5 ; fail if too large +setrw3: + mov ax,RHS_ERROR+8 ; return "sector not found" + stc + ret + +setrw4: ; less than 65536 records + add ax,cx ; compute end of transfer + jc setrw3 ; skip if overflow + cmp ax,es:UDSC_BPB+BPB_TOTSEC[di] + jae setrw3 ; skip if too large +setrw5: + sub ax,cx + sbb dx,0 ; add partition address for hard disk + add ax,es:word ptr (UDSC_BPB+BPB_HIDDEN)[di] + adc dx,es:word ptr (UDSC_BPB+BPB_HIDDEN+2)[di] + push ax ; AX/DX = 32 bit starting record address + push dx ; save starting record + mov ax,es:UDSC_BPB+BPB_SPT[di] + mul es:UDSC_BPB+BPB_HEADS[di]; get sectors per track * heads + mov cx,ax ; CX = sectors per cylinder + pop dx ; recover 32 bit start block + pop ax + div cx ; AX = cylinder #, DX = head/sec offset + mov P_CYL[bp],ax ; save physical cylinder number + xor ax,ax ; make remainder 32 bit so + xchg ax,dx ; DX:AX = (head # * SPT) + sector # + div es:UDSC_BPB+BPB_SPT[di] ; divide by sectors per track + mov P_SECTOR[bp],dl ; DX = sector #, AX = head # + mov P_HEAD[bp],al ; save physical sector/head for later + + clc ; tell them we like the parameters + ret ; we've figured out starting address + +track_rw: +;-------- +; entry: P_CYL = cylinder for start of transfer +; P_HEAD = head # for start of transfer +; P_SECTOR = sector # for start of transfer +; P_COUNT = remaining sector count +; P_DMAOFF = transfer offset +; P_DMASEG = transfer segment +; ES:DI -> UDSC structure +; exit: CY = 0 if no error, P_COUNT = remaining sectors +; CY = 1 if error, AH = ROS error code + + call track_setup ; compute size of transfer +if FASTSETTLE + call new_settle ; set new head settle delay +endif + cmp P_DIRECT[bp],0 ; DMA boundary problem? + jne trkrw10 ; no, direct transfer performed + cmp P_ROSCMD[bp],ROS_READ + je trkrw10 ; skip if not writing to disk + pushx + mov cx,SECSIZE/2 ; CX = # of word per sector + push ds + pop es ; ES:DI -> destination + mov di,CG:local_buffer + lds si,P_DMA[bp] ; DS:SI -> source + rep movsw ; copy from deblocking buffer + popx +trkrw10: + mov P_RETRY[bp],RETRY_MAX ; perform up to three retries +trkrw20: ; loop back here for retries + mov cx,P_CYL[bp] ; get cylinder # + xchg cl,ch ; CH = bits 0..7, CL = bits 8..11 + ror cl,1 + ror cl,1 ; cylinder bits 8..9 in bits 6..7 + mov dh,cl ; cylinder bits 10.11 in bits 0..1 + and cl,11000000b ; isolate cylinder bits 8..9 + add cl,P_SECTOR[bp] ; bits 0..5 are sector number + inc cx ; make it one-relative for ROS + ror dh,1 + ror dh,1 ; cylinder bits 10..11 in bits 6..7 + and dh,11000000b ; isolate cylinder bits 10..11 + add dh,P_HEAD[bp] ; add physical head number + mov dl,es:UDSC_RUNIT[di] ; get ROS unit # + + push es + mov ax,ds + mov es,ax + mov bx,CG:local_buffer ; point at our local buffer + cmp P_DIRECT[bp],0 ; DMA boundary problem? + je trkrw30 ; no, direct transfer performed + les bx,P_DMA[bp] ; ES:BX -> transfer address +trkrw30: + mov ax,P_MCNT[bp] ; AL = physical sector count + mov ah,P_ROSCMD[bp] ; AH = ROS read command + cmp ah,ROS_VERIFY ; write with verify? + jne trkrw40 ; skip if ROS_READ or ROS_WRITE + mov ah,ROS_WRITE ; else first perform normal write + int_____DISK_INT ; call ROS to write to disk + jc trkrw50 ; skip if any errors occurred + mov ax,P_MCNT[bp] ; else get sector count + mov ah,ROS_VERIFY ; verify disk sectors +trkrw40: ; AH = function, AL = count + int_____DISK_INT ; read/write/verify via ROM BIOS +trkrw50: ; CY = 1, AH = error code + pop es + jnc trkrw70 ; skip if no errors occurred + call disk_reset ; reset the hardware + cmp ah,11h ; ECC corrected data? + je trkrw60 ; first sector known to be good + cmp ah,03h ; write protect error + je trkrw_error ; don't recover, report to user + dec P_RETRY[bp] ; count # of errors so far + jnz trkrw20 ; retries done, declare it permanent +trkrw_error: ; disk error occurred +if FASTSETTLE + call old_settle ; restore head settle delay +endif + stc ; CY = 1 indicates error, AH = code + ret + +trkrw60: ; ECC error, only 1st sector OK + mov P_MCNT[bp],1 ; say we have done one sector +trkrw70: ; read/write/verify succeeded + cmp P_DIRECT[bp],0 ; DMA boundary problem? + jne trkrw80 ; no, direct transfer performed + cmp P_ROSCMD[bp],ROS_READ + jne trkrw80 ; skip if not reading from disk + pushx + mov cx,SECSIZE/2 ; CX = # of word per sector + mov si,CG:local_buffer + les di,P_DMA[bp] ; DS:SI -> source, ES:DI -> destination + rep movsw ; copy from deblocking buffer + popx +trkrw80: + mov ax,P_MCNT[bp] ; get physical transfer length + sub P_COUNT[bp],ax ; subtract from total transfer length + jz trkrw90 ; exit if none left + add P_SECTOR[bp],al ; update current sector + mov ah,SECSIZE/16 + mul ah ; AX = paras to inc DMA address + add P_DMASEG[bp],ax ; update DMA segment + xor ax,ax + mov al,P_SECTOR[bp] ; get current sector + cmp ax,es:UDSC_BPB+BPB_SPT[di] + jb trkrw90 ; skip if on same track + mov P_SECTOR[bp],0 ; else start at beginning of new track + inc P_HEAD[bp] ; move to the next head + mov al,P_HEAD[bp] ; get current head + cmp ax,es:UDSC_BPB+BPB_HEADS[di] + jb trkrw90 ; did we go over end of cylinder? + mov P_HEAD[bp],0 ; start with first head... + inc P_CYL[bp] ; ... on the next cylinder +trkrw90: +if FASTSETTLE + call old_settle ; restore head settle delay +endif + clc ; indicate no errors + ret + + + +disk_reset: +;---------- +; entry: DL = ROS drive code + + push ax ; save the error status +; mov ah,ROS_RESET ; try a restore + xor ax,ax + int_____DISK_INT ; might sort things out + pop ax ; restore error status + ret + + +track_setup: ; prepare for I/O on disk track +;----------- +; entry: P_CYL = cylinder for start of transfer +; P_HEAD = head # for start of transfer +; P_SECTOR = sector # for start of transfer +; P_COUNT = remaining sector count +; P_DMAOFF = transfer offset +; P_DMASEG = transfer segment +; ES:DI -> UDSC structure +; exit: P_DIRECT = 1 if no deblocking +; P_MCNT = # of sectors possible in one ROS call + + + mov ax,P_DMASEG[bp] ; get transfer address + cmp ax,DeblockSeg ; is this in high memory ? + jae trksu20 ; then force through deblock buffer + mov ax,P_COUNT[bp] ; assume we can transfer all + mov P_MCNT[bp],ax ; that's requested this time + mov P_DIRECT[bp],1 ; directly to destination + test es:UDSC_RUNIT[di],80h ; is it a hard disk transfer ? + jnz trksu30 ; yes, transfer the lot +; floppy transfer, break up into tracks + mov dx,es:UDSC_BPB+BPB_SPT[di] + ; DX = sectors per track + sub dl,P_SECTOR[bp] ; subtract starting sector + cmp dx,ax ; more than we want? + jae trksu10 ; no, use this count + mov P_MCNT[bp],dx ; set count for this pass +trksu10: + mov ax,P_DMASEG[bp] ; get transfer address + mov cl,4 + shl ax,cl ; get A4..A15 from segment + add ax,P_DMAOFF[bp] ; combine with A0..A15 from offset + not ax ; AX = # of bytes left in 64K bank + sub dx,dx + mov cx,SECSIZE + div cx ; convert this to physical sectors + cmp ax,P_MCNT[bp] ; capable of more than requested? + jae trksu30 ; skip if we can do it all + mov P_MCNT[bp],ax ; else update possible transfer length + test ax,ax ; can we transfer anything at all? + jnz trksu30 ; yes, perform the transfer +trksu20: + mov P_MCNT[bp],1 ; single sector transfer via buffer + mov P_DIRECT[bp],0 ; if DIRECT = 0, deblocked transfer +trksu30: + ret + + + + +if FASTSETTLE +new_settle: +;---------- + test es:UDSC_FLAGS[di],UDF_HARD ; fix head settle on floppies + jnz new_settle9 + cmp P_ROSCMD[bp],ROS_READ + jne new_settle9 + push ax + pushx + sub ax,ax + mov ds,ax + Assume DS:IVECT + lds bx,i1eptr + xchg al,9[bx] + Assume DS:CGROUP + popx + mov P_SETTLE[bp],al + pop ax +new_settle9: + ret + +old_settle: +;---------- + test es:UDSC_FLAGS[di],UDF_HARD ; fix head settle on floppies + jnz old_settle9 + cmp P_ROSCMD[bp],ROS_READ + jne old_settle9 + pushx + mov al,P_SETTLE[bp] + sub bx,bx + mov ds,bx + Assume DS:IVECT + lds bx,i1eptr + mov 9[bx],al + Assume DS:CGROUP + popx +old_settle9: + ret +endif + + +dd_open: ; 13-device open +;------- + call point_unit ; get unit descriptor + inc es:UDSC_OPNCNT[di] ; increment open count + sub ax,ax + ret + + +dd_close: ; 14-device close +;-------- + call point_unit ; get unit descriptor + dec es:UDSC_OPNCNT[di] ; decrement open count + sub ax,ax + ret + + +dd_remchk: ; 15-removable media check +;--------- + call point_unit ; get unit descriptor + sub ax,ax ; assume floppy disk + test es:UDSC_FLAGS[di],UDF_HARD + jz remchk1 ; skip if it really is a floppy + mov ax,RHS_BUSY ; else return "busy" for hard disk +remchk1: + ret + +dd_genioctl: ; 19-generic IOCTL +;----------- + mov cx,es:RH19_CATEGORY[bx] ; get major & minor function + xchg cl,ch ; swap them around + call point_unit ; get unit descriptor + + cmp ch,8 ; is it the right major category? + jne ioctl20 ; no, return an error + + or es:UDSC_FLAGS[di],UDF_UNSURE + ; media unsure after IOCTL + + mov si,offset CGROUP:genioctlTable +ioctl10: + lods cs:byte ptr [si] ; get category + mov ch,al ; keep in CH + lods cs:word ptr [si] ; AX = function address + cmp cl,ch ; is it the category we want ? + je ioctl30 ; yes, go do it + test ch,ch ; is it the end of the list ? + jnz ioctl10 ; no, do another one +ioctl20: + mov ax,RHS_ERROR+3 ; "unknown command" + ret +ioctl30: + jmp ax ; go do our routine + +genioctlTable label byte + db RQ19_SET ; set device parameters + dw offset CGROUP:ioctl_set + db RQ19_GET ; get device parameters + dw offset CGROUP:ioctl_get + db RQ19_WRITE ; write track + dw offset CGROUP:ioctl_write + db RQ19_READ ; read track + dw offset CGROUP:ioctl_read + db RQ19_FORMAT ; format & verify track + dw offset CGROUP:ioctl_format + db RQ19_VERIFY ; verify track + dw offset CGROUP:ioctl_verify + db RQ19_GETMEDIA ; get media id + dw offset CGROUP:ioctl_getmedia + db RQ19_SETMEDIA ; set media id + dw offset CGROUP:ioctl_setmedia + db 0 ; terminate the list + +point_ioctl_packet: +;------------------ +; On Entry: +; None +; On Exit: +; DS:BX -> ioctl request packet +; All other regs preserved +; + lds bx,REQUEST[bp] + lds bx,ds:RH19_GENPB[bx] ; ES:BX -> request packet + ret + + +ioctl_get: +;--------- + push ds + call point_ioctl_packet ; DS:BX -> ioctl packet + mov al,es:UDSC_TYPE[di] ; get drive type + mov ds:1[bx],al ; return drive type (0/1/2/5/7) + + mov ax,es:UDSC_FLAGS[di] ; get device attributes + and ax,UDF_HARD+UDF_CHGLINE ; isolate hard disk + change line bits + mov ds:2[bx],ax ; return device attributes + + mov ax,es:UDSC_NCYL[di] ; get # of cylinders + mov ds:4[bx],ax ; return # of cylinders + + sub ax,ax ; for now always say "default" + mov ds:6[bx],al ; return media type + + test ds:byte ptr [bx],1 ; return default BPB? + pop ds + lea si,UDSC_DEVBPB[di] ; assume we want device BPB + jz get1 ; skip if yes + test es:UDSC_FLAGS[di],UDF_HARD + jnz get1 ; BPB doesn't change for hard disks + call ask_for_disk ; make sure we've got correct floppy + call login_media ; determine floppy disk type + jc get_err ; abort if can't login disk + lea si,es:UDSC_BPB[di] ; get current BPB +get1: + push ds + push es + push di + push es + call point_ioctl_packet ; DS:BX -> ioctl packet + push ds + pop es + lea di,7[bx] ; ES:DI -> BPB in parameter block + pop ds ; DS:SI -> BPB to copy + mov cx,UDSC_BPB_LENGTH + rep movsb ; copy the BPB across to user + pop di + pop es + pop ds + xor ax,ax ; return success + ret +get_err: + jmp xlat_error ; return error code +; ret + +ioctl_set: ; set device parameters +;--------- + + push ds + push es + call point_ioctl_packet ; DS:BX -> ioctl packet + test ds:byte ptr [bx],2 ; ignore all but track layout? + jnz set2 ; yes, skip BPB stuff + + mov al,ds:1[bx] ; get new drive type (0/1/2/5/7) + mov es:UDSC_TYPE[di],al ; set drive type + + and es:UDSC_FLAGS[di],not (UDF_HARD+UDF_CHGLINE) + mov ax,ds:2[bx] ; get new device attributes + and ax,UDF_HARD+UDF_CHGLINE ; isolate hard disk + change line bits + or es:UDSC_FLAGS[di],ax ; combine the settings + + mov ax,ds:4[bx] ; get new # of cylinders + mov es:UDSC_NCYL[di],ax ; set # of cylinders + + lea ax,UDSC_BPB[di] ; AX -> media BPB in es:UDSC_ + test ds:byte ptr [bx],1 ; fix BPB for "build BPB" call? + jnz set1 ; skip if new media BPB only + lea ax,UDSC_DEVBPB[di] ; AX -> device BPB in es:UDSC_ +set1: + lea si,7[bx] ; DS:SI -> new BPB from user + xchg ax,di ; ES:DI -> BPB in es:UDSC_ + mov cx,UDSC_BPB_LENGTH + rep movsb ; copy BPB into UDSC as new default + xchg ax,di ; ES:DI -> UDSC_ again + +set2: ; now set track layout + lea si,BPB_LENGTH+7[bx] ; DS:SI -> new user layout + mov es,cs:DataSegment + mov di,CG:layout_table ; ES:DI -> BIOS layout table + lodsw ; get sector count + test ax,ax ; make sure this is good value + jz set6 + cmp ax,MAX_SPT ; make sure this is good value + ja set6 ; so we don't overflow table + xchg ax,cx ; CX = sector count +set3: ; loop here for every sector + inc di + inc di + lodsw ; get sector number + stosb ; write sector number + lodsw ; get sector size (0080, 0100, 0200, 0400) + shl ax,1 ; double it (0100, 0200, 0400, 0800) +set4: + shr ah,1 ; halve the sector size until = 128 + jc set5 ; we've shifted out bottom bit + inc al ; count the # of bits + jnz set4 ; (this should always jump) +set5: + stosb ; store LOG2 (sector size/128) + loop set3 ; repeat for all sectors +set6: + pop es + pop ds + xor ax,ax + ret + +ioctl_read: +;---------- + + mov P_ROSCMD[bp],ROS_READ ; read physical track + jmps ioctl_rw_common ; use common code + +ioctl_write: +;----------- + + mov P_ROSCMD[bp],ROS_WRITE ; write physical track +; jmps ioctl_rw_common ; use common code + +ioctl_rw_common: + call ask_for_disk ; make sure we've got correct floppy + push ds + call point_ioctl_packet ; DS:BX -> ioctl packet + mov al,ds:5[bx] ; get logical sector (0..SPT-1) + mov P_SECTOR[bp],al + mov ax,ds:7[bx] ; get sector count + mov P_COUNT[bp],ax + mov ax,ds:9[bx] ; get transfer address + mov P_DMAOFF[bp],ax + mov ax,ds:11[bx] + mov P_DMASEG[bp],ax + mov ax,ds:1[bx] ; get head number + mov P_HEAD[bp],al + mov ax,ds:3[bx] ; get cylinder number + mov P_CYL[bp],ax + pop ds +rw_loop: + call track_rw ; read as much as possible on track + jc rw_err ; return if physical disk error + cmp P_COUNT[bp],0 ; test if any more stuff to read + jne rw_loop ; yes, loop back for more + sub ax,ax ; all done, no error encountered + ret ; return O.K. code +rw_err: + jmp xlat_error ; translate ROS code to DOS error +; ret + +ioctl_verify: +;------------ +ioctl_format: +;------------ + call ask_for_disk ; make sure we've got correct floppy + mov P_RETRY[bp],RETRY_MAX ; perform up to three retries +format_retry: + call set_format ; attempt data rate setup + push ds + call point_ioctl_packet ; DS:BX -> ioctl packet + test ds:byte ptr [bx],1 ; are we testing parameters only ? + jz format10 + mov ds:[bx],al ; return AL + pop ds + xor ax,ax ; we succeeded + ret + +format10: + mov ax,es:UDSC_BPB+BPB_SPT[di] + test ds:byte ptr [bx],2 ; is it undocumented "do 2 tracks" bit? + jz format20 + add ax,ax ; yes, double the count +format20: + mov P_COUNT[bp],ax ; save it locally for later + mov dh,ds:1[bx] ; get head # + mov cx,ds:3[bx] ; get cylinder # + ror ch,1 + ror ch,1 + xchg cl,ch + or cl,1 ; start with sector 1 + mov dl,es:UDSC_RUNIT[di] ; get ROS drive # + lds bx,REQUEST[bp] ; DS:BX -> Request Header + mov bx,ds:RH19_CATEGORY[bx] ; get major & minor function + pop ds + + push es + xor ax,ax + mov es,ax + mov ax,new_int1e_off ; point floppy paramters at local + xchg ax,es:[4*1Eh] + mov orig_int1e_off,ax ; save old value + mov ax,new_int1e_seg + xchg ax,es:[4*1Eh+2] + mov orig_int1e_seg,ax + pop es + +format30: + cmp bh,RQ19_FORMAT ; skip if verify only + jne format40 + test es:UDSC_FLAGS[di],UDF_HARD + jnz format40 ; hard disks are always verify + + mov ax,P_COUNT[bp] + mov ah,ROS_FORMAT + push es + push bx + push ds + pop es + mov bx,CG:layout_table ; ES:BX -> parameter table + int_____DISK_INT + pop bx + pop es + jc format50 +format40: ; no error on format, try verify + mov ax,P_COUNT[bp] + mov ah,ROS_VERIFY + push es + push bx + xor bx,bx + mov es,bx + int_____DISK_INT + pop bx + pop es + jc format50 + xor ax,ax ; return success +format50: + push es + push di + push ax + mov ax,0 + mov es,ax + mov di,78h + mov ax,orig_int1e_off + stosw + mov ax,orig_int1e_seg + stosw + pop ax + pop di + pop es + jnc format60 ; if no error's just exit + call xlat_error ; translate to DOS error + dec P_RETRY[bp] ; any more retries ? + jz format60 ; no, just exit with error +; mov ah,ROS_RESET + xor ax,ax + int_____DISK_INT ; reset the drive + jmp format_retry ; now give it another go +format60: + ret + + +; The following table indicates which combinations of drive +; types, sectors per track and tracks per disk are O.K. and +; which value in AL is required for those combinations for +; INT 13h, AH = 17h ("set DASD type for format"). + +; +---------------------- 0 = 360Kb, 1 = 1.2Mb, 2 = 720Kb +; | +------------------ # of sectors/track (9, 15, 18) +; | | +--------------- # of tracks per disk (40 or 80) +; | | | +----------- 1 = 360 Kb in 360 Kb +; | | | | 2 = 360 Kb in 1.2 Mb +; | | | | 3 = 1.2 Mb in 1.2 Mb +; | | | | 4 = 720 Kb in 720 Kb +; | | | | +-------- gap length for format +; | | | | | +; V V V V V + +ok_fmt_table db 0, 9, 40, 1, 50h ; 360 Kb + db 1, 9, 40, 2, 50h ; 360 Kb in 1.2 Mb + db 1, 15, 80, 3, 54h ; 1.2 Mb in 1.2 Mb + db 2, 9, 80, 4, 50h ; 720 Kb in 720 Kb + db -1 ; end of table + +set_format: +;---------- +; On Entry: +; ES:DI -> UDSC_ +; On Exit: +; AL = 0 on success, else value to return in parameter block +; ES:DI preserved +; + push ds + call point_ioctl_packet ; DS:BX -> ioctl packet + mov dh,ds:1[bx] ; get the head number + mov cx,ds:3[bx] ; get the cylinder number + pop ds + + mov si,CG:layout_table ; SI -> track layout table + mov ax,MAX_SPT ; AX = # of sectors per track +set_format10: + mov 0[si],cl ; set cylinder number + mov 1[si],dh ; set head number + add si,4 ; next sector entry + dec ax ; count down # of sectors + jnz set_format10 ; repeat until all done + + call get_ncyl ; return # of tracks + dec ax ; AX = max. cylinder # + ror ah,1 + ror ah,1 ; move bits 8,9 into 6,7 + xchg al,ah + mov cx,es:UDSC_BPB+BPB_SPT[di] + ; get desired sectors/track + or cx,ax ; CL, CH = max. cylinder/max. sector # + cmp cx,2708h ; check for 40 track, 8 sectors/track + jne set_format20 ; we convert 160, 320 to 180, 360 + inc cx ; make it 9 sectors per track +set_format20: + mov dl,es:UDSC_RUNIT[di] ; get ROS unit number + pushx + mov ah,ROS_SETMEDIA ; set type for format + int_____DISK_INT ; check if combination is legal + mov new_int1e_off,di + mov new_int1e_seg,es ; ES:DI -> new parameters if legal + popx + jc set_format40 ; did we succeed ? +set_format30: + xor ax,ax ; success, return no errors + ret + +set_format40: +; ROM BIOS has given an error, if the function isn't supported drop +; thru' and try the older method's +; + mov al,2 ; assume ROS doesn't support it + cmp ah,0Ch ; media combination not supported ? + je set_format80 ; return AL=2 + inc ax ; AL = 3 + cmp ah,80h ; drive not ready ? + je set_format80 ; return AL=3 + +; Lets look for a match in our tables + + call get_ncyl ; AX = number of cylinders + mov cx,es:UDSC_BPB+BPB_SPT[di] + ; CL = sectors per track + mov ch,al ; CH = tracks per disk + cmp cx,2808h ; 40 tracks, 8 sectors? + jne set_format50 + inc cx ; force it to 9 sectors/track +set_format50: + mov si,CG:ok_fmt_table-4 +set_format60: + add si,4 ; next table entry + lods cs:byte ptr [si] ; get drive type + cmp al,0FFh ; end of device/media list? + je set_format70 ; yes, can't handle this combination + cmp al,es:UDSC_TYPE[di] ; does the drive type match? + jne set_format60 ; try next one if wrong drive + cmp cx,cs:[si] ; do tracks/sectors match? + jne set_format60 ; no, try next one + + mov parms_spt,cl ; set sectors/track + mov al,cs:3[si] ; get required gap length from table + mov parms_gpl,al ; set gap length for format + mov ax,CG:local_parms + mov new_int1e_off,ax ; use local parameters for formatting + mov new_int1e_seg,ds ; set new interrupt vector address + mov dl,es:UDSC_RUNIT[di] + mov al,cs:2[si] ; get media/drive combination + mov ah,ROS_SETTYPE ; set the drive type + int_____DISK_INT + jnc set_format30 ; return if no errors + cmp es:UDSC_TYPE[di],0 ; is this a 360 K drive? + je set_format30 ; go ahead, might be old ROS + cmp es:UDSC_TYPE[di],2 ; is this a 720 K drive? + je set_format30 ; go ahead, might be old ROS +set_format70: + mov al,1 ; return not supported +set_format80: + ret + + +get_ncyl: +;-------- + mov ax,es:UDSC_BPB+BPB_TOTSEC[di] + xor dx,dx ; get sectors on disk + test ax,ax ; zero means we use 32 bit value + jnz get_ncyl10 + mov ax,es:word ptr (UDSC_BPB+BPB_SIZE)[di] + mov dx,es:word ptr (UDSC_BPB+BPB_SIZE+2)[di] +get_ncyl10: + div es:UDSC_BPB+BPB_SPT[di] ; AX = # of cylinders * heads + call get_ncyl20 ; round up + div es:UDSC_BPB+BPB_HEADS[di]; AX = # of cylinders +get_ncyl20: + test dx,dx ; do we have overflow ? + jz get_ncyl30 + inc ax ; round up + xor dx,dx ; make it a 32 bit value +get_ncyl30: + ret + + +ioctl_getmedia: +;-------------- + mov P_ROSCMD[bp],ROS_READ ; read from floppy/hard disk + call rw_media ; read the boot sector + jc getmedia10 + push es + push di + push ds + call point_ioctl_packet ; DS:BX -> ioctl packet + push ds + pop es + lea di,2[bx] ; ES:DI -> skip info word + pop ds ; DS:SI -> boot sector media id + mov cx,4+11+8 + rep movsb ; copy the boot sector image + pop di + pop es + xor ax,ax +getmedia10: + ret + + +ioctl_setmedia: +;-------------- + mov P_ROSCMD[bp],ROS_READ ; read from floppy/hard disk + call rw_media ; read the boot sector + jc setmedia10 + push ds + push si + push es + push di + push ds + push si + call point_ioctl_packet ; DS:BX -> ioctl packet + lea si,2[bx] ; DS:SI -> skip info word + pop di + pop es ; ES:DI -> boot sector image + mov cx,4+11+8 + rep movsb ; update the boot sector image + pop di + pop es + pop si + pop ds + mov P_ROSCMD[bp],ROS_WRITE ; write to floppy/hard disk + jmp rw_media ; write the boot sector +setmedia10: + ret + +rw_media: +;-------- +; On Entry: +; ES:DI -> UDSC +; On Exit: +; ES:DI preserved +; CY clear, SI -> boot record info +; CY set on error, AX = error code +; +; setup parameters to read/write boot sector to/from local buffer +; + call ask_for_disk ; make sure we've got correct floppy + mov P_DMAOFF[bp],CG:local_buffer + mov P_DMASEG[bp],ds ; set transfer address + mov P_COUNT[bp],1 ; read 1 sector + mov ax,es:UDSC_BPB+BPB_SPT[di] + mul es:UDSC_BPB+BPB_HEADS[di]; get sectors per track * heads + xchg ax,cx ; CX = sectors per cylinder + mov ax,es:word ptr (UDSC_BPB+BPB_HIDDEN)[di] + mov dx,es:word ptr (UDSC_BPB+BPB_HIDDEN+2)[di] + div cx ; AX = cylinder #, DX = head/sec offset + mov P_CYL[bp],ax ; save physical cylinder number + xor ax,ax ; make remainder 32 bit so + xchg ax,dx ; DX:AX = (head # * SPT) + sector # + div es:UDSC_BPB+BPB_SPT[di] ; divide by sectors per track + mov P_SECTOR[bp],dl ; DX = sector #, AX = head # + mov P_HEAD[bp],al ; save physical sector/head for later + call rw_loop ; read the boot sector + jc rw_media20 + cmp local_buffer+11+BPB_FATID,0F0h + jb rw_media10 + mov si,offset CGROUP:local_buffer+UDSC_BPB_LENGTH+11+2 + lodsb ; get extended boot + sub al,29h ; do we have an extended boot ? + je rw_media20 ; no, well we can't write a new one +rw_media10: + mov ax,RHS_ERROR+3 ; "unknown command" +rw_media20: + ret + + +dd_getdev: ; 23-get logical drive +;--------- +; get logical drive that corresponds to the physical drive + call point_unit ; get unit descriptor + call get_owner ; DL = owning drive (zero not owned) + jmps dd_setdev10 ; return the owner + + +dd_setdev: ; 24-set logical drive +;--------- +; set logical drive that corresponds to the physical drive +; + call point_unit ; get unit descriptor + call set_owner ; set new owner +dd_setdev10: + les bx,REQUEST[bp] + mov es:RH_UNIT[bx],dl ; return current logical drive + xor ax,ax + ret + +get_owner: +;--------- +; On Entry: +; ES:DI -> UDSC_ +; On Exit: +; DL = owning drive (zero = no owner) +; + xor dx,dx ; assume one unit per physical drive + mov ax,es:UDSC_FLAGS[di] + test ax,UDF_HARD + jnz get_owner40 + test ax,UDF_VFLOPPY + jz get_owner40 + push ds + mov ds,dx ; DS -> low memory + Assume DS:IVECT + mov dl,dual_byte + pop ds + Assume DS:CGROUP + mov al,es:UDSC_RUNIT[di] ; lets look for this ROS drive + test al,al ; is it physical unit zero ? + jz get_owner30 ; yes, return dual_byte + push ds ; no, search our internal info + lds si,udsc_root + Assume DS:Nothing +get_owner10: + cmp al,ds:UDSC_RUNIT[si] ; do we use the same drive ? + jne get_owner20 + test ds:UDSC_FLAGS[si],UDF_OWNER + jz get_owner20 ; do we own it ? + mov dl,ds:UDSC_DRIVE[si] ; get the logical drive owner +get_owner20: + lds si,ds:UDSC_NEXT[si] + cmp si,0FFFFh ; try the next drive + jne get_owner10 + pop ds + Assume DS:CGROUP +get_owner30: + inc dx ; make drive one based +get_owner40: + ret + +set_owner: +;--------- +; On Entry: +; ES:DI -> UDSC_ +; On Exit: +; ES:DI preserved +; DL = owning drive (zero = no owner) +; + xor dx,dx ; assume one unit per physical drive + mov ax,es:UDSC_FLAGS[di] + test ax,UDF_HARD + jnz set_owner40 + test ax,UDF_VFLOPPY + jz set_owner40 + mov al,es:UDSC_DRIVE[di] + mov ah,es:UDSC_RUNIT[di] ; get ROS unit + test ah,ah ; is it unit zero ? + jnz set_owner10 + push ds + mov ds,dx ; DS -> low memory + Assume DS:IVECT + mov dual_byte,al ; set dual drive support byte + pop ds + Assume DS:CGROUP +set_owner10: + push ds + lds si,udsc_root + Assume DS:Nothing +set_owner20: + cmp ah,ds:UDSC_RUNIT[si] ; does this unit use the same drive ? + jne set_owner30 + or ds:UDSC_FLAGS[si],UDF_UNSURE+UDF_OWNER + cmp al,ds:UDSC_DRIVE[di] + je set_owner30 + and ds:UDSC_FLAGS[si],not UDF_OWNER +set_owner30: + lds si,ds:UDSC_NEXT[si] + cmp si,0FFFFh ; end of the line ? + jne set_owner20 + pop ds + Assume DS:CGROUP + xchg ax,dx ; DL = owning drive + inc dx ; make it one based +set_owner40: + ret + + +ask_for_disk: ; make sure the right disk is in the floppy drive +;------------ + call get_owner ; DL = owning drive + dec dx ; make DL zero based + js askfdsk30 ; stop if not a logical drive + mov dh,es:UDSC_DRIVE[di] ; DH = new drive, DL = old drive + cmp dl,dh ; do we own the drive ? + je askfdsk30 ; yes, stop now + push dx ; save for broadcast + mov dl,dh ; new owner in DL + call set_owner ; we are now the owner + push es + push di + push cs + call FullScreen + pop di + pop es + pop dx + mov ax,4A00h ; should we prompt ? + xor cx,cx + int 2Fh ; lets ask + inc cx ; CX = FFFF ? + jcxz askfdsk30 ; then skip prompt +ifdef JAPAN + mov ax,5001h ; get adaptor mode + int VIDEO_INT ; .. + cmp bx,81 ; japanese mode ? + mov si,CG:disk_msgA_jpn ; get message to print for Japanese + je askfdsk10 ; yes +endif + mov si,CG:disk_msgA ; get message to print +askfdsk10: + call WriteASCIIZ ; output the string + mov al,es:UDSC_DRIVE[di] ; get drive letter for new drive + add al,'A' + dec si ; point to NUL + call WriteNext ; output char, stop at NUL +ifdef JAPAN + mov ax,5001h ; get adaptor mode + int VIDEO_INT ; .. + cmp bx,81 ; japanese mode ? + mov si,CG:disk_msgB_jpn ; get message to print for Japanese + je askfdsk20 ; yes +endif + mov si,CG:disk_msgB ; get message to print +askfdsk20: + call WriteASCIIZ ; output the string + mov ah,0 ; wait for any key to be pressed + int KEYBOARD_INT ; read one key from keyboard +askfdsk30: + ret ; we've got the right drive + +WriteNext: + int 29h ; output via fastconsole entry +WriteASCIIZ: + lods cs:byte ptr [si] ; get next char + test al,al + jnz WriteNext ; stop at NUL + ret + +FullScreen: + xor di,di + mov es,di + mov ax,1684h ; get the entry point + mov bx,21 ; for DOSMGR + int 2Fh + mov bx,es + or bx,di ; anyone there ? + jz FullScreen10 + mov ax,1 ; yes, go full screen please + push es ; fake a JMPF to ES:DI + push di +FullScreen10: + retf + + +driver endp + + +RCODE ends ; end of device driver code + +page + +ICODE segment 'ICODE' ; initialization code + + Assume CS:CGROUP, DS:CGROUP, ES:Nothing, SS:Nothing + +dd_init: ; 0-initialize driver +;------- + + call hard_init ; setup hard disk units + call floppy_init ; setup floppy units + + les bx,REQUEST[bp] + mov al,nunits ; get # of units installed + mov es:RH0_NUNITS[bx],al ; return value to the BDOS + mov NumDiskUnits,al ; also set it in device header + + mov ax,endbios ; get pointer to last resident byte + mov es:RH0_RESIDENT[bx],ax ; set end of device driver + mov es:RH0_RESIDENT+2[bx],ds + + mov ax,CG:bpbtbl + mov es:RH0_BPBOFF[bx],ax ; set BPB table array + mov es:RH0_BPBSEG[bx],ds + + sub ax,ax ; initialization succeeded + ret ; (BIOS init always does...) + + +floppy_init: +;----------- + mov nunits,0 ; floppies start at drive A: + mov ah,ROS_RESET ; reset the disk system + xor dx,dx ; for NEAT hard disk boot bug + int_____DISK_INT + int EQUIPMENT_INT ; determine equipment status + mov cl,6 + shr ax,cl ; shift down floppy bits + and ax,03h ; mask for floppy + inc ax ; correct 0 based code + mov nfloppy,al + + cmp al,1 ; if there is only one floppy + jne equip_check_des ; then use 2 designators + inc ax ; this fakes a B: drive +equip_check_des: + mov cx,ax ; CX = # of units to set up + xor dx,dx ; DL = physical drive +equip_loop: + push cx + + call new_unit ; ES:DI -> UDSC + mov es:UDSC_RUNIT[di],dl ; set physical drive (ROS code) + + call floppy_type ; determine type, build default BPB + + cmp nfloppy,1 ; do we only have single drive? + je equip_single ; yes, use same physical drive for all + inc dx ; else use new drive for each unit +equip_single: ; we only have one physical drive + + call add_unit ; add ES:DI to list of UDSC_'s + + pop cx + loop equip_loop ; repeat for all logical floppies + + pushx + + push ds ; DS -> i13_trap segment + + mov di,ds + mov es,di + sub si,si + mov ds,si + lds si,78h[si] + mov di,CG:local_parms ; copy parameters to template + mov cx,11 + rep movsb + + pop es ; now ES -> i13_trap segment + Assume ES:CGROUP + sub ax,ax + mov ds,ax ; DS -> interrupt vectors + Assume DS:IVECT + mov ax,CG:Int2FTrap ; hook Int 2F + mov i2Foff,ax + mov i2Fseg,es + mov ax,CG:Int13Trap ; hook Int 13 + xchg ax,i13off + mov es:i13off_save,ax + mov ax,es + xchg ax,i13seg + mov es:i13seg_save,ax + + mov di,500h ; dual drive byte & friends live here + mov cx,20h/2 ; zero some bytes at 50h:0 + sub ax,ax ; get a quick zero + mov es,ax ; ES:DI -> 0:500h + rep stosw ; setup dual drive byte & friends + + Assume DS:CGROUP, ES:Nothing + popx + + ret + + +floppy_type: +;----------- +; entry: DI -> unit descriptor + + mov UDSC_TYPE[di],0 ; assume 360K 5.25" floppy + mov UDSC_NCYL[di],40 ; 40 tracks only + mov ah,ROS_GETTYPE ; "Read DASD type" + int_____DISK_INT ; find out if disk change line available + jc equip_no_chgline ; skip if function not supported + cmp ah,2 ; floppy with disk change line? + jne equip_no_chgline ; no, must be old 360K + or es:UDSC_FLAGS[di],UDF_CHGLINE + mov es:UDSC_TYPE[di],1 ; assume 1.2Mb floppy + mov es:UDSC_NCYL[di],80 ; 80 tracks +equip_no_chgline: + pushx ; save our registers + mov ah,ROS_PARAM ; read drive parameters + int_____DISK_INT ; find out floppy type + popx + jc equip_no_type ; skip if PC,XT,jr,AT before 10 Jan 84 + dec bx ; make values 0 based + jns equip_type ; (CMOS invalid - type = 0) + xor bx,bx ; assume 360K + cmp ch,4fh ; is it 80 track ? + jne equip_no_type ; if not forget it + mov bl,1 ; BL = 1 (ie. 1.2M) + cmp cl,15 ; 15 spt ? + je equip_type + inc bx ; BL = 2 (ie. 720k) + cmp cl,9 ; 9 spt ? + je equip_type + inc bx ; BL = 3 (ie. 1.4M) + cmp cl,18 ; 18 spt ? + je equip_type + inc bx + inc bx ; BL = 5 (ie. 2.8M) + cmp cl,36 ; 36 spt ? + jne equip_no_type ; don't recognise anything +equip_type: + cmp bl,3 ; is it 1.44 Mb 3.5" type? + jb equip_type_ok ; skip if 360K, 1.2Mb, 720K (0, 1, 2) + mov bl,7 ; use reserved "Other" type + je equip_type_ok + inc bx ; else make it 2.88 Mb type 9 + inc bx +equip_type_ok: + mov es:UDSC_TYPE[di],bl ; set the default drive type for format +equip_no_type: + + mov al,es:UDSC_TYPE[di] ; AL = 0, 1, 2 or 7 (360/1.2/720/1.44) + cbw ; make it a word + xchg ax,si ; SI = drive type + shl si,1 ; SI = drive type * 2 + mov si,bpbs[si] ; get default BPB for drive + cmp si,CG:bpb360 ; is this is a 360 K drive? + jne equip_360 ; skip if any other type + mov bpbtbl[bx],CG:bpb720 ; use larger default BPB +equip_360: + mov cx,UDSC_BPB_LENGTH ; CX = size of BPB + pushx + lea di,es:UDSC_BPB[di] + mov ax,ds + mov es,ax ; ES = DS + rep movsb ; make default BPB current BPB in UDSC + popx + pushx + lea di,es:UDSC_DEVBPB[di] + rep movsb ; copy default BPB device BPB in UDSC + popx + ret + + + page + +LOG_PRIM equ 01h ; log in primary partitions +LOG_EXTD equ 02h ; log in extended partitions + +log_flag dw LOG_PRIM ; scan for primary only initially + +hard_init: ; setup all hard disk units +;--------- +; mov log_flag,LOG_PRIM ; log in primary only initially + call hardi0 ; C: & D: + mov log_flag,LOG_EXTD ; log in extended only +; call hardi0 +; ret + +hardi0: + mov ah,ROS_PARAM ; get hard disk parameters + mov dl,80h + int_____DISK_INT ; get # of hard disks we have + jc hardi9 ; skip if hard disks not supported + test dl,dl ; test if any hard disks found + jz hardi9 ; skip if there weren't any + mov al,dl + cbw + xchg ax,cx ; CX = # of hard disks + mov dl,80h ; start with first hard disk +hardi1: + pushx ; save drive count, physical drive + call login_hdisk ; find all partitions on hard disk + popx ; restore physical drive, drive count + inc dx ; next physical hard disk + loop hardi1 ; next physical hard disk +hardi9: ; all hard disks done + ret + + +login_hdisk: ; find all partitions on a hard disk +;----------- +; entry: DL = 80h, 81h for 1st/2nd hard disk + + push log_flag ; save state for next drive + + mov p_unit,dl ; save physical drive + mov cx,0001h ; track 0, sector 1 + mov dh,0 ; partition tables start on head 0 +log_h1: + mov dl,p_unit ; get physical unit + call login_read_dx + jnc log_h1a + jmp log_h9 ; give up if disk error +log_h1a: + push cx + push dx + + mov ah,ROS_PARAM + int_____DISK_INT ; return disk drive parameters + inc dh ; DH = number of heads + mov nhead,dh ; set # of heads on drive + and cl,3Fh ; isolate sector count + mov nsect,cl ; set sectors per track + + pop dx + pop cx + +;; cmp local_id,0AA55h +;; jne log_h9 ; give up if not initialized + + test log_flag,LOG_PRIM ; scanning for primary? + jz log_h5 ; no, ignore all primary partitions + + mov si,CG:local_pt ; point to partition table +log_h2: +;** SECURE PARTITIONS ** + mov al,init_runit + test al,al ; booting from a hard disk ? +;** SECURE PARTITIONS ** + mov al,4[si] ; get system ID +;** SECURE PARTITIONS ** + jns log_h2a ; booting from a hard disk ? + mov ah,al ; yes, allow secure partitions + and ah,0F0h + cmp ah,SEC_ID + je log_h02 + cmp ah,SEC_ID2 + jne log_h2a +log_h02: + sub al,ah ; turn into a sensible partition ID +log_h2a: +;** SECURE PARTITIONS ** + cmp al,DOS20_ID ; is this a DOS 2.x partition? + je log_h3 ; yes, try to log it in + cmp al,DOS30_ID ; is this a DOS 3.0/3.1/3.2 partition? + je log_h3 ; yes, try to log it in + cmp al,DOS331_ID ; is this a DOS 3.31/4.0 partition? + jne log_h4 ; skip if not a good partition +log_h3: + push si ; save partition table index + pushx ; save partition table address + call login_primary ; login primary partition + popx ; get partition table address + call login_read_dx ; re-read partition table + pop si ; get partition table index + jc log_h9 ; give up if error +log_h4: + add si,16 ; next partition table entry + cmp si,CG:local_id ; all partitions checked? + jb log_h2 ; loop back if more + +log_h5: ; primary partitions done + test log_flag,LOG_EXTD ; scanning for extended? + jz log_h9 ; skip if no extended scan + + or log_flag,LOG_PRIM ; scan for both types now + mov si,CG:local_pt ; SI -> partition table +; RG-01 +log_h6: +;** SECURE PARTITIONS ** + mov al,init_runit + test al,al ; booting from a hard disk ? +;** SECURE PARTITIONS ** + mov al,4[si] ; get system ID +;** SECURE PARTITIONS ** + jns log_h6a ; booting from a hard disk ? + mov ah,al ; yes, allow secure partitions + and ah,0F0h + cmp ah,SEC_ID + je log_sec2 + cmp ah,SEC_ID2 + jne log_h6a +log_sec2: + sub al,ah +log_h6a: +;** SECURE PARTITIONS ** + cmp al,DOSEX_ID ; DOS 3.3 extended partition found? + jne log_h7 +log_h6b: + mov dh,1[si] ; get head # for next table + mov cx,2[si] ; get cylinder, sector for next table + jmp log_h1 ; read & scan next partition table + +log_h7: ; entry not an extended partition + add si,16 ; next partition table entry + cmp si,CG:local_buffer+IDOFF; all partitions checked? + jb log_h6 ; loop back if more + +log_h9: ; drive login done + pop log_flag ; restore state for next drive + ret + + +login_primary: +;------------- +; entry: SI -> partition table entry + + mov ax,12[si] ; get size of partition (low) + mov part_size,ax + mov ax,14[si] ; get size of partition (high) + mov part_size+2,ax + mov cl,2 + mov bx,5[si] ; get last head/sector + and bx,1100000011000000b ; isolate cylinder bits 10..11,8..9 + rol bl,cl ; bits 10..11 from head into position + or bh,bl ; or in bits 8..9 + rol bh,cl ; bits 8..11 into place + mov bl,7[si] ; get cylinder bits 0..7 + mov dh,1[si] ; get head of DOS partition + mov cx,2[si] ; get cylinder, sector of DOS partition + pushx + call login_read_dx ; try to read the partition boot + popx + jc login_p9 ; skip if partition not readable + ; CX, DX = disk addr of 1st sector + ; SI -> boot sector + ; PART_SIZE = 32 bit partition address + cmp nunits,MAXPART ; do we already have the maximum? + jb log_p0 ; skip if space for more units +login_p9: + ret ; else ignore this partition + +log_p0: + call new_unit ; ES:DI -> new UDSC + mov es:UDSC_FLAGS[di],UDF_HARD + mov es:UDSC_RUNIT[di],dl ; set physical drive (ROS code) + mov es:UDSC_TYPE[di],5 ; set type = hard disk + + mov al,dh ; copy head byte + and al,11000000b ; cylinder # bits 10..11 are in 6..7 + rol al,1 ; shift bits to bottom of word + rol al,1 + mov ah,cl ; cylinder # bits 8..9 are in 6..7 + and ah,11000000b ; strip off non-cylinder # bits + or ah,al ; combine the bits + rol ah,1 ; shift the bits into place + rol ah,1 + mov al,ch ; cylinder # bits 0..7 + sub bx,ax ; bx = # cylinders + inc bx ; make it inclusive + mov es:UDSC_NCYL[di],bx ; and save it + push ax ; save # CYLINDERS + mov al,nsect + and dh,00111111b ; DH = head offset + mul dh ; AX = HEAD_OFF * NSECT + xchg ax,bx ; keep in BX + mov al,nsect + mul nhead ; AX = HEADS * NSECT + pop dx ; recover # CYLINDERS + mul dx ; DX:AX = CYLINDERS * HEADS * NSECT + add ax,bx + adc dx,0 ; DX:AX = (CYL*HEADS + HEAD_OFF)*NSECT + + and cx,00111111b ; isolate bottom 6 bits (sector #) + dec cx ; sector numbers are one-relative + add ax,cx ; add in non-partition sectors + adc dx,0 ; (usually 2.x partition table) + + lea bx,UDSC_BPB[di] ; BX -> BPB to build + add si,11 ; skip JMP + OEM name in boot sector + + mov es:word ptr BPB_HIDDEN[bx],ax ; set the partition address + mov word ptr BPB_HIDDEN+2[bx],dx ; (32 bit sector offset) + mov ax,part_size + mov dx,part_size+2 + mov word ptr BPB_SIZE[bx],ax ; set partition size in sectors + mov word ptr BPB_SIZE+2[bx],dx + + mov BPB_TOTSEC[bx],ax ; set partition size for < 32 Mb + ; we'll zero this later if > 32 Mb + push es + push di + push ax + push dx + push si + call hd_bpb ; build BPB from scratch + pop si + pop dx + pop ax + pop di + pop es + + cmp byte ptr -11[si],0E9h ; look for a jmp + jz log_p1a + cmp word ptr -11[si],0EB90h ; look for a nop!jmps + jz log_p1a + cmp byte ptr -11[si],0EBh ; look for a jmps + jnz log_p1 ; at the start of the boot sector. + cmp byte ptr -9[si],90h ; EJH 7-1-91 + jnz log_p1 +log_p1a: + + test BPB_SECSIZ[si],SECSIZE-1; not a multiple of 512 byte? + jnz log_p1 + cmp BPB_FATID[si],0F8h ; is this a good hard disk? + jne log_p1 + cmp BPB_NFATS[si],2 ; too many FATs? + ja log_p1 + cmp BPB_NFATS[si],1 ; no FATs at all? + jae log_p2 ; continue if BPB is valid + ; elsa build new BPB +log_p1: ; any of the above: BPB invalid + ; (propably FDISKed, not FORMATted yet) + jmps log_p9 + +log_p2: ; valid BPB for partition, AX/DX = size + push ax + mov al,BPB_ALLOCSIZ[si] ; copy a few parameters from the + mov BPB_ALLOCSIZ[bx],al ; Boot Sector BPB to our new BPB + mov ax,BPB_DIRMAX[si] ; EJH 7-1-91 + mov BPB_DIRMAX[bx],ax + mov ax,BPB_FATSEC[si] + mov BPB_FATSEC[bx],ax + mov ax,BPB_SECSIZ[si] + mov BPB_SECSIZ[bx],ax + mov ax,BPB_FATADD[si] + mov BPB_FATADD[bx],ax + mov al,BPB_NFATS[si] + mov BPB_NFATS[bx],al + pop ax + + cmp BPB_TOTSEC[bx],0 ; is it an 32 bit sector partition ? + jne log_p3 ; no, carry on + test dx,dx ; would it fit in 16 bit sector sizes ? + jnz log_p3 ; yes, then make BPB_TOTSEC + mov BPB_TOTSEC[bx],ax ; a valid 16 bit value too +log_p3: ; valid BPB for partition, AX/DX = size + cmp BPB_SECSIZ[bx],SECSIZE + jbe log_p9 ; skip if no large sectors + shr BPB_SECSIZ[bx],1 ; halve the sector size + shl BPB_ALLOCSIZ[bx],1 ; double the cluster size + shl BPB_FATSEC[bx],1 ; double the FAT size + shl BPB_FATADD[bx],1 ; double the FAT address + shl BPB_TOTSEC[bx],1 ; double # of sectors + jnc log_p3 ; skip if still < 65536 sectors + mov BPB_TOTSEC[bx],0 ; else indicate large partition + jmps log_p3 ; try again + ; we've adjusted the sector size +log_p9: + pushx + push es + pop ds + lea si,UDSC_BPB[di] ; DS:SI -> new BPB + lea di,UDSC_DEVBPB[di] ; ES:DI -> fixed BPB + mov cx,UDSC_BPB_LENGTH + rep movsb ; make this the fixed BPB + popx + call add_unit ; register this DDSC_ + inc nhard ; yet another hard disk + ret + +hd_bpb: +;------ + mov BPB_SECSIZ[bx],SECSIZE ; set standard sector size + mov BPB_FATADD[bx],1 ; one reserved (boot) sector + mov BPB_NFATS[bx],2 ; two FAT copies + mov BPB_DIRMAX[bx],512 ; assume 512 entry root directory + ; BPB_TOTSEC set up already + mov BPB_FATID[bx],0F8h ; standard hard disk ID + mov al,nsect + mov ah,0 + mov BPB_SPT[bx],ax ; set sectors/track + mov al,nhead + mov BPB_HEADS[bx],ax ; set # of heads + ; determine FAT size: + mov BPB_ALLOCSIZ[bx],2*2 ; assume 2 K clusters + mov ax,word ptr BPB_SIZE[bx]; AX/DX = 32 bit sector count + mov dx,word ptr BPB_SIZE+2[bx] + test dx,dx ; have we got huge partition (type 6)? + jnz hd_bpb10 ; yes, it's 16-bit + cmp ax,7FCEh ; more than 16 Mb? + jae hd_bpb20 ; yes, use 16 bit FAT + mov cx,4*2 ; else we've got old 12-bit FAT + mov BPB_ALLOCSIZ[bx],cl ; we use 4 K clusters + add ax,cx ; adjust DX:AX for rounding + dec ax ; when we work out num clusters + div cx ; AX = # of clusters + mov cx,ax + add ax,ax ; * 2 + add ax,cx ; * 3 + shr ax,1 ; AX = num clus * 3/2 = bytes + adc ax,512-1 ; allow for rounding + xor dx,dx + mov cx,512 + div cx ; AX = # fat sectors + mov BPB_FATSEC[bx],ax ; remember FAT size + ret + +hd_bpb10: + mov BPB_TOTSEC[bx],0 ; zero this if BPB_SIZE is required + cmp dx,2 ; less than 2*65536 sectors (64 Mb)? + jb hd_bpb20 ; yes, leave cluster size the same + mov BPB_ALLOCSIZ[bx],4*2 ; use 4 K clusters if 64-128 Mb + cmp dx,4 ; less than 4*65536 sectors (128 Mb)? + jb hd_bpb20 ; yes, leave cluster size the same + mov BPB_ALLOCSIZ[bx],8*2 ; use 8 K clusters if 128-512 Mb + cmp dx,16 ; less than 16*65536 sectors (512 Mb)? + jb hd_bpb20 ; yes, leave cluster size the same + mov BPB_ALLOCSIZ[bx],16*2 ; use 16 K clusters if 512-1024 Mb + cmp dx,32 ; less than 32*65536 sectors (1 Gb)? + jb hd_bpb20 ; yes, leave cluster size the same + mov BPB_ALLOCSIZ[bx],32*2 ; use 32 K clusters if 1-2 Gb + +hd_bpb20: ; cluster size determined + sub ax,1+(512*32/SECSIZE) ; subtract reserved+root directory + sbb dx,0 ; (note: 32 bytes per entry) + xor cx,cx + mov ch,BPB_ALLOCSIZ[bx] ; CX = (256 * # of clusters on drive) + dec cx + add ax,cx ; add in for rounding error + adc dx,0 + inc cx + div cx ; AX = # of fat sectors + mov BPB_FATSEC[bx],ax ; remember FAT size + mov es:UDSC_FSTYPE+4[di],'6'; change "FAT12" to "FAT16" + ret + + + +new_unit: + push ds + push ax + push bx + push cx + push dx + push si + mov es,cs:DataSegment + mov di,endbios ; get next unit descriptor + mov cx,UDSC_LENGTH + add endbios,cx ; grow the BIOS size + xor ax,ax + push di + rep stosb ; zero the UDSC + pop di + xor bx,bx + mov bl,nunits ; BX = unit we are working on + mov es:UDSC_DRIVE[di],bl ; make that our logical unit + shl bx,1 ; make it a BPB index + lea ax,es:UDSC_DEVBPB[di] ; get storage area for device BPB + mov bpbtbl[bx],ax ; update entry in BPB table + shr bx,1 ; get the latest drive + inc bx ; onto next unit + cmp bl,2 ; 3rd floppy ? + jne new_unit10 + add bl,nhard ; yes, skip past hard disks +new_unit10: + mov nunits,bl ; store ready for next time + mov es:UDSC_RUNIT[di],0FFh ; set physical drive (ROS code) + push cs + pop ds ; DS:SI -> our dummy value + mov si,offset CGROUP:dummyMediaID + call UpdateMediaID ; update UDSC_ with media info + pop si + pop dx + pop cx + pop bx + pop ax + pop ds + ret + + +ICODE ends + +RESBIOS segment 'RESBIOS' +; NOTE: we extend the resident BIOS size by the amount of +; memory required by the disk driver. + db MAXPART*UDSC_LENGTH dup (?) +RESBIOS ends + +IDATA segment +p_unit db ? ; 80h, 81h for hard disks +nsect db ? ; # of sectors per track +nhead db ? ; # of heads on disk +part_size dw 2 dup (?) ; temporary save address for size +nunits db 2 ; start with driver C: +nhard db 0 ; # of hard disk partitions +nfloppy db 0 ; # of floppy drives + + Public init_runit +init_runit db 0 ; poked with ROS Unit at boot + +IDATA ends + + end diff --git a/IBMBIO/DOSHNDL.DEF b/IBMBIO/DOSHNDL.DEF new file mode 100644 index 0000000..e93d690 --- /dev/null +++ b/IBMBIO/DOSHNDL.DEF @@ -0,0 +1,123 @@ +; File : $DOSHNDL.DEF$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG + + +DCNTRL_DSADD equ dword ptr 0000h +DCNTRL_DSOFF equ word ptr 0000h +DCNTRL_DSSEG equ word ptr 0002h +DCNTRL_COUNT equ word ptr 0004h +DCNTRL_LEN equ 6 + +DHNDL_COUNT equ word ptr 00h ; 00 - Usage Count +DHNDL_MODE equ word ptr 02h ; 02 - File Mode + +DHM_FCB equ 8000h ; marks as FCB +DHM_COMMIT equ 4000h ; auto-commit file +DHM_NOCRIT equ 2000h ; no critical errors +DHM_LOCAL equ 10000000b ; file is not inherited +DHM_SHAREMSK equ 01110000b ; sharing bits +DHM_COMPAT equ 00000000b +DHM_DENY_ALL equ 00010000b ; exclusive - deny all +DHM_DENY_WRITE equ 00100000b +DHM_DENY_READ equ 00110000b +DHM_DENY_NONE equ 01000000b +DHM_RWMSK equ 00001111b ; read write bits +DHM_RW equ 00000010b ; file opened read/write +DHM_WO equ 00000001b ; file opened write only +DHM_RO equ 00000000b ; file opened read only + +; +; 01h to 03h To be Determined +; +DHNDL_DATRB equ byte ptr 04h ; Disk attribute byte +DHNDL_ATTR equ byte ptr 05h ; Attribute Byte +DHNDL_WATTR equ word ptr 05h ; Attribute Word + +DHAT_REMOTE equ 8000h ; set if file remote +DHAT_TIMEOK equ 4000h ; set if timestamp up to date +DHAT_LOCAL equ 1000h ; file is not inherited +DHAT_NETPRN equ 0800h ; device is networked printer +DHAT_DEV equ 0080h ; device/file bit +DHAT_READY equ 0040h ; ready/not ready bit +DHAT_CLEAN equ 0040h ; this bit CLEAR if dirty +DHAT_BIN equ 0020h ; raw/cooked bit +DHAT_DRVMSK equ 001Fh ; drive in bottom bits +DHAT_CLK equ 0008h ; -reserved- +DHAT_NUL equ 0004h ; handle is null device +DHAT_COT equ 0002h ; handle is console output device +DHAT_CIN equ 0001h ; handle is console input device + +DHNDL_DEVPTR equ dword ptr 07h ; 07 - pointer to device +DHNDL_DEVOFF equ word ptr 07h ; 07 - offset of device +DHNDL_DEVSEG equ word ptr 09h ; 09 - segment of device +DHNDL_BLK1 equ word ptr 0Bh ; 0B - first cluster in file +DHNDL_TIME equ word ptr 0Dh ; 0D - file time stamp +DHNDL_DATE equ word ptr 0Fh ; 0F - file date stamp +DHNDL_SIZE equ dword ptr 11h ; 11 - file length +DHNDL_SIZELO equ word ptr 11h +DHNDL_SIZEHI equ word ptr 13h +DHNDL_POS equ dword ptr 15h ; 15 - current file position +DHNDL_POSLO equ word ptr 15h +DHNDL_POSHI equ word ptr 17h +DHNDL_IDX equ word ptr 19h ; 19 - relative cluster within file of last read +DHNDL_DBLK equ word ptr 1Bh ; 1B - cluster # of dir entry +DHNDL_DCNTHI equ byte ptr 1Eh ; 1E - dir offset # within cluster +DHNDL_DCNTLO equ byte ptr 1Fh ; 1F - dir offset # within cluster +DHNDL_NAME equ byte ptr 20h ; 20 - File/Device Name +DHNDL_EXT equ byte ptr 28h ; 28 - File extension +DHNDL_SFT equ dword ptr 2Bh ; 2B - pointer to previous SFT +DHNDL_UID equ word ptr 2Fh ; 2F - Owning Machine ID +DHNDL_PSP equ word ptr 31h ; 31 - Owning PSP +DHNDL_SHARE equ word ptr 33h ; 33 - Offset of sharing record +DHNDL_BLK equ word ptr 35h ; 35 - absolute cluster of last read + ; 37 - dword reserved for IFS +DHNDL_LEN equ 3Bh + +; With DOS 3 structures _DBLK is a 16 bit + + +; Logical Drive Table format +LDT_NAME equ byte ptr 00h ; 00 - Ascii Name field +LDT_FLAGS equ word ptr 43h ; 43 - Flag field +LDT_PDT equ dword ptr 45h ; 45 - PDT for this drive +LDT_BLK equ word ptr 49h ; 49 - directory sector +LDT_ROOT equ word ptr 4bh ; 4B - virtual block root +LDT_DRV equ byte ptr 4dh ; 4D - physical drive +LDT_ROOTLEN equ word ptr 4fh ; 4F - Length of root portion +LDT_LEN equ 58h + +LFLG_NETWRKD equ 8000h +LFLG_PHYSICAL equ 4000h +LFLG_JOINED equ 2000h +LFLG_SUBST equ 1000h diff --git a/IBMBIO/DRIVER.EQU b/IBMBIO/DRIVER.EQU new file mode 100644 index 0000000..a5809cb --- /dev/null +++ b/IBMBIO/DRIVER.EQU @@ -0,0 +1,59 @@ +; File : $DRIVER.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; ENDLOG +; Device driver header offsets. + + +DH_NEXT equ es:dword ptr 0 ; Dword Pointer to Next DEV +DH_NEXTOFF equ es:word ptr 0 ; Offset of next device +DH_NEXTSEG equ es:word ptr 2 ; Segment of next device +DH_ATTRIB equ es:word ptr 4 ; device attribute bits +DH_STRATEGY equ es:word ptr 6 ; offset of strategy entry +DH_INTERRUPT equ es:word ptr 8 ; offset of interupt entry +DH_NAME equ es:byte ptr 10 ; 8-BYTE device name + +DA_CHARDEV equ 8000h ; 1=character device, 0=block device +DA_IOCTL equ 4000h ; device supports IOCTL string I/O +DA_NONIBM equ 2000h ; dosen't require FAT for login +DA_OTILBSY equ 2000h ; supports "output until busy" +DA_REMOVE equ 0800h ; supports "removable media" check +DA_QUERY equ 0080h ; supports query ioctl +DA_GETSET equ 0040h ; supports 3.2 level functionality +DA_SPECIAL equ 0010h ; fast console ouput via INT 29h +DA_ISCLK equ 0008h ; device is current clock device +DA_ISNUL equ 0004h ; device is NUL device (reserved) +DA_BIGDRV equ 0002h ; supports > 65535 sector per drive +DA_ISCOT equ 0002h ; device is standard output device +DA_ISCIN equ 0001h ; device is standard input device + +FASTCON_INT equ 29h ; fast console output interrupt + diff --git a/IBMBIO/DRMACROS.EQU b/IBMBIO/DRMACROS.EQU new file mode 100644 index 0000000..b5830a2 --- /dev/null +++ b/IBMBIO/DRMACROS.EQU @@ -0,0 +1,85 @@ +; File : $DRMACROS.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +; 09-Nov-88 made RETF conditional for MASM 5.1/TASM 1.0 + +FALSE equ 0 +TRUE equ (not FALSE) + +ifndef @filename ;; Turbo Assembler always knows RETF + ;; some versions of MASM do as well +retf macro ;; define far return macro for others + db 0cbh + endm +endif + +jmps macro l + jmp short l + endm + +pushx macro regs + irp r, + push r + endm + endm + +popx macro regs + irp r, + pop r + endm + endm + +incx macro regs + irp r, + inc r + endm + endm + +decx macro regs + irp r, + dec r + endm + endm + +rb macro count + db count dup (?) + endm + +rw macro count + dw count dup (?) + endm + +rd macro count + dd count dup (?) + endm + diff --git a/IBMBIO/F52DATA.DEF b/IBMBIO/F52DATA.DEF new file mode 100644 index 0000000..44bb546 --- /dev/null +++ b/IBMBIO/F52DATA.DEF @@ -0,0 +1,88 @@ +; File : $F52DATA.DEF$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +; The following equates define the Data Area whose address is +; returned by function 52. +; + +F52_BCBBUF equ es:dword ptr -0008h[bx] ; current buffer +F52_BCBOFF equ es:word ptr -0008h[bx] ; current buffer +F52_BCBSEG equ es:word ptr -0006h[bx] ; current buffer +F52_DMDROOT equ es:word ptr -0002h[bx] ; Memory Descriptor Root (Seg) +F52_DDSCPTR equ es:dword ptr 0000h[bx] ; DDSC Table Address +F52_FILEPTR equ es:dword ptr 0004h[bx] ; File Handle Table Address +F52_CLKDEV equ es:dword ptr 0008h[bx] ; Clock Device Header +F52_CONDEV equ es:dword ptr 000Ch[bx] ; Console Device Header +F52_SECSIZE equ es:word ptr 0010h[bx] ; Maximum Sector Size +F52_BUFINFOPTR equ es:dword ptr 0012h[bx] ; Buffer Info pointer +F52_PATHPTR equ es:dword ptr 0016h[bx] ; Path Control Table Address +F52_PATHOFF equ es:word ptr 0016h[bx] +F52_PATHSEG equ es:word ptr 0018h[bx] +F52_FCBPTR equ es:dword ptr 001Ah[bx] ; FCB Table Address +; equ es:word ptr 001Eh[bx] ; #Entries in FCB Table +F52_PHYDRV equ es:byte ptr 0020h[bx] ; Last Physical Drive +F52_LASTDRV equ es:byte ptr 0021h[bx] ; Last Logical Drive +F52_DEVROOT equ es:dword ptr 0022h[bx] ; Root Device Header +F52_JOINDRV equ es:byte ptr 0034h[bx] ; Number of JOIN'd drives +F52_SETVER equ es:dword ptr 0037h[bx] ; SETVER table pointer +F52_NUM_BUF equ es:word ptr 003Fh[bx] ; number of disk buffers +F52_READ_AHEAD equ es:word ptr 0041h[bx] ; size of read-ahead buffer +F52_BOOTDRV equ es:byte ptr 0043h[bx] ; boot drive (1-26) +F52_CPU_TYPE equ es:byte ptr 0044h[bx] ; 01 if >= 386SX +F52_EXT_MEM equ es:word ptr 0045h[bx] ; Int 15h, AH=87h +F52_BUF_INFO equ es:dword ptr 0047h[bx] ; points at Buffer Info +F52_HMAFLAG equ es:byte ptr 0053h[bx] ; 1 if buffers in HMA +F52_DEBLOCK equ es:word ptr 0056h[bx] ; deblock if buffers in HMA +F52_DMD_UPPER equ es:word ptr 0066h[bx] ; upper memory chain +F52_SHARE_STUB equ es:dword ptr 006Ah[bx] ; Share Stub Entries*15 + +;DRDOS Specific + +DRDOS_CRITSTUBS equ es:word ptr 0000h[bx] ; Offset of end of instance data +DRDOS_HIST1CTL equ es:word ptr 0004h[bx] ; History 1 Control +DRDOS_HIST2CTL equ es:word ptr 0006h[bx] ; History 2 Control +DRDOS_HISTFLG equ es:byte ptr 0008h[bx] ; History Buffer Flag +DRDOS_DUAL_LANG equ es:byte ptr 0009h[bx] ; Utils Dual Language Support +DRDOS_CUR_LANG equ es:byte ptr 000Ah[bx] ; Current Language +DRDOS_EXT_MEM equ es:word ptr 000Bh[bx] ; Total Extended Memory +DRDOS_HIMEM_ROOT equ es:word ptr 0010h[bx] ; High memory chain +DRDOS_ENVSEG equ es:word ptr 0012h[bx] ; Seg of environment +DRDOS_DMD_BASE equ es:word ptr 0016h[bx] ; base memory freed at +DRDOS_DMD_UPPER equ es:word ptr 0018h[bx] ; upper memory chain +DRDOS_MACHINE_ID equ es:word ptr 001Ah[bx] ; local machine ID +DRDOS_COUNTRY_FILE equ es:word ptr 001Eh[bx] ; offset of filename +DRDOS_HASHOFF equ es:word ptr 0020h[bx] ; fastopen hash root +DRDOS_HASHSEG equ es:word ptr 0022h[bx] ; pointer +DRDOS_HASHMAX equ es:word ptr 0024h[bx] ; max # dir entries +DRDOS_DEBLOCK equ es:word ptr 0026h[bx] ; himem deblock buffer +DRDOS_INT2F equ es:word ptr 002Ch[bx] ; internal Int 2F hook diff --git a/IBMBIO/FDOS.EQU b/IBMBIO/FDOS.EQU new file mode 100644 index 0000000..71954ca --- /dev/null +++ b/IBMBIO/FDOS.EQU @@ -0,0 +1,220 @@ +; File : $FDOS.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +; Structure of Buffer Control Blocks +; ---------------------------------- +; These BCBs immediately preceed the data buffers. BCBs are +; always shared for all drives and therefore must be big +; enough for the largest drive. +; + +BCB_NEXT equ word ptr 00h ; link to next buffer +BCB_PREV equ word ptr 02h ; link to previous buffer +BCB_DRV equ byte ptr 04h ; drive of this buffer or 0FFh +BCB_FLAGS equ byte ptr 05h ; buffer flags +BCB_REC equ word ptr 06h ; low 16 bits of sector address +BCB_REC2 equ byte ptr 08h ; top 8 bits of record address +BCB_COPIES equ byte ptr 0Ah ; number of copies to write +BCB_SEPARATION equ word ptr 0Bh ; # sectors copies are apart +BCB_DDSC equ dword ptr 0Dh ; DWORD ptr to DDSC_ +BCB_REMOTE equ word ptr 11h ; remote in-use count +BCB_DATA equ byte ptr 14h ; buffer data + +BF_ISFAT equ 0002h ; buffer marked as FAT sector +BF_ISDIR equ 0004h ; buffer marked as Directory sector +BF_ISDAT equ 0008h ; buffer marked as Data sector +BF_DIRTY equ 0040h ; buffer marked as modified +BF_REMOTE equ 0080h ; buffer is remote + +MAX12 equ 0FF6h ; max. disk size w/ 12-bit media + +; Structure of Hash Control Block +; ------------------------------- +; Each hash control block refers to the hash codes of one +; disrectory cluster or a root directory. + +HCB_LINK equ word ptr 0 ; link to next control block +HCB_DRV equ byte ptr 2 ; drive for this entry or 0FFh +HCB_CLU equ word ptr 4 ; cluster number or 0000 if root +HCB_CNT equ word ptr 6 ; number of hashed entries +HCB_DATA equ word ptr 8 ; hash buffer data + + +; Structure of DOS FCB +; -------------------- + +MSF_EXTFLG equ byte ptr 0 ; if this is 0xFF, skip 1st 7 byte +MSF_ATTRIB equ byte ptr 6 ; file attributes if MSF_EXTFLG +MSF_DRIVE equ byte ptr 0 ; 1st byte normally drive code +MSF_NAME equ byte ptr 1 ; 8-bit ASCII file name, 11 characters +MSF_BLOCK equ word ptr 12 ; current block number +MSF_RECSIZE equ word ptr 14 ; current logical record size +MSF_SIZE equ word ptr 16 ; 32-bit file size +MSF_DATE equ word ptr 20 ; last date stamp +MSF_TIME equ word ptr 22 ; last time stamp +MSF_IFN equ byte ptr 24 ;; internal file number +MSF_IOCTL equ byte ptr 25 ;; file status +MSF_BLOCK1 equ word ptr 26 ;; 1st block of file +MSF_DBLK equ word ptr 28 ;; directory block +MSF_DEVPTR equ dword ptr 28 ;; address of device driver +MSF_DCNT equ word ptr 30 ;; directory count +MSF_CR equ byte ptr 32 ; current sequential record +MSF_RR equ word ptr 33 ; random record address (3 or 4 byte) +MSF_RR2 equ byte ptr 35 ; random record overflow + + +; Structure of DOS DPB +; -------------------- + +DDSC_UNIT equ byte ptr 0 ; absolute drive number +DDSC_RUNIT equ byte ptr 1 ; relative unit number +DDSC_SECSIZE equ word ptr 2 ; sector size in bytes +DDSC_CLMSK equ byte ptr 4 ; sectors/cluster - 1 +DDSC_CLSHF equ byte ptr 5 ; log2 (sectors/cluster) +DDSC_FATADDR equ word ptr 6 ; sector address of FAT +DDSC_NFATS equ byte ptr 8 ; # of FAT copies +DDSC_DIRENT equ word ptr 9 ; size of root directory +DDSC_DATADDR equ word ptr 11 ; sector address of cluster #2 +DDSC_NCLSTRS equ word ptr 13 ; # of clusters on disk +DDSC_NFATRECS equ word ptr 15 ; # of sectors per FAT +DDSC_DIRADDR equ word ptr 17 ; sector address of root dir +DDSC_DEVHEAD equ dword ptr 19 ; device driver header +DDSC_DEVOFF equ word ptr 19 +DDSC_DEVSEG equ word ptr 21 +DDSC_MEDIA equ byte ptr 23 ; current media byte +DDSC_FIRST equ byte ptr 24 ; "drive never accessed" flag +DDSC_LINK equ dword ptr 25 ; next drive's DDSC +DDSC_BLOCK equ word ptr 29 ; next block to allocate +DDSC_FREE equ word ptr 31 ; total free clusters on drive +DDSC_LEN equ 33 + + + +; DELWATCH hooks called by OS + +DELW_RDMASK equ 0 ; delete dir search mask +DELW_DELETE equ 2 ; delete this dir entry +DELW_FREECLU equ 3 ; free some clusters +DELW_FREERD equ 4 ; free root dir entry +DELW_SPACE equ 5 ; add "deletes" to free space +DELW_NEWDISK equ 7 ; new disk logged in +DELW_PURGE equ 14 ; perge pd file +DELW_UNDEL equ 15 ; undelete pd file + +; SuperStore hook called by OS + +SSTOR_SPACE equ 10h ; enquire # physical free space + +; Password hooks called by OS + +PASSWD_CREAT equ 20h ; initialise an entry +PASSWD_CHMOD equ 21h ; change an entry +PASSWD_CHECK equ 22h ; check an entry + +; Share hooks in PCMODE data segment +; +; These point to a stub which does a "STC, RETF" +; + +NUM_SHARE_STUB_ENTRIES equ 15 + +S_LOCKS equ DWORD*0 ; share lock/unlock region +S_UPDATE equ DWORD*1 ; update DHNDL from share +S_RECORD equ DWORD*2 ; update share from DHNDL +S_FDOSRW equ DWORD*3 ; validate proposed operation +S_DISCARD equ DWORD*4 ; discard all files on drive +S_OPEN equ DWORD*5 ; files is opening, remember it +S_CLOSE equ DWORD*6 ; files is closing, forget it +S_OM_COMPAT equ DWORD*7 ; check open mode compatible +S_CLOSE_IF_OPEN equ DWORD*8 ; close if compat open, else deny +S_DENY_IF_OPEN equ DWORD*9 ; deny if open shared/by others +S_GET_LIST_ENTRY equ DWORD*10 ; get open file list entry +S_CLOSE_FILES equ DWORD*11 ; close all files for given PSP/UID + +; struct dirfcb + +DNAME equ byte ptr 0 ;file name & type +DATTS equ byte ptr 11 + DA_RO equ 01h ; 0x01 - read/only + DA_HIDDEN equ 02h ; 0x02 - hidden + DA_SYSTEM equ 04h ; 0x04 - system + DA_VOLUME equ 08h ; 0x08 - volume label + DA_DIR equ 10h ; 0x10 - sub-directory + DA_ARCHIVE equ 20h ; 0x20 - archive + DA_CLUSTER equ 80h ; 0x80 - return starting cluster from search (API extention) + DA_DELWATCH equ 80h ; 0x88 - return pending delete files + DA_FIXED equ 11011000b ; can't CHMOD label, dir, unused bits + DA_CHANGE equ not DA_FIXED ; all others are changeable + +;DATTS2 equ 12 ;CP/M attributes +; ; 0x80 - f1' modify default open rules +; ; 0x40 - f2' partial close default +; ; 0x20 - f3' ignore close checksum errors +; ; 0x10 - f4' disable checksums +; ; 0x08 - (reserved) +; ; 0x04 - DELETE password +; ; 0x02 - WRITE password +; ; 0x01 - READ password +DUNDEL equ 13 ;1st letter of deleted file +DPWD equ word ptr 14 ;16-bit password hash code +DMODTIME equ word ptr 16 ;delwatch time (hhhhhmmmmmmsssss) +DMODDATE equ word ptr 18 ;delwatch date (yyyyyyymmmmddddd) +;DRECSIZE equ 16 ;FlexOS record size +;DUSER equ 18 ;FlexOS user ID of creator +;DGROUP equ 19 ;FlexOS group ID of creator +DPWM equ word ptr 20 ;FlexOS access rights +DTIME equ 22 ;time (hhhhhmmmmmmsssss) +DDATE equ 24 ;date (yyyyyyymmmmddddd) +DBLOCK1 equ 26 ;first block in file +DSIZE equ 28 ;current file size + +; DOS Media Password Definitions +; ------------------------------ + +PWM_OWNER equ 000Fh ; PWD Owner mask +PWM_GROUP equ 00F0h ; PWD Group mask +PWM_WORLD equ 0F00h ; PWD World mask +PWM_R equ 0888h ; PWD required for reading +PWM_W equ 0444h ; PWD required for writing +PWM_E equ 0222h ; PWD req'd for executing +PWM_D equ 0111h ; PWD required for deleting +PWM_ANY equ PWM_R+PWM_W+PWM_D ; PWD required for anything + + +; literal constants + +FAT12 equ 00fffh ; 12 bit fat +FAT16 equ 0ffffh ; 16 bit fat + +ENDDIR equ 0ffffh ;end of directory + diff --git a/IBMBIO/GENERCFG.A86 b/IBMBIO/GENERCFG.A86 new file mode 100644 index 0000000..6f95228 --- /dev/null +++ b/IBMBIO/GENERCFG.A86 @@ -0,0 +1,3607 @@ +; File : $GENERCFG.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; GENERCFG.A86 1.51 93/12/02 00:15:06 +; When auto-sizing DEVICEHIGH requirements use EXE header info if present +; GENERCFG.A86 1.49 93/11/29 14:10:29 +; Add NUMLOCK=ON/OFF support +; GENERCFG.A86 1.48 93/11/28 15:32:22 +; Support HIBUFFERS in UMB's +; GENERCFG.A86 1.47 93/11/22 15:45:11 +; Ignore [COMMON] statements +; GENERCFG.A86 1.46 93/11/18 16:20:16 +; Add primitive multi-master checking +; GENERCFG.A86 1.45 93/11/17 20:07:17 +; change history defaults +; GENERCFG.A86 1.44 93/11/16 14:10:21 +; F5 has precedence over ? +; GENERCFG.A86 1.42 93/11/08 17:37:06 +; Move INSTALLHIGH to before INSTALL, so it's now recognised +; GENERCFG.A86 1.41 93/11/04 16:28:08 +; Cosmetic change - the preload name field now strips off "C:\" properly +; GENERCFG.A86 1.40 93/11/03 22:52:14 +; Replace chardev test with one for zero units +; GENERCFG.A86 1.39 93/11/03 18:21:16 +; disable CHARDEV test until it gets fixed +; GENERCFG.A86 1.38 93/11/03 17:11:05 +; Preloaded compression drivers maybe loaded from C: when booting +; from a diskette. +; GENERCFG.A86 1.37 93/10/29 19:42:51 +; DOS=UMB turns HIDOS on +; GENERCFG.A86 1.36 93/09/28 19:54:52 +; Support "DEVICE?=" syntax, and "SWITCHES=/N" +; GENERCFG.A86 1.35 93/09/02 22:35:16 +; Add header to system allocations +; GENERCFG.A86 1.32 93/08/02 14:46:21 +; hide preload drives from func_device +; support INSTALLHIGH +; GENERCFG.A86 1.30 93/07/29 14:47:15 +; Change SETVER method +; GENERCFG.A86 1.28 93/07/20 22:32:07 +; default upper memory link = FFFF +; ENDLOG + + + include config.equ + include i:msdos.equ + include i:char.def + include i:reqhdr.equ + include i:driver.equ + include i:fdos.equ + include i:f52data.def ; Function 52 DOS Data Area + include i:doshndl.def ; DOS Handle Structure Definition + include i:country.def + +TRUE equ 0FFFFh ; value of TRUE +FALSE equ 0 ; value of FALSE + +F5KEY equ 3F00h ; keys returned by BIOS +F8KEY equ 4200h ; in boot_options + +CGROUP group INITCODE, INITDATA, INITENV + +INITCODE CSEG PARA 'INITCODE' + + extrn whitespace:near + extrn build_cmd_tail:near + extrn device_init:near + extrn init_static_request:near + extrn block_device:near + extrn device_insert:near +if not ADDDRV + extrn nls_hook:near + extrn nls_unhook:near +endif + +CONFIG_ERRLVL equ 400h ; special 'CONFIG' error level + +; config_process returns CF set if an error occurred during command file +; processing for ADDDRV.EXE + + Public config_process +config_process: ; Process CONFIG.SYS + + mov save_sp,sp ; save SP for unstructured GOSUB's + +if ADDDRV + mov error_flag,0 +else + mov ax,offset envstart ; env buffer is para aligned + mov cl,4 + shr ax,cl ; convert offset to paras + mov cx,ds + add ax,cx ; segment of env variables + les bx,drdos_ptr + mov es:DRDOS_ENVSEG[bx],ax ; tell COMMAND.COM where we are + push ds ! pop es +endif + + mov ah,MS_DRV_GET ; check whether we are loading from + int DOS_INT ; drive C: + cmp al,2 + je preload_security + push ds + mov ah,32h ; get DOS parameter block + mov dl,3 ; ensure drive C: is valid (no critical + int DOS_INT ; errors) + pop ds + cmp al,0ffh ; skip if the drive is not valid + je preload_stacker + mov alt_drive,1 ; drive C: should be used also + jmp preload_stacker + +preload_security: + call preload_device ; preload the SECURITY device driver + +preload_stacker: + mov preload_file,offset stacker_file+2 + call preload_device ; preload STACKER from default drive + jnc preload_done + + mov preload_file,offset dblspace_file+2 + call preload_device ; STACKER failed, try DBLSPACE from default + jnc preload_done + + cmp alt_drive,0 ; STACKER and DBLSPACE failed on A:, + je preload_done ; should we look on drive C:? + + mov preload_file,offset stacker_file + call preload_device ; preload STACKER from drive C: + jnc preload_done + + mov preload_file,offset dblspace_file + call preload_device ; STACKER failed, try DBLSPACE from C: + +preload_done: + mov ax,(MS_X_OPEN*256)+80h ; Open the configuration file + mov dx,offset cfg_file ; Try Opening the file DCONFIG.SYS + int DOS_INT ; if this fails then open CONFIG.SYS + jnc cfg_20 ; Found DCONFIG.SYS + +if ADDDRV + mov si,dx + mov dx,offset err_no_command_file + xor al,al + call config_error + jmps cfg_exit +else + mov si,offset cfg_file+1 + mov di,offset cfg_file + call copy_asciiz ; make DCONFIG.SYS = CONFIG.SYS + + mov ax,(MS_X_OPEN*256)+80h ; Open the configuration file + int DOS_INT ; CONFIG.SYS + jc cfg_exit ; Return on error without complaint +endif + +cfg_20: + mov bx,ax ; get the CONFIG handle + mov ah,MS_X_CLOSE ; Close the CONFIG file + int DOS_INT + +cfg_nextline: ; Read the next command line + call readline ; If Carry then Terminal Error + jc cfg_exit ; so Exit + mov ax,boot_options +cfg_continue: + push ax ; save query options + call scan ; Now Scan the command List + pop ax ; recover query options + jc cfg_error ; for a matching command name + call cfg_query ; prompt to see if we want it + jc cfg_nextline + call CFG_FUNC[di] ; Execute the request command + jmps cfg_nextline ; and loop till the end of the file + +cfg_error: + mov dx,offset bad_command ; Display a Bad command error msg + mov al,CR ; and the CR terminated string + call config_error ; then continue processing + jmps cfg_nextline ; Carry Returned On Error + +cfg_exit: + mov sp,save_sp ; get back the real stack + call preload_complete ; move transcient code to final position +if ADDDRV + cmp error_flag,1 ;Set CF if error flag is zero + cmc ;Set CF if error flag is 1 +endif + ret + + +cfg_query: +; On Entry: +; AX = boot_options key +; SI -> command tail +; DI -> CFG_ +; On Exit: +; CY set if we should skip command +; SI/DI preserved +; + push si + push di + test CFG_FLAGS[di],CF_NOF ; are Function Keys allowed ? +; clc ; if not process the command + jz $+5 ! jmp cfg_query90 + cmp ax,F5KEY ; F5 bypasses CONFIG processing + stc ; so bypass this line + je cfg_query90 + test CFG_FLAGS[di],CF_QUERY ; specific QUERY request ? + jnz cfg_query10 + cmp ax,F8KEY ; should we prompt for everything ? + clc ; if not process the command + jne cfg_query90 +cfg_query10: + push si + mov si,CFG_NAME[di] ; DS:SI -> command name we matched +cfg_query20: + lodsb ; get character + test al,al ; zero terminated + jz cfg_query30 + xchg ax,dx ; DL= character + mov ah,MS_C_WRITE + int DOS_INT ; output the character + jmps cfg_query20 ; "DEVICE" +cfg_query30: + mov dl,'=' + mov ah,MS_C_WRITE + int DOS_INT ; "DEVICE=" + pop si ; rest of command line +cfg_query40: + lodsb + cmp al,CR ; is it the end of the line ? + je cfg_query50 ; no, do another character + xchg ax,dx ; DL= character + mov ah,MS_C_WRITE + int DOS_INT ; output the character + jmps cfg_query40 ; "DEVICE=FILENAME.SYS" +cfg_query50: + mov ah,MS_C_WRITESTR ; Output msg of form " (Y/N) ? " + mov dx,offset confirm_msg1 + int DOS_INT ; do " (" + mov ah,MS_C_WRITE + mov dl,yes_char + int DOS_INT ; do "Y" + mov dl,'/' + int DOS_INT ; do "/" + mov dl,no_char + int DOS_INT ; do "N" + mov ah,MS_C_WRITESTR + mov dx,offset confirm_msg2 + int DOS_INT ; do ") ? " +cfg_query60: + call wait_for_key ; wait until a key is pressed + mov al,default_query_char ; if we timeout default + jc cfg_query70 + mov ah,MS_C_RAWIN + int DOS_INT ; read a char + test al,al ; is it a function key ? + jnz cfg_query70 + mov ah,MS_C_RAWIN + int DOS_INT ; throw away function keys + jmps cfg_query60 +cfg_query70: + push ax ; save response + mov ah,MS_C_WRITE + mov dl,al + int DOS_INT ; echo the char + mov ah,MS_C_WRITESTR + mov dx,offset confirm_msg3 ; "DEVICE=FILENAME.SYS (Y/N) ?" + int DOS_INT ; now do CR/LF to tidy up + pop ax + call toupper ; make response upper case + cmp al,yes_char ; is it yes ? + je cfg_query90 + stc ; return CY set, skip this line +cfg_query90: + pop di + pop si + ret + + +call_preload_entry: ; call the preload device driver back door + push ds ; all DBLSPACE calls destroy DS register + callf preload_entry + pop ds + ret + +preload_complete: ; CONFIG processing complete + push ds + push es + mov ax,4a11h ; DBLSPACE presence check + xor bx,bx + int 2fh + or ax,ax + jnz reloc_end + test dx,8000h ; is relocation already complete (may + jz reloc_end ; be done by HIDEVICE statement) + mov bx,0ffffh ; query the size of the transcient + mov ax,4a11h ; portion + int 2fh + + mov cx,mem_current ; pull transcient portion down to low + mov es,cx ; memory + inc cx + mov es:DMD_ID,'D' ; control block type is 'D' (device + mov es:DMD_PSP,cx ; driver), owner is self + mov es:DMD_LEN,ax + inc ax ; control block overhead + add mem_current,ax + mov di,8 ; copy the name to the control block + mov si,preload_file ; device filename +preload_complete10: + lodsb ; get a character + cmp al,'\' ; have we found the '\' yet ? + jne preload_complete10 ; no, go swallow another character + movsw ! movsw ! movsw ! movsw ; copy the 8 bytes + mov ax,es + inc ax ; segment address of free memory + mov es,ax + mov bx,0fffeh ; move transcient portion down + mov ax,4a11h + int 2fh +reloc_end: + pop es + pop ds + ret + +PreloadFixup: +;------------ +; On Entry: +; None +; On Exit: +; None +; All regs preserved +; + push es + push bx + push ax + mov al,preload_drv ; get number of preload drives + les bx,func52_ptr + sub es:F52_PHYDRV[bx],al + sub es:F52_LASTDRV[bx],al + pop ax + pop bx + pop es + ret + +PreloadCleanup: +;-------------- +; On Entry: +; None +; On Exit: +; None +; +; inform DBLSPACE about each device driver + push ds + push es + xor ax,ax + xchg al,preload_drv ; get number of preload drives + les bx,func52_ptr + add es:F52_PHYDRV[bx],al + add es:F52_LASTDRV[bx],al + mov ax,4a11h ; DBLSPACE installation check + xor bx,bx + int 2fh + or ax,ax + jnz broadcast_exit + test dx,8000h ; initialisation complete? + jz broadcast_exit + mov preload_drv,ch ; save # preload drives + mov dx,mem_max ; top of available memory + mov cx,mem_current ; base of available memory + sub dx,cx + mov ah,55h ; version number + mov al,dev_count ; number of new units installed + mov bx,02h + callf preload_entry +broadcast_exit: + pop es + pop ds + ret + +preload_device: ; preload disk compression driver before + ; processing (D)CONFIG.SYS file + mov dx,preload_file + mov cx,mem_current ; next available segment address + mov es,cx + inc cx + mov es:DMD_ID,'D' ; control block type is 'D' (device + mov es:DMD_PSP,cx ; driver), owner is self + mov di,8 ; copy the name to the control block + mov si,dx ; device filename +preload_device10: + lodsb ; get a character + cmp al,'\' ; have we found the '\' yet ? + jne preload_device10 ; no, go swallow another character + movsw ! movsw ! movsw ! movsw ; copy the 8 bytes + mov ax,es + inc ax ; segment address of free memory + mov dev_load_seg,ax ; destination segment for EXEC call + mov dev_reloc_seg,ax ; relocation factor for .EXE drivers + push ax + push ds ! pop es + mov bx,offset dev_epb ; ES:BX control structure + mov ax,(MS_X_EXEC * 256)+3 + int DOS_INT + pop es ; ES:0 -> preload driver + jnc load_ok +load_bad: + jmp preload_exit +load_ok: + cmp es:WORD PTR .12h,2e2ch ; preload device signature + jne load_bad + mov preload_seg,es ; back door entry to preload driver + cmp es:word ptr .82h,6 ; is it the old DBLSPACE driver ? + jne load_new_dblspace + mov preload_ver,6 ; yes, give it the old version +load_new_dblspace: + mov rel_unit,0 ; reset driver relative unit no. + mov bx,offset request_hdr ; DS:BX static INIT request header + mov ax,mem_max ; highest segment available to the + mov ds:RH0_RESIDENT,0 ; driver + mov ds:RH0_RESIDENT+2,ax + mov ax,cs + mov es,ax + push ds + call init_static_request ; initialise remaining fields + mov ax,cs:preload_ver + callf preload_entry + pop ds + jc preload_exit ; INIT function fails if CARRY set + or ax,ax ; or AX != 0 + jnz preload_exit +;; mov ax,ds:RH0_RESIDENT ; end of resident portion (offset) +;; add ax,15 ; convert offset to paragraph size +;; mov cl,4 +;; shr ax,cl +;; add ax,ds:RH0_RESIDENT+2 ; end of resident portion (segment) +;JS we should check that the source and destination do not overlap here! + + mov bx,04h ; find the size of the transient code + call call_preload_entry + sub mem_max,ax ; move the top of available memory down + + mov es,mem_max ; ES destination for relocatable code + dec mem_max ; last free segment address + mov bx,06h ; call driver to relocate code etc. + call call_preload_entry + inc ax + mov mem_current,ax ; update base of free TPA + + mov es,preload_seg + xor di,di ; ES:DI -> preload driver + mov bx,offset request_hdr + mov al,ds:RH0_NUNITS + test al,al + jz preload_char_dev + add preload_drv,al ; remember how many preloaded drives + call block_device ; setup the DPBs and other block structures + +preload_char_dev: + mov cx,mem_current + mov ax,preload_seg + sub cx,ax ; CX = length of preload driver + dec ax + mov es,ax ; ES:0 -> "DMD" for preload driver + mov es:DMD_LEN,cx + inc ax + mov es,ax + xor di,di ; ES:DI -> "device" header + mov ax,0FFFFh + mov es:[di],ax + mov es:2[di],ax + call device_insert ; insert device into chain + + mov dx,mem_max ; top of available memory + mov cx,mem_current ; base of available memory + sub dx,cx + mov ax,5500h ; AH = version, AL = all internal drives + mov bx,02h ; mount existing container files + call call_preload_entry + + xor bx,bx ; complete initialisation (hook + call call_preload_entry ; interrupts etc.) + +preload_exit: + push cs ! pop es + ret + + + +func_hidevice: ; HIDEVICE=filename +; Look for /L:r1[,s1][;r2[,s2]] [/S] filename +; Look for SIZE= filename + + mov himem_region,0 ; assume no region supplied + mov himem_size,0 ; and no size + mov di,offset region_opt ; check out /L: region option + call compare + jc hidevice10 + call parse_region ; get region and size + jnc hidevice20 + xor si,si ; something wrong, give an error + mov dx,offset bad_filename + jmp config_error + +hidevice10: + mov di,offset size_opt ; check out SIZE= option + call compare + jc hidevice20 ; if no SIZE= just try to load it + call parse_size ; else get supplied value +hidevice20: + call whitespace ; we may have a '=' lurking +hidevice30: + lodsb ; strip off optional '=' + cmp al,'=' ; before the filename + je hidevice30 + dec si ; it wasn't a '=' after all + call whitespace + + mov ax,himem_size ; get size parameter + cmp ax,6000h ; should we just load low ? + jae func_device + push si + test ax,ax ; have we been given a size ? + jne hidevice40 + call size_file ; get requirements from file size +hidevice40: + call himem_setup ; try and find some hi memory + pop si + jc func_device ; if we can't load low + push si + call func_device ; now try and install the device + call himem_cleanup ; clean up our hi memory + pop si + jc func_device ; error loading hi, try low + ret + + +func_device: ; DEVICE=filename + push si + mov di,offset dev_name ; Copy the Device Filename into a + mov byte ptr [di],0 ; local buffer and zero terminate + call copy_file + pop si ; Restore original SI + jc device_error + + push es + push si + mov es,mem_current ; ES points at structure + call BuildHeader + pop si + push si + call FindName ; DS:SI -> leafname + call SetName ; Fill in name info + pop si + pop es + + mov ax,mem_current ; Get Current Memory Base + inc ax ; allow a para for a header + mov dev_load_seg,ax ; Setup the Load Address and the + mov dev_reloc_seg,ax ; relocation factor to be applied to + ; .EXE device drivers + + mov ax,(MS_X_OPEN * 256)+0 ; open file r/o + mov dx,offset dev_name + int DOS_INT + jc device_error + mov bx,ax ; now find out how big the file is + mov ax,(MS_X_LSEEK * 256)+2 + xor cx,cx + xor dx,dx ; by seeking to zero bytes from end + int DOS_INT + jc device_error + + xchg ax,cx ; save lo byte of length + + mov ah,MS_X_CLOSE ; close this file + int DOS_INT + jc device_error + + mov ax,cx ; DX:AX file length + or cx,dx ; do we have a zero length file + jz device_error ; if so stop now + + mov cl,4 + shr ax,cl ; convert file size to para + mov cl,12 + shl dx,cl ; ignore > 1 MByte portion + or dx,ax ; dx = file size in para + inc dx ; one for rounding error + + add dx,mem_current ; top of area needed for the load + cmp dx,mem_max ; will file fit (really HIDEVICE check) + jb func_device10 ; no, stop now + ret + +device_error: + mov error_level,ax ; save error code + mov al,0 + mov si,offset dev_name + mov dx,offset bad_filename + jmp config_error + +func_device10: + mov ax,(MS_X_EXEC * 256)+3 ; Use the Load Overlay function to + mov bx,offset dev_epb ; Read in and Relocate the Device + mov dx,offset dev_name ; driver + int DOS_INT ; + jc device_error + +; mov dosVersion,ax ; set version number + + push es + mov ax,mem_current ; Get Current Memory Base + push ax + inc ax ; skip the header + xor di,di ; Address of the first device header + mov es,ax ; in the device chain + +if ADDDRV + test es:DH_ATTRIB[di],DA_CHARDEV + jnz f_dev30 ;Character device driver ? + +; Can't install block device drivers so output error message and exit. + pop es + pop es + + xor al,al + mov si,offset dev_name + mov dx,offset err_block_device + jmp config_error + +f_dev30: +endif + + call PreloadFixup ; fiddle things for preload +if DOS5 + call ProtmanFixup ; fiddle int 12 memory for PROTMAN$ +endif + call device_init ; initialise the device drivers +if DOS5 + call ProtmanCleanup ; restore int 12 memory after PROTMAN$ +endif + mov error_level,ax ; save error code + pop es ; by old EMM386.SYS + mov ax,mem_current + mov es:DMD_LEN,ax ; save memory field + mov ax,es + inc ax + sub es:DMD_LEN,ax + pop es + call PreloadCleanup ; cleanup after ourselves + ret + + +BuildHeader: +;----------- +; On Entry: +; ES:0 -> header +; On Exit: +; None +; + xor di,di + mov al,'D' + stosb ; ID_FIELD + mov ax,es + inc ax + stosw ; OWNER_FIELD + xor ax,ax + stosb ! stosw ! stosw ; zero rest up to name + ret + + +FindName: +;-------- +; On Entry: +; DS:SI -> pathname of file +; On Exit: +; DS:SI -> final leaf name of file +; CX = length of leaf name +; + mov cx,si ; remember start of leaf +FindName10: + lodsb + cmp al,' ' ; end of the name ? + jbe FindName30 + call dbcs_lead ; is it a double byte pair ? + jne FindName20 + lodsb ; include the second byte + jmps FindName10 +FindName20: + cmp al,'\' ; is it a seperator ? + je FindName + cmp al,'/' + je FindName + jmps FindName10 +FindName30: + xchg cx,si ; SI -> start of leaf name + sub cx,si + dec cx ; CX = length + ret + + +SetName: +;------- +; On Entry: +; DS:SI -> leaf name to update +; ES = DMD to update +; On Exit: +; CX/SI preserved +; + push si + mov di,offset DMD_NAME ; point at the owners name field +SetName10: + lodsb + cmp al,' ' ; end of the name ? + jbe SetName30 + call dbcs_lead ; is it a double byte pair ? + jne SetName20 + stosb ; copy 1st byte of pair + cmp di,(offset DMD_NAME)+DMD_NAME_LEN + jae SetName30 ; don't overflow if name too long + movsb ; and the second + jmps SetName10 + +SetName20: + stosb + cmp al,'.' ; discard all following '.' + je SetName30 + cmp di,(offset DMD_NAME)+DMD_NAME_LEN + jb SetName10 ; don't overflow if name too long +SetName30: + dec di + xor ax,ax +SetName40: + stosb ; zero the '.' + cmp di,(offset DMD_NAME)+DMD_NAME_LEN + jb SetName40 ; zero the rest of the name +SetName50: + pop si + ret + +if DOS5 + +ROS_MEMORY equ .413h ; main memory on KB + +protmanName db 'PROTMAN$' + +protmanAdjust dw 0 + +ProtmanFixup: +;------------ +; On Entry: +; ES:DI -> device driver header +; On Exit: +; All regs preserved +; +; fiddle int 12 memory for PROTMAN$ +; + push cx + push si + push di + mov cs:protmanAdjust,0 ; assume it's not protman + mov si,offset protmanName + lea di,DH_NAME[di] ; ES:DI -> device driver name + mov cx,8/2 + repe cmpsw ; does the name match ? + jne ProtmanFixup10 + mov si,mem_max ; SI = top of memory in para + push ds +; xor cx,cx + mov ds,cx + mov cl,10-4 + shr si,cl ; convert para to KBytes + mov cx,ds:ROS_MEMORY ; CX = existing top of memory + sub cx,si ; CX = amount to hide + sub ds:ROS_MEMORY,cx ; hide it + pop ds + mov cs:protmanAdjust,cx ; remember how much we hid +ProtmanFixup10: + pop di + pop si + pop cx + ret + +ProtmanCleanup: +;-------------- +; On Entry: +; None +; On Exit: +; All regs preserved +; restore int 12 memory after PROTMAN$ +; + push ds + push ax + xor ax,ax + mov ds,ax + mov ax,cs:protmanAdjust ; normally zero.. + add ds:ROS_MEMORY,ax + pop ax + pop ds + ret + +endif + +; +; The syntax currently supported is "COUNTRY=NNN,[YYY],[FILENAME]" +; where:- +; NNN is a valid country code based on +; the International Dialing Code +; +; YYY is the default CODEPAGE +; +; FILENAME is the location and name of the COUNTRY.SYS +; file containing the extended country info. +; +; +if not ADDDRV +func_country: ; COUNTRY=nnn,[yyy],[filename] + call atoi ; ax = country code + jc f_ctry50 ; check for error + mov country_code,ax ; save the Country Code + call separator ; look for ',' + jc f_ctry20 + call atoi ; Get the Code Page + jc f_ctry10 ; invalid or non existent code page + mov code_page,ax ; save default Code Page +f_ctry10: + call separator ; look for ',' + jc f_ctry20 ; copy the supplied pathname + les bx,drdos_ptr ; Get the internal data area + mov di,es:DRDOS_COUNTRY_FILE[bx] + ; ES:DI -> pcmode buffer for name + call copy_file + push cs ; restore ES + pop es +f_ctry20: + call nls_hook ; install our lang support + mov bx, country_code ; bx = country code + mov ah, MS_S_COUNTRY + mov al, 0FFh ; 16 bit country code + mov dx, 0FFFFh ; set country code subfunction + int DOS_INT + jc f_ctry40 ; check for error + mov bx, code_page ; bx = code page + or bx,bx + jz f_ctry30 ; No Code Page Set leave as 437 + mov ax, MS_X_SETCP ; set codepage subfunction + int DOS_INT ; to set Current CodePage +f_ctry30: + jmp nls_unhook ; remove our lang support +; ret + +f_ctry40: + call nls_unhook ; remove our lang support +f_ctry50: +; Bad or non-existant number in command tail. Display error message. + xor si,si + mov dx, offset bad_country + jmp config_error + + + +func_shell: ; SHELL=filename + mov di,offset shell ; Copy the New Command Name + call copy_file ; into the BIOSINIT buffer + mov al,0 ! stosb ; Terminate the Environment Correctly + jc shell_error + + mov di,offset shell_cline+1 ; Now copy the default command + mov al,' ' ! stosb ; into place + mov cx,0 ; +f_sh10: + lodsb ! stosb ; Copy the next Character + inc cx ; Increment the count + cmp al,CR ; Was this the end of string Char + jnz f_sh10 ; No so Repeat + mov shell_cline,cl ; Save Command Length + ret + +shell_error: + mov al,CR + mov dx,offset bad_shell + jmp config_error + + +func_lastdrive: ; LASTDRIVE=d: + call atoi ; are we supplying a decimal number? + jc f_lastdrive10 + cmp al,32 ; is it in range ? + jbe f_lastdrive20 +lastdrv_error: + xor si,si ; Do not display Failing String + mov dx,offset bad_lastdrive ; and display an error message + jmp config_error + +f_lastdrive10: + lodsb ; Get the Option Character + call toupper ; and convert to Upper Case + sub al, 'A' ; al should be between 0..25 + jc lastdrv_error + cmp al, 'Z'-'A' + ja lastdrv_error + inc al ; al = number of drives in system +f_lastdrive20: + mov last_drv,al ; remember for later + ret + + + +func_break: ; BREAK=ON/OFF + call check_onoff ; Check for ON or OFF + mov dl,al ; Get value found + jnc set_break ; and check for error + + xor si,si ; Do not display Failing String + mov dx, offset bad_break ; Bad or non-existant ON/OFF string + jmp config_error ; in command tail. Display error message. + +set_break: + mov ah,MS_S_BREAK ; Set the Default Break Flag + mov al,01 ; Set Sub-Function + int DOS_INT ; Execute function and return + ret + + + +func_numlock: ; NUMLOCK=ON/OFF + call check_onoff ; Check for ON or OFF + jc numlock20 + push ds + xor bx,bx + mov ds,bx + mov bx,417h ; DS:BX -> keyboard control + or ds:byte ptr [bx],20h ; set numlock bit + test al,al ; was it numlock on ? + jnz numlock10 ; if not, better clear the bit + and ds:byte ptr [bx],not 20h +numlock10: + pop ds + mov ah,MS_C_STAT ; get console status + int DOS_INT ; (usually int 16 update NUMLOCK state) +numlock20: + ret + + + +func_hibuffers: ; HIBUFFERS=nn[,nn] + or buffersIn,BUFFERS_IN_HMA +; jmp func_buffers + +func_buffers: ; BUFFERS=nn[,nn] + call atoi ; AX = # of buffers + jc buffer_error ; check for error + cmp ax,MIN_NUM_BUFFS ; check if less than minimum + jae func_buf1 + mov ax,3 ; force to use minimum if less +func_buf1: + cmp ax,MAX_NUM_BUFFS ; check if more than maximum + jbe func_buf2 + mov ax,MAX_NUM_BUFFS ; force to use maximum if more +func_buf2: + mov init_buf,al ; update if we want more + call separator ; look for ',' + jc func_buf4 + call atoi ; Get read-ahead buffer size + jc buffer_error + cmp ax,MIN_READ_AHEAD + jb buffer_error + cmp ax,MAX_READ_AHEAD + ja buffer_error + mov num_read_ahead_buf,al +func_buf4: + ret + +buffer_error: + xor si,si ; Do not display Failing String + mov dx, offset bad_buffers + jmp config_error + + +func_files: ; FILES=nn + call atoi ; AX = # of files + jc files_error ; check for error + cmp ax,MIN_NUM_FILES ; check if less than minimum + jae func_fil1 + mov ax,MIN_NUM_FILES ; force to use minimum if less +func_fil1: + cmp ax,MAX_NUM_FILES ; check if more than maximum + jbe func_fil2 + mov ax,MAX_NUM_FILES ; force to use maximum if more +func_fil2: + mov num_files,ax ; update the number required + ret + +files_error: + xor si,si ; Do not display Failing String + mov dx, offset bad_files + jmp config_error + + + +func_fcbs: ; FCBS=nn + call atoi ; AX = # of files + jc fcbs_error ; check for error + cmp ax,MIN_NUM_FCBS ; check if less than minimum + jae func_fcb1 + mov ax,MIN_NUM_FCBS ; force to use minimum if less +func_fcb1: + cmp ax,MAX_NUM_FCBS ; check if more than maximum + jbe func_fcb2 + mov ax,MAX_NUM_FCBS ; force to use maximum if more +func_fcb2: + mov num_fcbs,ax ; update number of FCB's + ret + +fcbs_error: + xor si,si ; Do not display Failing String + mov dx, offset bad_fcbs + jmp config_error +endif ;not ADDDRV + + + +func_common: ; [COMMON] +func_remark: ; REM Comment field + ret + +func_switches: ; SWITCHES=... + ; /N = disable F5/F8 feature + ; /W = zap wina20.386 name + ; /K = disable enhanced keyboard support + ; /F = skip statup delay + + call whitespace ; skip all spaces + lodsw ; get '/x' + cmp al,CR ; check for end-of-line + je func_switches10 + cmp ah,CR ; check for end-of-line + je func_switches10 + cmp ax,'N/' + jne func_switches + mov boot_options,0 ; disable boot options +func_switches10: + ret + +func_stacks: ; STACKS=number,size +;----------- + call atoi ; ax = number of stacks + jc func_stacks20 ; check for error + test ax,ax ; special case ? (disabled) + jz func_stacks10 + cmp ax,MIN_NUM_STACKS ; range check for a sensible value + jb func_stacks20 + cmp ax,MAX_NUM_STACKS + ja func_stacks20 +func_stacks10: + mov num_stacks,ax + call separator ; look for ',' + jc func_stacks20 + call atoi ; get size of a stack frame + jc func_stacks20 + cmp ax,MIN_SIZE_STACK ; range check it + jb func_stacks20 + cmp ax,MAX_SIZE_STACK + ja func_stacks20 + mov stack_size,ax +func_stacks20: + ret + + +if not ADDDRV +func_deblock: ; DEBLOCK=xxxx +;------------ + call atohex ; read hex number into DX:AX + jc func_deblock10 + test dx,dx + jnz func_deblock10 + mov DeblockSetByUser,TRUE ; the user has supplied a setting + push ds + mov ds,bios_seg + mov DeblockSeg,ax ; save deblocking segment + pop ds +func_deblock10: + ret + +func_fastopen: ; FASTOPEN=nn + call atoi ; AX = # of files to cache + jc fopen_error ; check for error + test ax,ax ; disable fast open? + jz func_fopen2 ; yes, allow to set to 0000 + cmp ax,MIN_NUM_FOPEN ; check if less than minimum + jae func_fopen1 + mov ax,MIN_NUM_FOPEN ; force to use minimum if less +func_fopen1: + cmp ax,MAX_NUM_FOPEN ; check if more than maximum + jbe func_fopen2 + mov ax,MAX_NUM_FOPEN ; force to use maximum if more +func_fopen2: + mov num_fopen,ax ; update if we want more +func_fopen3: + ret + +fopen_error: + xor si,si ; Do not display Failing String + mov dx, offset bad_fopen + jmp config_error + + +func_drivparm: ; DRIVPARM = /d:nn [/c] [/f:ff] [h:hh] [/n] [/s:ss] [/t:tt] +;------------- +; This function specifies the drive parameters for a device +; and overrides the defaults assumed by the device driver. + + mov drivp_drv,0FFh ; invalid drive + call get_switch ; get next switch + cmp al,'d' ; first option must be /d:dd + jne drivparm_error + call get_number ; get numeric parameter + mov drivp_drv,al + mov drivp_chg,FALSE + mov drivp_prm,FALSE + mov drivp_trk,80 ; assume 80 tracks + + mov bl,drivp_drv ; get drive to set up + cmp bl,'Z'-'A' + ja drivparm_error + inc bl + mov ioctl_pb,0 ; return defaults + mov ax,440Dh ; generic IOCTL + mov cx,0860h ; get device parameters + mov dx,offset ioctl_func + int DOS_INT + jc drivparm_error ; skip if we can't get parameters + + mov drivp_ff,2 ; assume 720K 3.5" drive + call set_form_factor ; set defaults for form factor + + call get_switch ; get next switch + cmp al,'c' ; is it /c (change line available) + jne drivparm1 + mov drivp_chg,TRUE ; disk change line available + call get_switch ; get next switch +drivparm1: + cmp al,'f' ; form factor specification? + jne drivparm2 + call get_number ; get numeric parameter + mov drivp_ff,al ; set form factor + call set_form_factor ; set defaults for form factor + jmps drivparm_loop ; get more parameters + +drivparm_error: + xor si,si + mov dx,offset bad_drivparm + jmp config_error + +drivparm_loop: + call get_switch ; get next switch +drivparm2: + cmp al,'h' ; specify number of heads + jne drivparm3 + call get_number ; get numeric parameter + cmp ax,99 + ja drivparm_error + mov drivp_heads,ax ; set # of heads + jmps drivparm_loop + +drivparm3: + cmp al,'n' + jne drivparm4 + mov drivp_prm,TRUE ; non-removable media + jmps drivparm_loop + +drivparm4: + cmp al,'s' + jne drivparm5 + call get_number ; get numeric parameter + cmp ax,63 ; range check sector per track + ja drivparm_error + mov drivp_spt,ax ; set # of sectors/track + jmps drivparm_loop + +drivparm5: + cmp al,'t' + jne drivparm_error + call get_number ; get numeric parameter + cmp ax,999 + ja drivparm_error + mov drivp_trk,ax ; set # of sectors/track + jmps drivparm_loop + +drivparm_done: ; now set drive parameters + mov bl,drivp_drv + cmp bl,'Z'-'A' + ja drivparm_error + + mov ioctl_func,0000$0100b ; normal track layout assumed, + ; set device BPB for drive + mov al,drivp_ff ; get form factor + mov ioctl_type,al + + sub ax,ax ; assume removable, no disk change + cmp drivp_prm,FALSE + je drivp_d1 + or ax,1 ; drive is permanent media +drivp_d1: + cmp drivp_chg,FALSE + je drivp_d2 + or ax,2 ; drive supports disk change line +drivp_d2: + mov ioctl_attrib,ax ; set drive attributes + + mov ax,drivp_trk ; set # of cylinders + mov ioctl_tracks,ax + + mov ioctl_mtype,0 ; assume standard type + + mov ax,drivp_spt ; get sectors/track + mov di,offset ioctl_layout + push ds ! pop es ; ES:DI -> layout table + stosw ; set # of sectors + xchg ax,cx ; CX = # of sectors + mov ax,1 ; start with sector 1 +drivp_d3: + stosw ; set next sector # + inc ax ; move to next sector + loop drivp_d3 ; repeat for all sectors + + mov ax,drivp_heads + mul drivp_spt + mov dx,drivp_trk + mul dx ; AX/DX = # of sectors/disk + mov di,offset ioctl_bpb + mov 8[di],ax ; set sectors per disk + test dx,dx + jz drivp_d4 + mov word ptr 8[di],0 ; indicate large partition + mov 21[di],ax ; set disk size in sectors + mov 23[di],dx +drivp_d4: + mov bl,drivp_drv + inc bl + mov ax,440Dh + mov cx,0840h ; set drive parameters + mov dx,offset ioctl_func + int DOS_INT ; tell the BIOS, ignore errors + + ret + + +get_switch: ; get next command line switch + call whitespace ; skip all spaces & tabs + lodsb ; get next character + pop dx ; get return address + cmp al,'/' ; did we get a switch? + je get_swt9 ; yes, return the character + jmp drivparm_done +get_swt9: + lodsb + or al,('a' xor 'A') ; return upper-cased character + jmp dx + + +get_number: +; entry: SI -> next character (must be ':') + + lodsb ; get next character + cmp al,':' ; must be colon + jne get_num_err ; return error if not + call atoi ; get numeric value + jc get_num_err ; must be number + ret ; AX = number + +get_num_err: + pop dx + jmp drivparm_error ; reject this command + + +set_form_factor: + mov bl,drivp_ff + cmp bl,7 + ja set_form9 + mov bh,0 + shl bx,1 + push si ! push es + mov si,ff_table[bx] ; SI -> default media BPB + push ds ! pop es + mov di,offset ioctl_bpb ; ES:DI -> local BPB + mov cx,21 ; copy initialized portion + rep movsb + pop es ! pop si + ret + +set_form9: + jmp drivparm_error + + +; +; This function modifies the History buffer support provided by +; DR DOS the defaults are History OFF, 512 byte buffers, +; Insert ON, Search OFF, Matching OFF. +; +func_history: ; HISTORY = ON|OFF[,NNNN[,ON|OFF[,ON|OFF[,ON|OFF]]]] +;------------ + mov history_flg,0 ; start with it all off + + call check_onoff ; Check for ON|OFF Switch + jc f_hist_err + test al,al ! jz f_hist_exit ; if OFF forget the rest + or history_flg,RLF_ENHANCED+RLF_INS + + call separator ; look for ',' + jc f_hist_exit ; Buffer Size not Specified + call atoi ; Get the Buffer Size + jc f_hist_err ; Invalid on no existant size + cmp ax,128 ! jb f_hist_err ; Buffer Size to Small + cmp ax,4096 ! ja f_hist_err ; Buffer Size to Large + mov history_size,ax ; Save History Buffer Size + + call separator ; look for ',' + jc f_hist_exit ; Insert mode not Specified + call check_onoff ; Check for ON|OFF Switch + jc f_hist_err + test al,al ! jnz func_hist10 + and history_flg,not RLF_INS ; Insert state OFF +func_hist10: + call separator ; look for ',' + jc f_hist_exit ; Search mode not Specified + call check_onoff ; Check for ON|OFF Switch + jc f_hist_err + test al,al ! jz func_hist20 + or history_flg,RLF_SEARCH ; Search state ON +func_hist20: + call separator ; look for ',' + jc f_hist_exit ; Match mode not Specified + call check_onoff ; Check for ON|OFF Switch + jc f_hist_err + test al,al ! jz func_hist30 + or history_flg,RLF_MATCH ; Match state ON +func_hist30: + +f_hist_exit: + ret + +f_hist_err: + xor si,si ; Do not display Failing String + mov dx, offset bad_history ; Bad or non-existant ON/OFF string + jmp config_error ; in command tail. Display error message. + + +; +; HIINSTALL filename [Command Line Parameters] +; +; As INSTALL, but uses high memory if possible +; +func_hiinstall: + + mov ax,5802h + int DOS_INT ; get upper memory link + cbw + push ax ; save upper memory link + + mov ax,5800h + int DOS_INT ; get alloc strategy + push ax ; save alloc strategy + + mov ax,5803h + mov bx,1 ; set upper memory link + int DOS_INT ; to 1 + + mov ax,5801h + mov bx,80h ; set alloc strategy to lowest-upper + int DOS_INT ; if available + + call func_install ; try and install it + + mov ax,5801h + pop bx ; set alloc strategy + int DOS_INT ; to original value + + mov ax,5803h + pop bx ; set upper memory link + int DOS_INT ; to original value + + ret + + + +; +; INSTALL filename [Command Line Parameters] +; +; INSTALL will load and execute "FILENAME" with the optional command +; line parameters and continue processing the DCONFIG.SYS file when +; the application terminates. +; +; Entry +; ds:si -> first character of CR terminated filename and option string. +; Exit +; none +; +; WARNING - +; This code make certain assumptions about memory layout. +; If memory gets fragmented then it all starts falling apart. +; +func_install: +;------------ + push ds ! push es +; +; Shrink the previously allocated memory block to MEM_CURRENT +; in preparation of the INSTALL EXEC function. +; + mov es,mem_current_base ; ES: Base Allocated Memory + mov bx,mem_current ; Get the currently allocated memory + sub bx,mem_current_base ; and subtract mem_current_base to + mov ah,MS_M_FREE ; give the number of paragraphs used + jz func_i10 ; if none, free it all up + mov ah,MS_M_SETBLOCK ; else modify block accordingly +func_i10: + int DOS_INT + +; Now to protect the CONFIG code in high memory + mov ah,MS_M_ALLOC ; we now try to find base of TPA + mov bx,0ffffh ; ASSUME it is the biggest bit + int 21h ; of free memory about + mov ah,MS_M_ALLOC ; give it to me please + int 21h ; ax:0 -> exec memory + push bx ; we have allocated BX para's + mov es,ax ; ES -> exec memory + mov bx,init_dseg ; we want to protect BX:0 and above + dec bx ; allow for DMD + sub bx,ax ; we can spare this many paras + mov ah,MS_M_SETBLOCK ; for the exec so grow the + int 21h ; block accordingly + pop ax ; AX = total, BX = amount for install + + sub ax,bx ; AX = amount we just freed + dec ax ; allow for DMD + xchg ax,bx ; BX = freed portion (the Init code) + mov ah,MS_M_ALLOC ; ASSUME an allocation of this size + int 21h ; will contain SYSDAT/CONFIG + push ax ; save seg so we can free mem later + + mov ah, MS_M_FREE ; now free up the bit we prepared + int 21h ; earlier so exec has something + push ds ! pop es ; to work in + + mov di,offset dev_name ; Copy the filename into a local + call copy_file ; buffer + + ; Calculate the command line length + mov di,si ; by scanning the command line for + mov al,CR ; the terminating CR + mov cx,128 + repnz scasb + dec di + mov ax,di + sub ax,si + dec si ; Point to the byte before the + mov byte ptr [si],al ; command line string and update + ; the count + + mov ax,offset envstart ; env buffer is para aligned + mov cl,4 + shr ax,cl ; convert offset to paras + mov cx,ds + add ax,cx ; segment of env variables + mov exec_envseg,ax + mov exec_lineoff,si + mov exec_lineseg,ds + mov exec_fcb1off,0FFFEh ; Force PCMODE to generate + mov exec_fcb2off,0FFFEh ; correct FCB References + + mov system_ss,ss + mov system_sp,sp + + mov dx,offset dev_name ; Get ASCIIZ Command + mov bx,offset exec_envseg ; and Parameter Block Offset + mov ax,4B00h ; Load and Execute Program with Handle + int DOS_INT ; EXEC the application + + cli ; Swap back to the original stack + mov ss,cs:system_ss ; again with interrupts disabled + mov sp,cs:system_sp + sti + + mov ah,MS_X_WAIT ; if all went well return the + jnc func_i20 ; termination code + mov ah,MS_F_ERROR ; if we had an error from EXEC + xor bx,bx ; get extended error +func_i20: + int DOS_INT ; retrieve error value + mov cs:error_level,ax ; and save for testing + + pop es ; recover the seg we protected + mov ah, MS_M_FREE ; so we can free that memory up + int 21h + + mov ah,MS_M_ALLOC ; try and allocate as much as possible + mov bx, 0FFFFh ; ASSUME this will cover CONFIG + int 21h ; bx = No. of paras available + mov ah, MS_M_ALLOC ; give me bx paras please + int 21h ; ax:0 -> my memory + + pop es ! pop ds + mov mem_current_base,ax ; save memory base + mov mem_current,ax ; for future allocations + ret + + + +func_hidos: ; HIDOS ON/OFF + call check_onoff ; Check for ON or OFF + jc f_hidos10 ; Return on error + mov hidos,al ; update hidos flag +f_hidos10: + ret + + +func_dos: ; DOS=HIGH - relocate BIOS/BDOS/Buffer etc to FFFF + call separator ; Deblank Command + mov di,offset high_opt ; es:di -> "HIGH" + call compare ; do we have an "HIGH"? + jc func_dos10 + push si + call func_dos_high ; execute HIGH + pop si + jmps func_dos +func_dos10: + mov di,offset low_opt ; es:di -> "LOW" + call compare + jc func_dos20 + push si + call func_dos_low ; execute LOW + pop si + jmps func_dos +func_dos20: + mov di,offset umb_opt ; es:di -> "UMB" + call compare + jc func_dos30 + push si + call func_dos_umb ; execute UMB + pop si + jmps func_dos +func_dos30: + mov di,offset noumb_opt ; es:di -> "NOUMB" + call compare + jc func_dos40 + push si + call func_dos_noumb ; execute NOUMB + pop si + jmps func_dos +func_dos40: + ret + +func_dos_high: +;------------- +; Move DOS into the HMA and allocate buffers etc. high too. +; + mov dos_target_seg,0FFFFh + mov bios_target_seg,0FFFFh + mov hidos,TRUE ; update hidos flag to be ON + or buffersIn,BUFFERS_IN_HMA; buffers at seg FFFF too + ret + +func_dos_low: +;------------ +; force all allocation to be low +; + mov dos_target_seg,0 + mov bios_target_seg,0 + mov hidos,FALSE ; system allocation from low memory + mov buffersIn,0 ; buffers from low memory + ret + +func_dos_umb: +;------------ +; allocate Upper Memory Blocks and link them to the DMD chain +; + mov hidos,TRUE ; update hidos flag to be ON + call initialise_dmd_upper ; build initial upper memory DMD + jc func_dos_umb30 +func_dos_umb10: + call alloc_xms_umb ; allocate XMS upper memory + jc func_dos_umb20 + call add_dmd_upper ; add to upper memory DMD's + jmps func_dos_umb10 ; go around again +func_dos_umb20: + call remove_last_dmd ; get rid of useless last DMD +func_dos_umb30: + mov ax,(MS_M_STRATEGY*256)+3 + mov bx,1 ; link in upper memory region + int 21h + ret + +func_dos_noumb: +;-------------- +; Unlink Upper Memory blocks from the DMD chain +; + mov ax,(MS_M_STRATEGY*256)+3 + xor bx,bx ; unlink upper memory region + int 21h + ret + +alloc_xms_umb: +; On Entry: +; None +; On Exit: +; CY set is no upper memory available +; else +; BX = para base address +; DX = para size +; +; Try to allocate the largest possible block of XMS memory +; so we can link it to the upper memory chain +; + push es + mov ax,4300h ; check for XMS installation + int 2fh + cmp al,80h + jne alloc_xms10 + mov ax,4310h ; get address of XMS driver + int 2fh + mov word ptr xms_driver,bx + mov word ptr xms_driver+2,es + mov ah,10h ; allocate upper memory block + mov dx,0FFFFh ; DX set to find largest block + callf xms_driver + cmp dx,3 ; we need at least 3 para's + jb alloc_xms10 ; before we contruct a DMD + mov ah,10h ; now allocate largest block + callf xms_driver + cmp ax,1 ; did we succeed ? + je alloc_xms20 +alloc_xms10: + stc ; return CY set indicating failure +alloc_xms20: + pop es + ret + +xms_driver rd 0 + dw 0,0 + +initialise_dmd_upper: +; On Entry: +; None +; On Exit: +; CY set if chain already exists +; (BX/DX preserved) +; +; build initial upper memory DMD +; we rely on the fact the last para in memory is unused +; (but BIOSINIT makes sure that is true) +; + push es + push bx + push dx +if DOS5 + les bx,func52_ptr ; ES:BX -> list of lists + cmp es:F52_DMD_UPPER[bx],0FFFFh +else + les bx,drdos_ptr + cmp es:DRDOS_DMD_UPPER[bx],0 + les bx,funv52_ptr ; ES:BX -> list of lists +endif + stc ; assume error return required + jne initialise_dmd_upper30 ; bail out if chain already established + mov es,es:F52_DMDROOT ; ES -> 1st DMD +initialise_dmd_upper10: + cmp es:DMD_ID,IDZ ; end of DMD chain ? + je initialise_dmd_upper20 + cmp es:DMD_ID,IDM ; do we have any more DMD's ? + stc + jne initialise_dmd_upper30 ; woops, chain must be bad + mov ax,es ; better point to it + inc ax + add ax,es:DMD_LEN ; AX:0 -> next DMD + mov es,ax + jmps initialise_dmd_upper10 + +initialise_dmd_upper20: + mov ax,es + add ax,es:DMD_LEN ; AX:0 -> will be upper memory chain + cmp ax,0A000h ; if the DMD chain is already into + cmc ; upper memory, lets make sure we + jb initialise_dmd_upper30 ; stop before we fall apart + mov es:DMD_ID,IDM ; no longer the last entry + dec es:DMD_LEN ; shorten last DMD to make room + mov es,ax ; point to new DMD + mov es:DMD_ID,IDZ ; there is only one entry in the chain + mov es:DMD_PSP,8 ; its' owned by "system" + xchg ax,cx ; CX = DMD + mov ax,0FFFFh + sub ax,cx ; it's this big + mov es:DMD_LEN,ax +if DOS5 + les bx,func52_ptr + mov es:F52_DMD_UPPER[bx],cx +else + les bx,drdos_ptr + mov es:DRDOS_DMD_UPPER[bx],cx +endif + clc +initialise_dmd_upper30: + pop dx + pop bx + pop es + ret + + +remove_last_dmd: +; On Entry: +; None +; On Exit: +; None +; +; We have build an upper memory DMD chain, but we have left an extra +; DMD around covering the ROMs at the top of memory. Remove it if +; it's not required. +; + push es + les bx,func52_ptr ; ES:BX -> list of lists + mov es,es:F52_DMDROOT[bx] ; ES -> 1st DMD +remove_last_dmd10: + cmp es:DMD_ID,IDM ; do we have any more DMD's ? + jne remove_last_dmd20 ; bail out if we don't + mov ax,es ; remember previous DMD + mov dx,es + inc dx + add dx,es:DMD_LEN ; DX:0 -> next DMD + mov es,dx + cmp es:DMD_ID,IDZ ; end of DMD chain ? + jne remove_last_dmd10 + cmp es:DMD_PSP,8 ; is it owned by "system" ? + jne remove_last_dmd20 ; if so we can ditch this entry + mov es,ax ; ES = next to last DMD + mov es:DMD_ID,IDZ ; new end of chain + inc es:DMD_LEN ; include last para +if DOS5 + les bx,func52_ptr ; ES:BX -> list of lists + cmp dx,es:F52_DMD_UPPER[bx] + jne remove_last_dmd20 ; remove upper memory link if none left + mov es:F52_DMD_UPPER[bx],0FFFFh +else + les bx,drdos_ptr + cmp dx,es:DRDOS_DMD_UPPER[bx] + jne remove_last_dmd20 ; remove upper memory link if none left + mov es:DRDOS_DMD_UPPER[bx],0 +endif +remove_last_dmd20: + pop es + ret + + +add_dmd_upper: +; On Entry: +; BX = base address of DMD +; DX = size of DMD +; On Exit: +; None +; +; Add this block into the upper memory chain. +; To do this we find the DMD containing the block and link it into place +; + push es + push bx ; save base address + les bx,func52_ptr ; ES:BX -> list of lists + mov ax,es:F52_DMDROOT[bx] ; AX -> 1st DMD + pop bx ; 1st DMD is always below XMS + cmp ax,bx ; memory, so bomb out if not + jae add_dmd_upper40 ; as our DMD's must be corrupt +add_dmd_upper10: + mov es,ax + add ax,es:DMD_LEN ; AX:0 -> end of this block + cmp ax,bx ; is the next block above us ? + ja add_dmd_upper20 ; if not try the next block + inc ax ; AX:0 -> next DMD + cmp es:DMD_ID,IDM ; do we have any more DMD's ? + je add_dmd_upper10 ; we should have...... + jmps add_dmd_upper40 ; stop, DMD's are screwed up + +add_dmd_upper20: +; We have found the block we wish to insert a new free block into + cmp es:DMD_PSP,8 ; it must be owned by "system" + jne add_dmd_upper40 +; Shorten existing DMD to point to new block + mov ax,bx ; work out how far to new DMD + mov cx,es + sub ax,cx ; it's this many para's + dec ax ; forget the header + xchg ax,es:DMD_LEN ; set new length +; now we need to work out how much is left above the new DMD + sub ax,dx ; subtract length of new block + sub ax,es:DMD_LEN ; subtract the portion below +; Create DMD covering new block + mov cl,IDM ; create a new entry + xchg cl,es:DMD_ID ; CL = existing ID (M/Z) + mov es,bx ; ES -> base of new DMD + mov es:DMD_ID,IDM ; it's a link field + mov es:DMD_PSP,0 ; it's free + dec dx ; forget the header + add bx,dx ; last para is here + dec dx ; forget the next link + mov es:DMD_LEN,dx ; it's this long +; Build a new DMD at the top if the new block for anything above it + mov es,bx + mov es:DMD_ID,cl ; inherit the ID field + mov es:DMD_LEN,ax ; and it's this long + test ax,ax ; if zero length then + jz add_dmd_upper30 ; it's free + mov ax,8 ; else it's system +add_dmd_upper30: + mov es:DMD_PSP,ax ; set owner +add_dmd_upper40: + pop es + ret + + + + +func_set: ; SET envar=string + call whitespace ; deblank the command + mov di,offset envstart-1 ; point to our environment area +func_set5: + inc di + cmp es:word ptr [di],0 ; are we at the end yet + jne func_set5 + cmp di,offset envstart ; if nothing is there yet start + je func_set10 ; at the NUL, else skip the NUL + inc di ; to leave a seperator +func_set10: + lodsb ; get a character + cmp al,CR ; end of the line yet ? + je func_set20 + cmp di,offset envend ; have we room ? + jae func_set30 ; bail out if not + stosb ; save the character + jmps func_set10 +func_set20: + xor ax,ax ; terminate with NULL + stosb +func_set30: + ret +endif ;not ADDDRV + + +func_echo: ; ECHO "string" + call whitespace ; Scan off all white space + lodsb ; before the optional + cmp al,'=' ; '=' character. + je func_echo10 + dec si ; point at char +func_echo10: + mov dx,offset msg_dollar ; NUL error message + mov al,CR ; SI -> config line anyway + jmp config_error ; use error reporting routine + +func_yeschar: ; yeschar "string" + call whitespace ; Scan off all white space + lodsb ; before the optional + cmp al,'=' ; '=' character. + je func_yeschar10 + dec si ; point at char +func_yeschar10: + call whitespace + lodsb + mov yes_char,al ; update YES character + ret + +func_chain: ; CHAIN="filename" - use as new CONFIG.SYS + mov di,offset dev_name ; Copy the Device Filename into a + mov byte ptr [di],0 ; local buffer and zero terminate + call copy_file + jc func_chain10 ; ignore if any problems + mov ax,(MS_X_OPEN*256)+80h ; Try to open the file + mov dx,offset dev_name ; as a new config file + int DOS_INT ; if we can't ignore it + jc func_chain10 + mov bx,ax + mov ah,MS_X_CLOSE + int DOS_INT ; close the new file + mov si,offset dev_name + mov di,offset cfg_file + call copy_asciiz ; copy the new name + mov cfg_seeklo,0 ; start at begining of it + mov cfg_seekhi,0 + mov cfg_tail,0 ; force a read +func_chain10: + ret + +func_switch: ; SWITCH=option0, option1 +; GOSUB to appropriate label + call wait_for_key ; wait until a key is pressed + jc func_switch01 ; ignore if timeout + mov ah,MS_C_RAWIN + int DOS_INT ; read a char + cmp al,CR + jne func_switch02 +func_switch01: + mov al,default_switch_char ; use default character +func_switch02: + cmp al,'0' ; ignore if < '0' + jb func_switch + cmp al,'9' ; or > '9' + ja func_switch + sub al,'1' ; convert from ASCII + jns func_switch05 + mov al,10 ; make '0' into 10 +func_switch05: + cbw ; AX = lines to skip + xchg ax,cx ; make CX the loop count + jcxz func_switch30 + mov bx,si ; BX -> saved command line start +func_switch10: + push bx + push cx + mov di,offset dev_name ; copy and discard a label + call copy_file + pop cx + pop bx + jc func_switch40 ; ignore if any problems + push bx + push cx + call separator ; look for ',' + pop cx + pop bx + jc func_switch40 ; stop at end of line + loop func_switch10 +func_switch30: + jmp func_gosub ; execute a GOSUB + +func_switch40: + mov si,bx ; retract to start of line + jmps func_switch ; then back to sleep again + +func_gosub: ; GOSUB="label" +;---------- + pop ax ; get return address + mov bx,cfg_seeklo ; get existing offset + mov cx,cfg_seekhi ; in CONFIG file + sub bx,cfg_tail ; work out begining of buffer + sbb cx,0 + add bx,cfg_head ; add in current offset in buffer + adc cx,0 + push bx ; save as position to RETURN to + push cx + push ax ; save return address again + call func_goto ; try to GOTO label + jc func_return + ret ; RET, with old offset on stack + +func_return: ; RETURN [n] +;----------- + pop bx ; get return address + cmp sp,save_sp ; is anything on stack ? + jae func_return20 ; no, cannot RETURN + pop cfg_seekhi + pop cfg_seeklo ; restore position in file + mov cfg_tail,0 ; force a read + push bx + call atoi ; returning a value ? + pop bx + jnc func_return10 ; default to 0 + xor ax,ax +func_return10: + mov error_level,ax ; return result in error level +func_return20: + push bx ; save return address + ret ; and return to it + +func_goto: ; GOTO="label" +;--------- + mov di,offset dev_name ; Copy the label into a + mov byte ptr [di],0 ; local buffer and zero terminate + call copy_file + jc func_goto10 ; ignore if any problems + + mov cfg_seeklo,0 ; Seek to start of file + mov cfg_seekhi,0 + mov cfg_tail,0 ; force a re-read + +func_goto5: + call readline ; read in a line + jc func_goto10 ; stop if end of file + call strupr ; upper case possible label + mov bx,offset cfg_buffer + cmp ds:byte ptr [bx],':' ; is it a label ? + jne func_goto5 ; no, try next line + mov si,offset dev_name +func_goto6: + inc bx ; next char in possible label + lodsb ; get a character + test al,al ; end of label ? + je func_goto10 ; we have a match ! + cmp al,ds:byte ptr [bx] ; does it match + jne func_goto5 ; no, try next line + jmps func_goto6 ; yes, look at next character +func_goto10: + ret + +func_exit: +; Stop processing CONFIG.SYS + call readline ; read in a line + jnc func_exit ; until we can read no more.. + ret + +func_cls: +; CLEAR SCREEN +; This is PC specific - sorry + mov ah,15 ; get current + int 10h ; screen mode + mov ah,0 + int 10h ; reset it to clear screen + ret + +func_cpos: +; Set cursor position + call atoi ; AX = row + jnc func_cpos10 ; check for error + xor ax,ax ; default to top left + jmps func_cpos40 +func_cpos10: + push ax ; save row + call separator ; look for ',' + jc func_cpos20 ; no col specified + call atoi ; get col + jnc func_cpos30 +func_cpos20: + mov ax,1 ; default to left +func_cpos30: + pop dx + mov ah,dl ; AH = row, AL = col + sub ax,0101h ; compensate for being one based +func_cpos40: + xchg ax,dx ; DH = row, DL = col + xor bx,bx ; page zero + mov ah,2 ; set cursor position + int 10h ; Eeeek!! call the ROS + ret + +func_timeout: +; set TIMEOUT for keyboard input + call atoi ; AX = # timeout count + jnc func_timeout10 ; check for error + xor ax,ax ; bad values mean no timeout +func_timeout10: + mov keyb_timeout,ax ; save timeout count + call separator ; look for ',' + jc func_timeout20 + lodsb ; get default query char + cmp al,LF ! je func_timeout20 + cmp al,CR ! je func_timeout20 + mov default_query_char,al + call separator ; look for ',' + jc func_timeout20 + lodsb ; get default switch char + cmp al,CR ! je func_timeout20 + cmp al,LF ! je func_timeout20 + mov default_switch_char,al +func_timeout20: + ret + +func_error: +; ERROR='n' + call atoi ; AX = error count to match + jc func_error10 + mov error_level,ax ; set error level +func_error10: + ret + +func_onerror: +; ONERROR='n' optional command +; + call whitespace ; Scan off all white space + xor bx,bx ; index relationship = 1st item + xor dx,dx ; DX is bit to set +func_onerror10: + or bx,dx ; set reationship bit + lodsb ; now process a character + mov dx,2 + cmp al,'=' ; if '=' set bit 1 + je func_onerror10 + mov dx,4 + cmp al,'<' ; if '<' set bit 2 + je func_onerror10 + mov dx,8 + cmp al,'>' ; if '>' set bit 3 + je func_onerror10 + dec si ; point at char + push bx ; save relationship + call atoi ; AX = error count to match + pop bx ; recover relationship + jc func_onerror20 + cmp error_level,ax ; is it the error level we want ? + jmp func_onerror_tbl[bx] ; jump to handler +func_onerror20: + ret + +func_onerror_tbl: + dw func_onerror_eq ; . . . + dw func_onerror_eq ; . . = + dw func_onerror_lt ; . < . + dw func_onerror_le ; . < = + dw func_onerror_gt ; > . . + dw func_onerror_ge ; > . = + dw func_onerror_ne ; > < . + dw func_onerror_take ; > < = + +func_onerror_eq: + je func_onerror_take + ret + +func_onerror_ne: + jne func_onerror_take + ret + +func_onerror_lt: + jb func_onerror_take + ret + +func_onerror_le: + jbe func_onerror_take + ret + +func_onerror_gt: + ja func_onerror_take + ret + +func_onerror_ge: + jae func_onerror_take + ret + +func_onerror_take: + pop ax ; discard return address + xor ax,ax ; boot key options = none + jmp cfg_continue ; and execute this command + + + +func_query: +; ?optional command + cmp boot_options,F5KEY ; if F5 has been pressed then + je func_query50 ; do nothing + call whitespace ; discard any following whitespace + lodsb ; get a character + cmp al,'?' ; is it another '?', is so swallow it + je func_query ; and go round again + dec si ; it wasn't a '?', forget we looked + push si ; save current position + lodsb ; get next real char + xor cx,cx ; assume no prompt string + cmp al,'"' ; '?"user prompt"' - keep silent as + jne func_query10 ; user has supplied prompt + xchg ax,cx ; CL = " if user prompt + lodsb +func_query10: + cmp al,cl ; is this the user prompt char ? + je func_query20 ; then stop now + xchg ax,dx ; DL= character + mov ah,MS_C_WRITE + int DOS_INT ; output the character + lodsb + cmp al,CR ; is it the end of the line ? + jne func_query10 ; no, do another character + mov ah,MS_C_WRITESTR ; Output msg of form " (Y/N) ? " + mov dx,offset confirm_msg1 + int DOS_INT ; do " (" + mov ah,MS_C_WRITE + mov dl,yes_char + int DOS_INT ; do "Y" + mov dl,'/' + int DOS_INT ; do "/" + mov dl,no_char + int DOS_INT ; do "N" + mov ah,MS_C_WRITESTR + mov dx,offset confirm_msg2 + int DOS_INT ; do ") ? " +func_query20: + jcxz func_query30 ; if no user supplied prompt + pop ax ; don't discard original starting + push si ; position +func_query30: + call wait_for_key ; wait until a key is pressed + mov al,default_query_char ; if we timeout default + jc func_query40 + mov ah,MS_C_RAWIN + int DOS_INT ; read a char + test al,al ; is it a function key ? + jnz func_query40 + mov ah,MS_C_RAWIN + int DOS_INT ; throw away function keys + jmps func_query30 +func_query40: + push ax ; save response + mov ah,MS_C_WRITE + mov dl,al + int DOS_INT ; echo the char + mov ah,MS_C_WRITESTR + mov dx,offset confirm_msg3 + int DOS_INT ; now do CR/LF to tidy up + pop ax + call toupper ; make response upper case + pop si ; recover starting position + cmp al,yes_char + jne func_query50 + pop ax ; Discard Return Address + xor ax,ax ; boot key options = none + jmp cfg_continue ; Execute the command +func_query50: + ret ; Return without Executing Command + + + +func_getkey: ; GETKEY + call wait_for_key ; wait until a key is pressed + mov ax,CONFIG_ERRLVL ; assume we have timed out + jc func_getkey10 ; ignore if timeout + mov ah,MS_C_RAWIN + int DOS_INT ; read a char + xor ah,ah ; convert to word +func_getkey10: + mov error_level,ax + ret + + +; CONFIG_ERROR is the global error handler for the CONFIG.SYS +; commands. It is called with SI pointing to the CR/LF terminated string +; that caused the error and with DX pointing to an "informative" error +; message. +; +; On Entry:- AL Terminating Character +; DX Offset of Error Message +; SI 0000 No Message to display +; Offset of AL terminated string +; +config_error: + +if ADDDRV + mov error_flag,1 +endif + + push ax + mov ah,MS_C_WRITESTR ; Print the Error Message + int DOS_INT ; passed in DX + pop ax + + mov ah,al ; AH = terminating character + test si,si ; display the failing string ? + jz cfg_e20 ; YES then scan for terminator +cfg_e10: + lodsb ; get char to display + cmp al,ah ; have we reached the terminator ? + je cfg_e20 + xchg ax,dx ; DL = character to display + mov ah,MS_C_WRITE ; print a character at a time + int DOS_INT + xchg ax,dx ; terminator back in AH + jmps cfg_e10 +cfg_e20: +;; jmp crlf ; Terminate with a CRLF + + Public crlf +crlf: + push dx + mov dx,offset msg_crlf ; Print a CR LF + mov ah,MS_C_WRITESTR + int DOS_INT + pop dx + ret + +; +; Scan the command table for a match with the first entry in the +; CR/LF terminated string passed in SI +scan: + call whitespace ; scan off all white space + push bx ; save the CONFIG Handle + mov bx,offset cfg_table - CFG_SIZE + +scan_10: + add bx,CFG_SIZE ; bx -> next entry in table + mov di,CFG_NAME[bx] ; es:di -> next entry name + test di,di ; end of table ? + stc ; assume so + jz scan_exit ; Yes Exit with the Carry Flag Set + push si ; Save the String Offset + call compare + pop ax ; Remove String Address + jnc scan_20 ; String Matched + xchg ax,si ; Restore the original String Address + jmps scan_10 ; and test the next entry + +scan_20: + and CFG_FLAGS[bx],not CF_QUERY + test CFG_FLAGS[bx],CF_LC ; should we upper case line ? + jnz scan_50 ; skip if not + xchg ax,si + call strupr ; upper case the command line + xchg ax,si +scan_30: + call whitespace ; Scan off all white space before and + lodsb ; after the option '=' character + cmp al,'?' ; are we querying things ? + jne scan_40 + or CFG_FLAGS[bx],CF_QUERY ; remember the query, now go and + jmps scan_30 ; remove any other whitespace +scan_40: + cmp al,'=' ; '=' character. + je scan_30 + dec si +scan_50: + mov di,bx ; Save the Table Entry + xor ax,ax ; and exit with the Carry Flag Reset +scan_exit: + pop bx + ret + +; Compare two strings in case insensitive manner +; On Entry: +; ds:si -> String 1 (upper/lower case, length determined by string 2) +; es:di -> String 2 (uppercase, null terminated) +; On Exit: +; Carry clear: strings are the same +; ds:si -> character immediately following end of string 1 +; es:di -> character immediately following end on string 2 +; +; Carry set: strings different +; ds:si -> As on entry +; es:di -> undefined +; +compare: +;------- + push bx + push si ; save starting position +compare10: + mov al,es:[di] ; al = next character + inc di + test al,al ; end of string 2 yet ? + jz compare40 ; yes, strings must be equal + call dbcs_lead ; DBCS lead byte? + jnz compare20 ; no + mov ah,al + lodsb ; is 1st byte of pair the same ? + cmp al,ah + jne compare30 + cmpsb ; is 2nd byte of pair equal ? + jne compare30 + jmps compare10 +compare20: + call toupper ; just uppercase this byte + xchg ax,bx ; BL = string2 character + lodsb ; al = next char in string 1 + call toupper ; (can't be KANJI if it matches) + cmp al,bl ; check the characters are + je compare10 ; identical stop the compare +compare30: + stc ; on a mismatch and set CY +compare40: + pop bx ; recover starting position + jnc compare50 + mov si,bx ; SI = original start +compare50: + pop bx + ret + + +separator: +;--------- +; On Entry: +; DS:SI -> string +; On Exit: +; DS:SI -> next option +; CY set if end of line +; +; Strips off all whitespace, and the optional ',' +; CY set at end of line + call whitespace ; deblank string and + lodsb ; check for ',' separator + cmp al,',' ; discarding if found + je separator10 + cmp al,CR ; end of the line ? + stc ; assume so + je separator10 + dec si ; something else, leave alone + clc ; not end of line +separator10: + ret + +separator20: + call whitespace ; strip of following spaces + clc ; not end of line + ret + + +strupr: +;------ +; Uppercase a null terminated string. +; Entry +; ds:si -> null terminated string +; Exit +; none (string is uppercased) +; Lost +; no registers changed + + + push si + push ax + +spr_loop: + mov al, [si] ; al = next byte from string + test al, al ; end of string? + jz spr_done ; yes - exit + +; cmp al,' ' ; BAP. End at first space +; je spr_done ; or comma or slash +; cmp al,',' ; so that parameters +; je spr_done ; are not uppercased +; cmp al,'/' ; Took out again cos it caused +; je spr_done ; problems with labels (I think). + + call dbcs_lead ; DBCS lead byte? + jnz spr_not_dbcs ; no + inc si ; yes - skip first and second bytes of + inc si ; pair as they cannot be uppercased + jmp spr_loop ; loop round +spr_not_dbcs: + + call toupper ; just uppercase this byte + mov [si], al ; return the result to the string + inc si + jmp spr_loop ; continue + +spr_done: + pop ax + pop si + ret + + +dbcs_lead: +;--------- +; Return true if given byte is the first of a double byte character. +; Entry +; al = byte to be tested +; Exit +; Z Flag = 1 - byte is a DBCS lead +; 0 - byte is not a DBCS lead +; Lost +; no registers changed + + + push ds + push si + push bx + push ax + +; First get a pointer to the double byte lead table in the COUNTRY info. + lds si, dbcs_tbl ; ds:si -> double byte table + inc si + inc si ; skip table length + +; Examine each entry in the table to see if it defines a range that includes +; the given character. + mov bl, al ; bl = byte to be tested +dbcs_loop: + lodsw ; al/ah = start/end of range + test ax, ax ; end of table? + jz dbcs_no ; yes - exit (not in table) + cmp al, bl ; start <= bl? + ja dbcs_loop ; no - try next range + cmp ah, bl ; bl <= end? + jb dbcs_loop ; no - try next range + + cmp al, al ; return with Z flag set + jmp dbcs_exit + +dbcs_no: + cmp al, 1 ; return with Z flag reset + +dbcs_exit: + pop ax + pop bx + pop si + pop ds + ret + + + +toupper: +;------- +; Return the uppercase equivilant of the given character. +; The uppercase function defined in the international info block is +; called for characters above 80h. +; Entry +; al = character to uppercase +; Exit +; al uppercased +; Lost +; no registers lost + + push bx + mov bh, ah + mov ah, 0 ; ax = character to be converted + cmp al, 'a' ; al < 'a'? + jb exit_toupper ; yes - done (char unchanged) + cmp al, 'z' ; al <= 'z'? + jbe a_z ; yes - do ASCII conversion + cmp al, 80h ; international char? + jb exit_toupper ; no - done (char unchanged) + +; ch >= 80h -- call international routine + callf dword ptr ctry_info+CI_CASEOFF + jmp exit_toupper + +a_z: +; 'a' <= ch <= 'z' -- convert to uppercase ASCII equivilant + and al, 0DFh + +exit_toupper: + mov ah, bh + pop bx + ret + + + + +; +; Scan the string DS:SI for ON or OFF return with the carry flag set +; on error or AL = 1 for ON and AL = 0 for OFF. +; +check_onoff: + call whitespace ; Deblank Command + push si + mov di,offset cmd_on ; es:di -> "ON" + call compare ; do we have an "ON"? + mov al,01 ; Assume ON found + jnc chk_onoff10 + + pop si ! push si ; Save String Location in Case of Error + mov di,offset cmd_off ; es:di -> "OFF" + call compare ; do we have an "OFF"? + mov al,00 + jnc chk_onoff10 + pop si ; No match so return original address + stc ; with the CARRY falg set. + ret + +chk_onoff10: + pop di ; Remove Old String address + ret ; and return to caller + +atohex: +;------ +; To convert a hex number in the form of an ASCII string to a 32 bit +; integer. +; +; On Entry: +; DS:SI -> ASCII hex number +; (the end of the number is taken as the first non-digit) +; On Exit: +; CY clear: +; DX:AX = converted number +; ds:si -> first non-digit +; +; CY set: +; Either the first character was not a digit +; or the number could not be represented in 32 bits +; ds:si -> point at which error occured +; ax undefined +; Lost +; no other register + + push bx + push cx + push di + call whitespace ; Deblank Line + mov di,si ; save string start offset + xor dx,dx + xor bx,bx ; number is formed in DX:BX + +atohex10: + lodsb ; AL = next char from string + call toupper ; upper case it + cmp al,'A' + jb atohex20 + cmp al,'F' + ja atohex20 + sub al,'A'-10 + jmps atohex30 +atohex20: + sub al, '0' + jc atohex40 ; stop if invalid character + cmp al, 9 + ja atohex40 +atohex30: + cbw ; AX = digit + test dh,0f0h ; will we overflow ? + jnz atohex_error + mov cl,4 + push bx ; save (top 4 bits) + shl bx,cl ; *16 + add bx,ax ; add in new digit + pop ax + rol ax,cl ; top 4 bits to bottom 4 bits + and ax,000Fh ; isolate them + shl dx,cl + add dx,ax ; add in new digit + jmp atohex10 + +atohex40: + dec si ; forget the char we stopped on + cmp si, di ; was there at least one digit? + ja atohex50 ; yes - exit with carry clear +atohex_error: + stc ; set error flag +atohex50: + xchg ax,bx ; AX = result + pop di + pop cx + pop bx + ret + +atoi: +;---- +; To convert a decimal number in the form of an ASCII string to a 16 bit +; integer. +; +; Entry +; ds:si -> ASCII decimal number +; (the end of the number is taken as the first non-digit) +; Exit +; Carry clear: +; ax = converted number +; ds:si -> first non-digit +; +; Carry set: +; Either the first character was not a digit +; or the number could not be represented in 16 bits +; ds:si -> point at which error occured +; ax undefined +; Lost +; no other register + + push bx ! push cx + push dx ! push di + call whitespace ; Deblank Line + mov di, si ; save string start offset + mov cx, 10 ; for multiply + xor ax, ax ; number is formed in ax + +atoi_loop: + mov bl, [si] ; bl = next char from string + sub bl, '0' + jc atoi_done + cmp bl, 9 + ja atoi_done + mov bh, 0 ; bx = next digit + + mul cx ; ax = 10 * ax + jc exit_atoi ; check for 16 bit overflow + add ax, bx ; ax = (10 * ax) + bx + jc exit_atoi + + inc si ; ds:si -> next char in string + jmp atoi_loop + +atoi_done: + cmp si, di ; was there at least one digit? + jne exit_atoi ; yes - exit with carry clear + stc ; no - set error flag + +exit_atoi: + pop di ! pop dx + pop cx ! pop bx + ret + +atol: +;---- +; To convert a decimal number in the form of an ASCII string to a 32 bit +; integer. +; +; Entry +; ds:si -> ASCII decimal number +; (the end of the number is taken as the first non-digit) +; Exit +; CY clear: +; DX:AX = converted number +; ds:si -> first non-digit +; +; CY set: +; Either the first character was not a digit +; or the number could not be represented in 32 bits +; ds:si -> point at which error occured +; ax undefined +; Lost +; no other register + + push bx + push cx + push di + call whitespace ; Deblank Line + mov di, si ; save string start offset + xor ax, ax ; number is formed in + cwd ; DX/AX + +atol10: + xor bx,bx ; use CX/BX for next digit + xor cx,cx + mov bl,[si] ; BL = next char from string + sub bl,'0' + jc atol20 + cmp bl, 9 ; validate digit + ja atol20 + add ax,ax + adc dx,dx ; * 2 + jc atol30 + add bx,ax ; * 2 + new digit + adc cx,dx + jc atol30 + add ax,ax + adc dx,dx ; * 4 + jc atol30 + add ax,ax + adc dx,dx ; * 8 + jc atol30 + add ax,bx ; * 10 + new digit + add dx,cx + jc atol30 + inc si ; ds:si -> next char in string + jmp atol10 + +atol20: + cmp si,di ; was there at least one digit? + jne atol30 ; yes - exit with carry clear + stc ; no - set error flag +atol30: + pop di + pop cx + pop bx + ret + +readline: +;-------- +; On Entry: +; None +; On Exit: +; DS:SI -> line in buffer +; CY set if we have a problem (eg at EOF) +; + mov cx,CFG_BUF_LEN-2 ; Read the next command line + mov di,offset cfg_buffer ; into the CFG_BUFFER + mov si,di ; Save the Destination String + ; address +read_l10: + call getchar ; al = next char from file + cmp al,CR ! jz read_l10 ; end of line ? + cmp al,LF ! jz read_l10 ; end of line ? + cmp al,EOF ! jne read_l20 ; end of file ? + stc ; indicate a problem + ret + +read_l20: + stosb ; put next char into the buffer + call getchar ; al = next char from file + + cmp al,EOF ! jz read_l30 ; end of file ? + cmp al,CR ! jz read_l30 ; end of line ? + cmp al,LF ! jz read_l30 ; end of line ? + loop read_l20 ; loop while space remains + +; If we fall through to this point the line is too long. Make it a comment. + mov di, si ; ds:di -> start of buffer + mov al, ';' + stosb ; place ';' at buffer start + mov cx, 1 ; get another one character + jmps read_l20 ; loop until all of this line consumed + +; At this point buffer contains a line of text from CCONFIG.SYS. +; Terminate it properly +read_l30: + mov al,CR ! stosb ; terminate line with CR + mov al,LF ! stosb ; and a LF + xor al,al ! stosb ; Reset the Carry Flag + ret + +getchar: + mov bx,cfg_head ; we are here in the buffer + cmp bx,cfg_tail ; are there any more characters ? + jae getchar10 ; no, read some in from disk + push ds + mov ds,init_dseg + mov al,CONFIG_BUF[bx] ; get a character from the buffer + pop ds + inc cfg_head ; inc the pointer + ret + +getchar10: +; we need to read some characters from disk into our buffer + push cx ! push dx ; Assume something will go wrong + mov cfg_tail,0 ; say nothing is in the buffer + + mov ax,(MS_X_OPEN*256)+80h ; Open the configuration file + mov dx,offset cfg_file + int DOS_INT + jc getchar40 ; failure, return EOF + + mov bx,ax + mov ax,(MS_X_LSEEK*256)+0 + mov dx,cfg_seeklo + mov cx,cfg_seekhi + int DOS_INT ; seek to current file position + jc getchar30 ; failure to seek, close and exit + + mov ah,MS_X_READ + mov cx,CONFIG_BUF_SIZE + push ds + mov ds,init_dseg + mov dx,offset CONFIG_BUF ; lets try and fill out buffer + int DOS_INT + pop ds + jc getchar30 + mov cfg_tail,ax + mov ax,(MS_X_LSEEK*256)+1 + xor dx,dx + xor cx,cx + int DOS_INT ; get current file position + mov cfg_seeklo,ax ; and save for possible + mov cfg_seekhi,dx ; future re-opens +getchar30: + mov ah,MS_X_CLOSE ; Close the CONFIG file + int DOS_INT +getchar40: + mov bx,cfg_tail ; now lets see if we filled the buffer + cmp bx,CONFIG_BUF_SIZE ; if not its EOF so mark it as such + je getchar50 + push ds + mov ds,init_dseg + mov CONFIG_BUF[bx],EOF ; add an EOF mark + pop ds ; in case there isn't one already + inc cfg_tail + inc cfg_seeklo + jnz getchar50 + inc cfg_seekhi +getchar50: + push ds + mov ds,init_dseg + mov al,CONFIG_BUF ; return 1st char from buffer + pop ds + mov cfg_head,1 ; remember we have returned char + pop dx ! pop cx + ret + + +; +; On a DEVICEHIGH we have encountered a line +; /L:r1[,s1][;r2[,s2]]... [/S] +; where r1 = load region, s1 = hex size in bytes, r2,s2 etc are further regions +; currently only r1/s1 are supported +; /S says the regions should m#be minimised + +parse_region: +;On Entry: +; DS:SI -> command line following '/L:' +; On Exit: +; DS:SI -> 1st non-parsed character +; CY set on error +; + call atoi ; get a region to load in + jc parse_region40 + mov himem_region,ax ; remember region to try + call whitespace ; scan off all white space + lodsb ! dec si ; now see is we have an optional size + cmp al,',' ; have we a ',' character ? + mov ax,0 ; assume minimum size not supplied + jne parse_region30 + inc si + call atol ; read number into DX:AX + cmp dx,15 ; is number too big ? + ja parse_region40 + mov cx,16 ; convert to para's + div cx + inc ax ; allow for round up + inc ax ; and for header + push ax ; save size of region +parse_region10: + mov di,offset slashs_opt ; do we have a "/S" to minimise + call compare ; the UMB's (ignore it if so) + jnc parse_region20 + call whitespace ; scan off all white space + lodsb ! dec si ; strip off other regions + cmp al,';' ; another region follows ';' + jne parse_region20 + inc si + call atoi ; eat the region number + jc parse_region20 + call whitespace ; scan off all white space + lodsb ! dec si + cmp al,',' ; is a size specified ? + jne parse_region10 ; no, check for another region + inc si + call atol ; eat the size + jnc parse_region10 +parse_region20: + pop ax +parse_region30: + clc ; we can proceed + ret + +parse_region40: + mov himem_size,0FFFFh ; 1 MByte wanted (ho, ho) + stc ; we had problems.. + ret + +; On a DEVICEHIGH we may encounter a line +; SIZE [=] s +; where s = size of region in hex bytes + +parse_size: +;On Entry: +; DS:SI -> command line following '/L:' +; On Exit: +; DS:SI -> 1st non-parsed character +; CY set on error +; + call whitespace ; Scan off all white space + lodsb ; before and after the optional + cmp al,'=' ; '=' character. + je parse_size + dec si + call atohex ; read hex number into DX:AX + jc parse_size10 + cmp dx,15 ; is number too big ? + ja parse_size20 ; just load low + mov cx,16 ; convert to para's + div cx + inc ax ; allow for round up + inc ax ; and for header + mov himem_size,ax ; remember size required +parse_size10: + clc + ret + +parse_size20: + mov himem_size,0FFFFh ; 1 MByte wanted (ho, ho) + stc + ret + + +; A size has not been suppleied with DEVICEHIGH, so guess-timate one +; based on file size + +size_file: +; On Entry: +; DS:SI -> filename +; On Exit: +; DS:SI preserved +; + push si + mov di,offset dev_name ; copy the device filename into a + mov byte ptr [di],0 ; local buffer and zero terminate + call copy_file + pop si + mov ax,(MS_X_OPEN * 256)+0 ; open file r/o + mov dx,offset dev_name + int DOS_INT + jnc size_file10 + mov ax,0FFFFh ; can't open file, force low to prevent + ret ; two sets of error messages + +size_file10: + xchg ax,bx ; handle in BX + mov ah,MS_X_READ + mov cx,EXE_LENGTH + mov dx,offset exeBuffer + int DOS_INT ; read in possible exe header + jc size_file20 + cmp ax,cx ; did we read all we wanted ? + jb size_file40 ; if not it can't be an EXE + cmp exeSignature,'ZM' ; check the signature + jne size_file40 ; if invalid can't be an EXE + mov ax,512 + mul exeSize ; DX/AX bytes in image + add ax,exeFinal + adc dx,0 + mov cx,16 + cmp dx,cx ; are we too big ? + jae size_file20 ; yes, force low + div cx ; AX = para's required + inc ax ; one for rounding error + jz size_file20 + add ax,exeMinpara ; add on extra para's required + jnc size_file30 +size_file20: + mov ax,0FFFFh ; problems, force a load low +size_file30: + push ax ; save para's required + mov ah,MS_X_CLOSE ; close this file + int DOS_INT + pop ax ; AX para's required + ret + +size_file40: + mov ax,(MS_X_LSEEK * 256)+2 + xor cx,cx ; now find out how big the file is + xor dx,dx ; by seeking to zero bytes from end + int DOS_INT + jc size_file20 + mov cx,16 + cmp dx,cx ; are we too big ? + jae size_file20 ; yes, force low + div cx ; AX = para's required + inc ax ; one for rounding error + jmps size_file30 + +himem_setup: +; On Entry: +; AX = minimum amount of upper memory required (in para's) +; On Exit: +; CY clear if able to satisfy request +; CY set on error (we then load low) +; +; try and find some hi memory +; we allocate the biggest available chunk of upper memory +; + push es + mov cx,ax ; CX = para's required + mov ax,mem_current_base + mov himem_current_base,ax ; save mem_current_base + mov ax,mem_current + mov himem_current,ax ; save mem_current + mov ax,mem_max + mov himem_max,ax ; save mem_max + mov ah,MS_M_ALLOC + mov bx,0FFFFh ; give me all memory (please) + int 21h ; bx = No. of paras available + cmp bx,cx ; do we have enough ? + jc himem_setup40 ; no, give up now + + cmp himem_region,0 ; is there a region specified ? + je himem_setup20 ; no, allocate largest block + +; Allocate the region specified by /L: + les bx,func52_ptr ; ES:BX -> list of lists + mov ax,es:F52_DMD_UPPER[bx] ; get upper memory link + cmp ax,0FFFFh ; make sure there is one + je himem_setup20 ; shouldn't happen.... + mov es,ax +himem_setup10: + cmp es:DMD_ID,'M' ; is there another block ? + stc ; if we run out of blocks then + jne himem_setup40 ; we load low + mov es,ax ; ES -> DMD + mov bx,es:DMD_LEN ; get length in para'a + inc ax + add ax,bx ; AX -> next DMD + cmp es:DMD_PSP,0 ; is it free ? + jne himem_setup10 ; no, try the next + dec himem_region ; found the right region yet ? + jnz himem_setup10 + cmp bx,cx ; do we have enough ? + jc himem_setup40 ; no, go low + mov ax,es ; ES -> DMD header to allocate + inc ax + mov es,ax ; ES -> data in block + mov ah, MS_M_SETBLOCK + int 21h ; "allocate" this block + mov ax,es + jnc himem_setup30 ; this can only fail if DMD chain + jmps himem_setup40 ; is corrupt... + +himem_setup20: +; allocate the largest block available for DEVICEHIGH + mov ah, MS_M_ALLOC + mov bx, 0FFFFh ; give me all memory (please) + int 21h ; bx = No. of paras available + mov ah, MS_M_ALLOC ; give me bx paras please + int 21h ; ax:0 -> my memory + jc himem_setup40 ; woops, what happened ? +himem_setup30: + mov mem_current_base,ax + mov mem_current,ax ; save base of himem area + mov mem_max,ax + add mem_max,bx ; top of himem area +himem_setup40: + pop es + ret + +himem_cleanup: +; clean up our high memory - this hook should free up any difference +; between himem_current and himem_max + mov ax,himem_max + mov mem_max,ax ; restore mem_max + mov ax,himem_current_base + xchg mem_current_base,ax ; restore mem_current_base + mov bx,himem_current + xchg mem_current,bx ; restore mem_current + push es + mov es,ax ; ES -> memory block + sub bx,ax ; has any memory been used ? + jz himem_cleanup10 + mov ah,MS_M_SETBLOCK ; try and shrink the block + int DOS_INT ; to the size we used + pop es +; clc ; return success + ret + +himem_cleanup10: + mov ah,MS_M_FREE ; free it all up + int DOS_INT + pop es + stc ; return an error + ret + +copy_asciiz: +;----------- + lodsb ; get a character + stosb ; copy it + test al,al ; is it the terminating NUL ? + jnz copy_asciiz ; do next char + ret + +wait_for_key: +;------------ +; On Entry: +; None +; On Exit: +; CY set if no key pressed within timeout +; + mov cx,keyb_timeout ; get timeout value + clc ; assume no timeout + jcxz wait_for_key30 +wait_for_key10: + push cx + mov ah,MS_T_GETTIME ; get current time + int DOS_INT ; so we can do timeout + mov bx,dx ; save secs in BH + pop cx +wait_for_key20: + mov ah,MS_C_STAT ; is a character ready ? + int DOS_INT ; if so process it + test al,al ; do we have a character ? + jnz wait_for_key30 + push cx + mov ah,MS_T_GETTIME ; get current time + int DOS_INT ; so we can do timeout + pop cx + cmp bh,dh ; have we timed out ? + je wait_for_key20 + loop wait_for_key10 ; another second gone by + stc ; we have timed out +wait_for_key30: + ret + +; +; COPY_FILE copies the next parameter from DS:SI into the buffer +; at ES:DI and terminates with a NULL character. The parameter is +; expected to be a FileName. DS:SI are returned pointing to the +; next parameter in the command. +; +copy_file: + call whitespace ; DeBlank the Command Line + mov cx,MAX_FILELEN ; Limit FileName Length + push si ; Save SI in case of error +copy_f10: + lodsb ; Copy upto the first Space or + cmp al,' ' ; Control Character + jbe copy_f20 + cmp al,',' ; stop at ',' too + je copy_f20 + cmp al,'/' ; Also stop scanning when a switch + je copy_f20 ; character is detected + stosb + loop copy_f10 + pop si ; Restore the original SI + mov ax,13 ; 13 = invalid data error + stc ; and return with an error + ret + +copy_f20: + pop ax ; Remove Original String address + dec si ; Point at the failing character + xor ax,ax + stosb ; Zero Terminate FileName + ret + + +INITDATA DSEG 'INITDATA' + +if ADDDRV + extrn err_no_command_file:byte + extrn err_block_device:byte +else + extrn shell:byte ; Default Command Processor + extrn shell_cline:byte ; Default Command Line +endif + extrn dev_epb:byte + extrn dev_count:byte + extrn rel_unit:word + + extrn dos_target_seg:word + extrn bios_target_seg:word + extrn mem_current_base:word ; Current Base Address + extrn mem_current:word ; Current Load Address + extrn mem_max:word ; Top of Available Memory + extrn mem_size:word ; Real top of Memory + + extrn init_dseg:word ; Current Init Data Segment + + +include initmsgs.def ; Include TFT Header File + + +; extrn bad_command:byte +; extrn bad_filename:byte + +if not ADDDRV +; extrn bad_shell:byte +; extrn bad_country:byte +; extrn bad_lastdrive:byte +; extrn bad_break:byte +; extrn bad_buffers:byte +; extrn bad_files:byte +; extrn bad_fcbs:byte +; extrn bad_fopen:byte +; extrn bad_drivparm:byte +; extrn bad_history:byte +endif + +; extrn yes_char:byte ; In BIOSMSGS.ASM +; extrn no_char:byte + + extrn dev_load_seg:word + extrn dev_reloc_seg:word + extrn dev_epb:byte + extrn dev_name:byte + extrn dev_name:byte + extrn dosVersion:word + extrn strategy_off:word + extrn strategy_seg:word + extrn interrupt_off:word + extrn interrupt_seg:word + extrn request_hdr:byte + extrn next_drv:byte + extrn strategy_seg:word + extrn strategy:dword + extrn interrupt:dword + extrn func52_ptr:dword + extrn strategy_seg:word + extrn condev_off:word + extrn condev_seg:word + extrn clkdev_off:word + extrn clkdev_seg:word + extrn num_blkdev:byte + extrn blkdev_table:byte + extrn last_drv:byte + extrn next_drv:byte + extrn max_secsize:word + extrn max_clsize:word + extrn country_code:word + extrn code_page:word + extrn drdos_ptr:dword + extrn init_buf:byte + extrn num_read_ahead_buf:byte + extrn buffersIn:byte + extrn num_files:word + extrn num_fcbs:word + extrn num_fopen:word + extrn history_flg:byte ; In INIT code + extrn history_size:word ; + extrn num_stacks:word + extrn stack_size:word + +if not ADDDRV + extrn hidos:byte + extrn bios_seg:word + extrn DeblockSetByUser:Byte + extrn DeblockSeg:word ; In BIOS data +endif + + extrn dbcs_tbl:dword + extrn ctry_info:byte + + + + Public cfg_file, cfg_file_end + +preload_entry rd 0 ; preload back door entry + dw 14h ; offset is pre-initialised to 14h +preload_seg rw 1 + +preload_ver dw 10 ; version to give DBLSPACE + + Public preload_drv +preload_drv db 0 ; number of preload drives +alt_drive db 0 ; preload checks alternative drive, + ; (only used loading from A:) + +; The preload_file is used as is to open a preload device +; It is also used to initialise a "DMD" name, and the code to do this +; currently finds the "\" and then copies the next 8 characters. +; This works with the current names - any new names may require modifications + +preload_file dw offset security_file ; initially '\SECURITY.BIN' +security_file db '\SECURITY.BIN',0 +stacker_file db 'C:\STACKER.BIN',0 +dblspace_file db 'C:\DBLSPACE.BIN',0 + +cfg_file db 'DCONFIG.SYS',0 ; Configuration File + rb 64 ; space for bigger CHAIN'd file +cfg_file_end rb 0 + +cfg_seeklo dw 0 ; offset we have reached in CONFIG file +cfg_seekhi dw 0 ; in case Richards CONFIG file > 64k + +cfg_head dw 0 ; offset we are at in CONFIG_BUF +cfg_tail dw 0 ; # bytes currently in CONFIG_BUF + +cfg_buffer rb CFG_BUF_LEN ; individual lines live here + +; +; EXEC parameter blocks for INSTALL function +; +exec_envseg rw 1 ; Environment Segment +exec_lineoff rw 1 ; Command Line Offset +exec_lineseg rw 1 ; Command Line Segment +exec_fcb1off rw 1 ; Offset of FCB 1 (5Ch) +exec_fcb1seg rw 1 ; Segment of FCB 1 (5Ch) +exec_fcb2off rw 1 ; Offset of FCB 2 (6Ch) +exec_fcb2seg rw 1 ; Segment of FCB 2 (6Ch) + rd 2 ; Initial SS:SP & CS:IP + +system_sp rw 1 +system_ss rw 1 + +ioctl_pb rb 0 +ioctl_func rb 1 ; special functions +ioctl_type rb 1 ; device type (form factor) +ioctl_attrib rw 1 ; device attributes +ioctl_tracks rw 1 ; # of tracks +ioctl_mtype rb 1 ; media type, usually zero +ioctl_bpb rb 31 ; default BPB for this type of disk +ioctl_layout rw 1+64 ; support 64 sectors/track max. + +drivp_drv rb 1 ; drive 0-15 +drivp_chg rb 1 ; change line support +drivp_prm rb 1 ; permanent media flag +drivp_ff rb 1 ; form factor +drivp_trk dw 80 +drivp_spt equ word ptr ioctl_bpb+13 +drivp_heads equ word ptr ioctl_bpb+15 ; # of heads + +ff_table dw bpb360, bpb1200, bpb720 ; 360/1200/720 Kb + dw bpb243, bpb1200 ; 8" sd/dd + dw bpb360, bpb360 ; hard disk, tape + dw bpb1440 ; 1440 Kb + +bpb360 dw 512 + db 2 + dw 1 + db 2 + dw 112 + dw 40*2*9 + db 0FDh + dw 2 + dw 9 + dw 2 + +bpb1200 dw 512 + db 1 + dw 1 + db 2 + dw 224 + dw 80*2*15 + db 0F9h + dw 7 + dw 15 + dw 2 + +bpb720 dw 512 ; bytes per sector + db 2 ; sectors/cluster + dw 1 ; FAT address + db 2 ; # of FAT copies + dw 112 ; root directory size + dw 80*2*9 ; sectors/disk + db 0F9h ; media byte + dw 3 ; size of single FAT copy + dw 9 ; sectors per track + dw 2 ; # of heads + +bpb1440 dw 512 + db 1 + dw 1 + db 2 + dw 224 + dw 80*2*18 + db 0F9h + dw 7 + dw 18 + dw 2 + +bpb243 dw 128 + db 4 + dw 1 + db 2 + dw 64 + dw 77*1*26 + db 0E5h + dw 1 + dw 26 + dw 1 + +msg_crlf db CR, LF +msg_dollar db '$' + +CFG_NAME equ word ptr .0000h ; Command Name +CFG_FUNC equ word ptr .0002h ; Command Subroutine +CFG_FLAGS equ word ptr .0004h ; Command flags +CFG_SIZE equ 6 ; Size of each Entry + +CF_NOF equ 0001h ; set if F5/F8 should be ignored +CF_LC equ 0002h ; set if case should be preserved +CF_QUERY equ 0004h ; set at run time eg. "DEVICE?" + +cfg_table rw 0 +if not ADDDRV + dw cmd_country, func_country, 0 ; COUNTRY=nnn,nnn,country + dw cmd_shell, func_shell, 0 ; SHELL=filename + dw cmd_lastdrive, func_lastdrive, 0 ; LASTDRIVE=d: + dw cmd_break, func_break, 0 ; BREAK=ON/OFF + dw cmd_buffers, func_buffers, 0 ; BUFFERS=nn + dw cmd_hibuffers, func_hibuffers, 0 ; HIBUFFERS=nn + dw cmd_fcbs, func_fcbs, 0 ; FCBS=nn + dw cmd_files, func_files, 0 ; FILES=nn + dw cmd_stacks, func_stacks, 0 ; STACKS=nn + dw cmd_fastopen, func_fastopen, 0 ; FASTOPEN=nnn + dw cmd_drivparm, func_drivparm, 0 ; DRIVPARM=/d:nn ... + dw cmd_history, func_history, 0 ; HISTORY=ON|OFF,NNN + dw cmd_hiinstall, func_hiinstall, 0 ; HIINSTALL=cmdstring + dw cmd_installhigh, func_hiinstall, 0 ; INSTALLHIGH=cmdstring + dw cmd_install, func_install, 0 ; INSTALL=cmdstring + dw cmd_hidos, func_hidos, 0 ; HIDOS=ON/OFF + dw cmd_dos, func_dos, 0 ; DOS=HIGH + dw cmd_set, func_set, CF_LC ; SET envar=string + dw cmd_switches, func_switches, CF_NOF ; SWITCHES=... +endif + dw cmd_hidevice, func_hidevice, 0 ; HIDEVICE=filename + dw cmd_devicehigh, func_hidevice, 0 ; DEVICEHIGH=filename + dw cmd_device, func_device, 0 ; DEVICE=filename + dw cmd_remark, func_remark, CF_NOF ; REM Comment + dw cmd_semicolon, func_remark, CF_NOF ; ; Comment + dw cmd_colon, func_remark, CF_NOF ; :label + dw cmd_chain, func_chain, 0 ; CHAIN=filename + dw cmd_goto, func_goto, 0 ; GOTO=label + dw cmd_gosub, func_gosub, 0 ; GOSUB=label + dw cmd_return, func_return, 0 ; RETURN (from GOSUB) + dw cmd_cls, func_cls, 0 ; Clear Screen + dw cmd_cpos, func_cpos, 0 ; Set Cursor Position + dw cmd_timeout, func_timeout, 0 ; set ? TIMEOUT + dw cmd_switch, func_switch, 0 ; SWITCH=n + dw cmd_onerror, func_onerror, CF_LC ; ONERROR='n' optional command + dw cmd_query, func_query, CF_NOF+CF_LC; ?optional command + dw cmd_echo, func_echo, CF_LC ; ECHO=string + dw cmd_exit, func_exit, 0 ; EXIT + dw cmd_error, func_error, 0 ; ERROR='n' + dw cmd_getkey, func_getkey, 0 ; GETKEY + dw cmd_yeschar, func_yeschar, 0 ; YESCHAR= + dw cmd_deblock, func_deblock, 0 ; DEBLOCK=xxxx + dw cmd_numlock, func_numlock, 0 ; NUMLOCK=ON/OFF + dw cmd_common, func_common, 0 ; [COMMON] + dw 0 ; end of table + +if not ADDDRV +cmd_country db 'COUNTRY',0 +cmd_shell db 'SHELL',0 +cmd_lastdrive db 'LASTDRIVE',0 +cmd_break db 'BREAK',0 +cmd_buffers db 'BUFFERS',0 +cmd_hibuffers db 'HIBUFFERS',0 +cmd_fcbs db 'FCBS',0 +cmd_files db 'FILES',0 +cmd_stacks db 'STACKS',0 +cmd_fastopen db 'FASTOPEN',0 +cmd_drivparm db 'DRIVPARM', 0 +cmd_history db 'HISTORY', 0 +cmd_install db 'INSTALL', 0 +cmd_hiinstall db 'HIINSTALL', 0 +cmd_installhigh db 'INSTALLHIGH', 0 +cmd_hidos db 'HIDOS',0 +cmd_dos db 'DOS',0 +cmd_set db 'SET',0 +cmd_switches db 'SWITCHES',0 +endif +cmd_hidevice db 'HIDEVICE',0 +cmd_devicehigh db 'DEVICEHIGH',0 +cmd_device db 'DEVICE',0 +cmd_remark db 'REM', 0 +cmd_semicolon db ';',0 +cmd_colon db ':',0 +cmd_chain db 'CHAIN',0 +cmd_goto db 'GOTO',0 +cmd_gosub db 'GOSUB',0 +cmd_return db 'RETURN',0 +cmd_cls db 'CLS',0 +cmd_cpos db 'CPOS',0 +cmd_timeout db 'TIMEOUT',0 +cmd_switch db 'SWITCH',0 +cmd_onerror db 'ONERROR',0 +cmd_query db '?',0 +cmd_echo db 'ECHO',0 +cmd_exit db 'EXIT',0 +cmd_error db 'ERROR',0 +cmd_getkey db 'GETKEY',0 +cmd_yeschar db 'YESCHAR',0 +cmd_deblock db 'DEBLOCK',0 +cmd_numlock db 'NUMLOCK',0 +cmd_common db '[COMMON]',0 + +cmd_on db 'ON',0 +cmd_off db 'OFF',0 + +confirm_msg1 db ' ($' +confirm_msg2 db ') ? $' +confirm_msg3 db CR,LF,'$' + +region_opt db '/L:',0 +slashs_opt db '/S',0 +size_opt db 'SIZE',0 +high_opt db 'HIGH',0 +low_opt db 'LOW',0 +umb_opt db 'UMB',0 +noumb_opt db 'NOUMB',0 + +himem_region dw 0 ; region to hidevice into +himem_size dw 0 ; minimum size wanted +himem_current dw 0 +himem_current_base dw 0 +himem_max dw 0 + +if ADDDRV +error_flag db 0 ;1 if error occurred during command + ;file processing, 0 otherwise +endif + +default_query_char db CR +default_switch_char db '1' + +keyb_timeout dw 0 ; default is no timeout +error_level dw 0 ; default is no error +save_sp dw 0 ; save SP here for GOSUB/RETURN's + + +INITENV DSEG PARA 'INITDATA' + +envstart rb 253 ; initial env buffer +envend dw 0 ; make it double null terminated + db 1Ah ; EOF marker env buffer + Public boot_options +boot_options dw 0 +; set by BIOS to either the SHIFT states, or to F5KEY or F8KEY + +EXE_LENGTH equ 001Ch + +exeBuffer rw 0 +exeSignature dw 0 ; 0000 Valid EXE contains 'MZ' +exeFinal dw 0 ; 0002 Image Length MOD 512 +exeSize dw 0 ; 0004 Image Length DIV 512 +exeRelcnt dw 0 ; 0006 No. of Relocation Items +exeHeader dw 0 ; 0008 Header Size in paragraphs +exeMinpara dw 0 ; 000A Minimum No extra paragraphs +exeMaxpara dw 0 ; 000C Maximum No of extra paragraphs +exeSS dw 0 ; 000E Displacment of Stack Segment +exeSP dw 0 ; 0010 Initial SP +exeChecksum dw 0 ; 0012 Negative CheckSum +exeIP dw 0 ; 0014 Initial IP +exeCS dw 0 ; 0016 Code Segment displacement +exeReloff dw 0 ; 0018 Byte Offset of First REL item +exeOverlay dw 0 ; 001A Overlay Number (0 == Resident) + + end + diff --git a/IBMBIO/IBMROS.EQU b/IBMBIO/IBMROS.EQU new file mode 100644 index 0000000..aa452ef --- /dev/null +++ b/IBMBIO/IBMROS.EQU @@ -0,0 +1,83 @@ +; File : $IBMROS.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG + +VIDEO_INT equ 10h +EQUIPMENT_INT equ 11h +MEMORY_INT equ 12h +DISK_INT equ 13h +ASYNC_INT equ 14h +SYSTEM_INT equ 15h +KEYBOARD_INT equ 16h +PRINTER_INT equ 17h +RTC_INT equ 1Ah +CTRLBRK_INT equ 1Bh + +; Int 10 subfunctions + +SET_CURSOR_TYPE equ 01h +WRITE_CURSOR equ 02h ; Set cursor position +READ_CURSOR equ 03h ; Read cursor position +SCROLL_UP equ 06h ; Scroll active page up +SCROLL_DOWN equ 07h ; Scroll active page down +READ_CHAR equ 08h ; Read attribute/char at cur position +WRITE_CHAR equ 09h ; Write attribute/char at cur position +WRITE_TTY equ 0eh ; Write teletype at current position +GET_STATE equ 0fh ; Return current video mode + +; Int 13 subfunctions + +ROS_RESET equ 00h ; reset disk system +ROS_READ equ 02h ; read from disk +ROS_WRITE equ 03h ; write to disk +ROS_VERIFY equ 04h ; verify data on disk +ROS_FORMAT equ 05h ; format track on disk +ROS_PARAM equ 08h ; get drive parameters +ROS_GETTYPE equ 15h ; get drive type +ROS_DSKCHG equ 16h ; check disk change status +ROS_SETTYPE equ 17h ; set disk type for format +ROS_SETMEDIA equ 18h ; set media type for format + +PRN_ERROR equ 00101001b ; printer error bits +PRN_NOTBUSY equ 10000000b +PRN_ACK equ 01000000b +PRN_PAPER equ 00100000b +PRN_SELECT equ 00010000b +PRN_IOERR equ 00001000b +PRN_TIMEOUT equ 00000001b + +AUX_ERROR equ 10000000b ; auxiliary error bits + +; Int 15 subfunctions + +EXT_MEMORY equ 88h ; Return extended memory size in KB diff --git a/IBMBIO/INIT.ASM b/IBMBIO/INIT.ASM new file mode 100644 index 0000000..16b14ec --- /dev/null +++ b/IBMBIO/INIT.ASM @@ -0,0 +1,1080 @@ +; File : $Workfile$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; INIT.ASM 1.25 93/12/07 15:51:27 +; Move int13pointer to offset 0B4h as some app expects it there +; INIT.ASM 1.24 93/11/18 18:57:20 +; Increase amount reserved for COMMAND.COM by 256 bytes +; INIT.ASM 1.23 93/11/17 19:29:26 +; Change default DEBLOCK seg to FFFF for performance reasons +; INIT.ASM 1.19 93/07/22 19:43:59 +; switch over to REQUEST.EQU +; ENDLOG + + + include BIOSGRPS.EQU + include DRMACROS.EQU + include IBMROS.EQU + include MSDOS.EQU + include REQUEST.EQU ; request header equates + include BPB.EQU + include UDSC.EQU + include DRIVER.EQU + +; IBM AT Hardware equates + +COMPRESSED equ TRUE ; enables compressed changes. + +; a little macro to help locate things +; it warns us when the ORG get trampled on +orgabs MACRO address + local was,is + was = offset $ + org address + is = offset $ + if was GT is + if2 + %OUT ERROR - absolute data overwritten !! moving it + endif + org was +endif +ENDM + +jmpfar MACRO address, fixup + db 0EAh ; jmpf opcode + dw CG:address ; offset of destination +fixup dw 0EDCh ; segment of destination +ENDM + +callfar MACRO address, fixup + db 09Ah ; callf opcode + dw CG:address ; offset of destination +fixup dw 0EDCh ; segment of destination +ENDM + +F5KEY equ 3F00h +F8KEY equ 4200h + +IVECT segment at 0000h + + org 0000h*4 +i0off dw ? +i0seg dw ? + + org 0001h*4 +i1off dw ? +i1seg dw ? + + org 0003h*4 +i3off dw ? +i3seg dw ? + + org 0004h*4 +i4off dw ? +i4seg dw ? + + org 0015h*4 +i15off dw ? +i15seg dw ? + + org 0019h*4 +i19off dw ? +i19seg dw ? + + org 001Eh*4 +i1Eptr label dword +i1Eoff dw ? +i1Eseg dw ? + + org 002Fh*4 +i2Fptr label dword +i2Foff dw ? +i2Fseg dw ? + + org 006Ch*4 +i6Cptr label dword +i6Coff dw ? +i6Cseg dw ? + +IVECT ends + + +CGROUP group CODE, RCODE, ICODE + +CG equ offset CGROUP + +CODE segment 'CODE' + + Assume CS:CGROUP, DS:Nothing, ES:Nothing, SS:Nothing + + public strat + + extrn ConsoleTable:word + extrn ClockTable:word + extrn SerParCommonTable:word + extrn DiskTable:near + extrn Int13Deblock:near + extrn Int13Unsure:near + extrn Int2FHandler:near + extrn ResumeHandler:near + + extrn biosinit_end:byte ; End of the BIOS Init Code and Data + extrn biosinit:near + + extrn boot_options:word + extrn rcode_fixups:word + extrn rcode_seg:word + extrn rcode_offset:word + extrn rcode_len:word + extrn icode_len:word + extrn current_dos:word + extrn device_root:dword + extrn mem_size:word + extrn ext_mem_size:word + extrn init_buf:byte + extrn init_drv:byte + extrn init_runit:byte + extrn comspec_drv:byte + extrn init_flags:word + + +include biosmsgs.def ; Include TFT Header File + + Public A20Enable +A20Enable proc near +;======== +; This location is fixed up at run time to be a RET +; If the BIOS is relocated to the HMA then it is fixed up again to be +; CALLF IBMDOS:A20Enable; RET +; Calling this location at run time will ensure that the HMA is mapped +; in so we can access the HMA code. +; +A20Enable endp + +init proc near ; this is at BIOSCODE:0000h +ifndef COPYPROT + jmp init0 ; jump to reusable init space +else + extrn protect:near ; Jump to Copy protection code + jmp protect ; which will return control to +endif ; INIT0 on completion +init endp + +compflg label word +ifdef COPYPROT + dw ' ' ; stops any compression working +else + dw offset CGROUP:INITDATA ; compresses from INITDATA onwards +endif ; this word set to 0 when compressed + + orgabs 06h + db 'COMPAQCompatible' + + dw offset CGROUP:RCODE ; lets find offset of RCODE +MemFixup dw 0 ; and its relocated segment + + + Public cleanup +cleanup PROC far ; BIOSINIT will call here later + ret +cleanup endp + +; Local single character buffer for Ctrl-Break handling + public serparFlag, serparChar + +serparFlag db 4 dup (FALSE) ; we haven't got any yet +serparChar db 4 dup (?) ; will store one character + + +; Device driver headers for serial/parallel devices + +con_drvr dw CG:aux_drvr, 0 ; link to next device driver + dw DA_CHARDEV+DA_SPECIAL+DA_ISCOT+DA_ISCIN+DA_IOCTL + dw CG:strat, CG:IntCon + db 'CON ' + +aux_drvr dw CG:prn_drvr, 0 ; link to next device driver + dw DA_CHARDEV + dw CG:strat, CG:IntCOM1 + db 'AUX ' + +prn_drvr dw CG:clock_drvr, 0 ; link to next device driver + dw DA_CHARDEV + dw CG:strat, CG:IntLPT1 + db 'PRN ' + +clock_drvr dw disk_drvr, 0 ; link to next device driver + dw DA_CHARDEV+DA_ISCLK + dw CG:strat, CG:IntClock + db 'CLOCK$ ' + +com1_drvr dw CG:lpt1_drvr, 0 ; link to next device driver + dw DA_CHARDEV + dw CG:strat, CG:IntCOM1 + db 'COM1 ' + +com2_drvr dw CG:com3_drvr, 0 ; link to next device driver + dw DA_CHARDEV + dw CG:strat, CG:IntCOM2 + db 'COM2 ' + +com3_drvr dw CG:com4_drvr, 0 ; link to next device driver + dw DA_CHARDEV + dw CG:strat, CG:IntCOM3 + db 'COM3 ' + +IFDEF EMBEDDED + extrn rdisk_drvr:near +com4_drvr dw CG:rdisk_drvr, 0 ; link to next device driver +ELSE +com4_drvr dw -1, -1 ; link to next device driver +ENDIF + dw DA_CHARDEV + dw CG:strat, CG:IntCOM4 + db 'COM4 ' + + + orgabs 0b4h ; save address at fixed location + ; for dirty apps + + Public i13pointer, i13off_save, i13seg_save + +i13pointer label dword ; address of ROS Int 13h entry +i13off_save dw ? +i13seg_save dw ? + + + orgabs 0b8h ; REQ_HDR + + public req_ptr, req_off, req_seg + +req_ptr label dword +req_off dw 0 ;** fixed location ** +req_seg dw 0 ;** fixed location ** + +strat proc far + mov cs:req_off,bx + mov cs:req_seg,es + ret +strat endp + +lpt1_drvr dw CG:lpt2_drvr, 0 ; link to next device driver + dw DA_CHARDEV + dw CG:strat, CG:IntLPT1 + db 'LPT1 ' + + +lpt2_drvr dw CG:lpt3_drvr, 0 ; link to next device driver + dw DA_CHARDEV + dw CG:strat, CG:IntLPT2 + db 'LPT2 ' + +lpt3_drvr dw CG:com2_drvr, 0 ; link to next device driver + dw DA_CHARDEV + dw CG:strat, CG:IntLPT3 + db 'LPT3 ' + + orgabs 100h ; save vectors at fixed location + ; for dirty apps + + Public orgInt13 + +NUM_SAVED_VECS equ 5 + +vecSave db 10h + dw 0,0 + db 13h +orgInt13 dw 0,0 + db 15h + dw 0,0 + db 19h + dw 0,0 + db 1Bh + dw 0,0 + +Int19Trap: + cld + cli ; be sure... + push cs + pop ds + lea si,vecSave + mov cx,NUM_SAVED_VECS ; restore this many vectors +Int19Trap10: + xor ax,ax ; zero AH for lodsb + mov es,ax ; ES -> interrupt vectors + lodsb ; AX = vector to restore + shl ax,1 + shl ax,1 ; point at address + xchg ax,di ; ES:DI -> location to restore + movsw + movsw ; restore this vector + loop Int19Trap10 ; go and do another + int 19h ; and go to original int 19... + + + orgabs 16ch ; PRN:/AUX: the device number + +devno db 0,0 ;** fixed location ** + + Public NumDiskUnits, DeblockSeg + +disk_drvr dw CG:com1_drvr, 0 ; link to next driver + dw DA_NONIBM+DA_GETSET+DA_REMOVE+DA_BIGDRV + dw CG:strat, CG:IntDisk +NumDiskUnits db 5, 7 dup (?) + dw 0EDCh ; checked by DRIVER.SYS + dw 0 ; was allocate UDSC +DeblockSeg dw 0A000h ; segment we start deblocking + + +IntLPT1: ; LPT1 + call DeviceDriver + dw 0 + +IntLPT2: ; LPT2 + call DeviceDriver + dw 1 + +IntLPT3: ; LPT3 + call DeviceDriver + dw 2 + +IntCOM1: ; AUX = COM1 + call DeviceDriver + dw 3 + +IntCOM2: ; COM2 + call DeviceDriver + dw 4 + +IntCOM3: ; COM3 + call DeviceDriver + dw 5 + +IntCOM4: ; COM4 + call DeviceDriver + dw 6 + +IntCon: + call DeviceDriver + dw offset CGROUP:ConsoleTable + +IntClock: + call DeviceDriver + dw offset CGROUP:ClockTable + + Public IntDiskTable +IntDisk: + call DeviceDriver +IntDiskTable: + dw offset CGROUP:DiskTable + +DeviceDriver proc near + call A20Enable ; make sure A20 is on + jmpfar DriverFunction, DriverFunctionFixup +DeviceDriver endp + + extrn i13_AX:word + + Public Int13Trap + +Int13Trap proc far +;-------- +; The Int 13 code is in low memory for speed, with unusual conditions +; having the overhead of A20Enable calls +; + cmp ah,ROS_FORMAT ; ROS format function? + je Int13TrapFormat +Int13Trap10: + mov cs:i13_AX,ax ; save Op/Count in case of error + clc + pushf ; fake an Int + call cs:i13pointer ; call the ROM BIOS + jc Int13Trap20 ; check for error + ret 2 ; none, so return to caller +Int13Trap20: + cmp ah,9 ; it it a DMA error ? + je Int13TrapDMA ; then deblock it + call Int13TrapUnsure ; else declare floppy drive unsure + stc ; restore error flag + ret 2 ; return to user + +Int13TrapFormat: + call Int13TrapUnsure ; mark media as unsure + jmps Int13Trap10 ; and resume + +Int13TrapDMA: + call A20Enable ; make sure A20 is on + jmpfar Int13Deblock, Int13DeblockFixup + +Int13TrapUnsure proc near + call A20Enable ; make sure A20 is on + callfar Int13Unsure, Int13UnsureFixup + ret +Int13TrapUnsure endp + +Int13Trap endp + + + Public Int2FTrap + +Int2FTrap proc far +;-------- + jmpfar Int2FHandler, Int2FFixup +Int2FTrap endp + + +Resume proc far +;----- + call A20Enable ; make sure A20 is on + jmpfar ResumeHandler, ResumeFixup +Resume endp + +Int0Trap proc far +;------- + call A20Enable ; make sure A20 is on + jmpfar Int0Handler, Int0Fixup +Int0Trap endp + + Public FastConsole + +FastConsole proc far +;---------- +; RAM entry to ensure INT29 vector is below INT20 vector +; We keep the normal path low to maxmimise performance, but on backspace we +; take the A20Enable hit and call high for greater TPA. +; + pushx ; old ROS corrupts these + cmp al,8 ; back space character + je Fastcon30 ; special case +Fastcon10: + mov ah,0Eh ; use ROS TTY-like output function + mov bx,7 ; use the normal attribute + int VIDEO_INT ; output the character in AL +Fastcon20: + popx + iret + +Fastcon30: + call A20Enable ; make sure A20 is on + jmpfar OutputBS, OutputBSFixup ; call up to the HMA + +FastConsole endp + + Public ControlBreak + +ControlBreak proc far +;----------- + mov cs:word ptr local_char,'C'-40h + (256*TRUE) +;; mov local_char,'C'-40h ; force ^C into local buffer +;; mov local_flag,TRUE ; indicate buffer not empty +Int1Trap: +Int3Trap: +Int4Trap: + iret +ControlBreak endp + + public daycount +daycount dw 0 + + + +; More Disk Data + + public local_buffer,local_id,local_pt + +local_buffer db 512 dup (?) ; local deblocking buffer +SECSIZE equ 512 +IDOFF equ SECSIZE-2 ; last word in boot sector is ID +PTOFF equ IDOFF-40h ; 4*16 bytes for partition def's +local_id equ word ptr local_buffer + IDOFF +local_pt equ word ptr local_buffer + PTOFF + + public bpbs,bpb160,bpb360,bpb720,NBPBS + +; List of BPBs that we usually support + +bpb160 BPB <512,1,1,2, 64, 40*1*8,0FEh,1, 8,1,0,0> +bpb180 BPB <512,1,1,2, 64, 40*1*9,0FCh,2, 9,1,0,0> +bpb320 BPB <512,2,1,2,112, 40*2*8,0FFh,1, 8,2,0,0> +bpb360 BPB <512,2,1,2,112, 40*2*9,0FDh,2, 9,2,0,0> +bpb1200 BPB <512,1,1,2,224,80*2*15,0F9h,7,15,2,0,0> +bpb720 BPB <512,2,1,2,112, 80*2*9,0F9h,3, 9,2,0,0> +bpb1440 BPB <512,1,1,2,224,80*2*18,0F0h,9,18,2,0,0> +bpb2880 BPB <512,2,1,2,240,80*2*36,0F0h,9,36,2,0,0> +NBPBS equ 8 + +; The following is a template, that gets overwritten +; with the real parameters and is used while formatting + + public local_parms,parms_spt,parms_gpl + public layout_table,bpbtbl + +local_parms db 11011111b ; step rate + db 2 ; DMA mode + db 37 ; 2*18.2 = 2 second motor off + db 2 ; 512 bytes per sector +parms_spt db 18 ; sectors per track + db 2Ah ; gap length for read/write + db 0FFh ; data length (128 byte/sector only) +parms_gpl db 50h ; data length for format + db 0F6h ; fill byte for format + db 15 ; head settle time in ms + db 8 ; motor on delay in 1/8s + +; The BPB table need not survive config time, so share with layout table + +bpbtbl label word + + MAX_SPT equ 40 + +layout_table label word ; current # of sectors/track + +S = 1 + +rept MAX_SPT + ; C H S N + ; - - - - + db 0, 0, S, 2 +S = S + 1 +endm + + orgabs 600h ; CON: one character look-ahead buffer +; nb. it's at 61B in DOS 4.0 + + Public local_char, local_flag + +local_char db 0 ;** fixed location ** +local_flag db 0 ;** fixed location ** + + public endbios +endbios dw offset CGROUP:RESBIOS ; pointer to last resident byte + +CODE ends + +ICODE segment 'ICODE' ; reusable initialization code + + Assume CS:CGROUP, DS:CGROUP, ES:CGROUP, SS:Nothing + +bpbs dw CG:bpb360 ; 0: 320/360 Kb 5.25" floppy + dw CG:bpb1200 ; 1: 1.2 Mb 5.25" floppy + dw CG:bpb720 ; 2: 720 Kb 3.5" floppy + dw CG:bpb360 ; 3: (8" single density) + dw CG:bpb360 ; 4: (8" double density) + dw CG:bpb360 ; 5: hard disk + dw CG:bpb360 ; 6: tape drive + dw CG:bpb1440 ; 7: 1.44 Mb 3.5" floppy + dw CG:bpb1440 ; 8: Other + dw CG:bpb2880 ; 9: 2.88 Mb 3.5" floppy + + Public init0 +init0 proc near +; +; We now uncompress to > (7C00h (ie. boot stack) - 700h (ie. base of code) +; This means our stack collides with our code, very bad news. +; To avoid this we switch stacks into a safer area ie. 0C000h +; The floppy parameters also live at 7C00, so we have to relocate these +; before we expand. + + mov cs:byte ptr A20Enable,0C3h + ; fixup the RET + + mov sp, 0C000h ; switch to magic stack + + sti + cld + + push cx ; save entry registers + push di ; (important in ROM systems) + + xor si,si + mov ds,si + mov es,si + + Assume DS:IVECT, ES:IVECT + + mov di,522h ; ES:DI -> save area for parameters + lds si,i1Eptr ; DS:SI -> FD parameters for ROS + + Assume DS:Nothing + + mov i1Eoff,di + mov i1Eseg,es ; setup new location + mov cx,11 + rep movsb + mov es:byte ptr 0-7[di],36 ; enable read/writing of 36 sectors/track + + pop di + pop cx + +if COMPRESSED + mov si, cs ; preserve entry registers + mov ds, si ; other than si, ds and es + mov es, si + xor si, si + mov si, compflg ; Get Compresed BIOS Flag + or si, si ; Set to Zero if the BIOS has + jnz not_compressed ; been compressed + mov si, CG:INITDATA + push di ; bios_seg + push ax ; bdos_seg + push bx ; initial drives + push cx ; memory size + push dx ; initial flags + lea cx, biosinit_end + sub cx, si + inc cx ; length of compressed part plus one + mov di, cx + neg di ; furthest offset we can use + and di, 0fff0h ; on the next para below + push di + push si + shr cx, 1 + rep movsw ; take a copy + pop di ; di is now -> compressed dest + pop si ; this is now -> compressed source +bios_r20: + lodsw ; get control word + mov cx,ax ; as a count + jcxz bios_r40 ; all done + test cx,8000h ; negative ? + jnz bios_r30 ; yes do zeros + rep movsb ; else move in data bytes + jmp short bios_r20 ; and to the next + +bios_r30: + and cx,7fffh ; remove sign + jcxz bios_r20 ; none to do + xor ax,ax + rep stosb ; fill with zeros + jmp short bios_r20 +bios_r40: + pop dx + pop cx + pop bx + pop ax + pop di +not_compressed: +endif + mov si,cs + mov ds,si ; DS -> local data segment + cmp dl,0ffh ; booting from ROM? + jz rom_boot + cmp si,1000h ; test if debugging + jb disk_boot ; skip if not + +; When the BIOS is loaded by the DOSLOAD or LOADER utilities under +; Concurrent for DEBUGGING or in a ROM system then on entry AX +; contains the current location of the BDOS and CX the memory Size. +; Bx is the current code segment + + mov rcode_seg,dx ; rom segment of bios + mov current_dos,ax ; current location of the BDOS + mov mem_size,cx ; total memory size + mov init_drv,bl ; initial drive + mov comspec_drv,bh ; + mov init_buf,3 ; assume default # of buffers + mov init_flags,3 + jmp bios_exit + +rom_boot: ; BIOS is copied from ROM: + ; DL = 0FFh + ; AX = segment address of DRBDOS + ; BH = COMSPEC drive + ; BL = INIT_DRV + mov rcode_seg,di ; DI = BIOS ROM SEG + mov current_dos,ax ; current location of the BDOS + mov init_drv,bl ; initial drive C: + mov comspec_drv,bh ; commspec drive C: + mov init_flags,3 ; it is a ROM system, use comspec drive + jmps rom_boot10 ; common code + +disk_boot: + mov rcode_seg,cs + sub ax,ax + mov current_dos,ax ; current BDOS location to disk load + xchg ax,dx ; AL = boot drive + mov init_runit,al ; save the ROS unit + test al,al ; test the boot drive + jz floppy_boot ; skip if floppy boot + mov al,2 ; it's drive C: +floppy_boot: + mov init_drv,al ; set boot drive + +rom_boot10: + pushx ; save registers + sub bx,bx + mov ds,bx ; DS:BX -> interrupt vectors + + Assume DS:IVECT + + push cs ; we want to save vectors some + pop es ; locally + + lea di,vecSave + mov cx,NUM_SAVED_VECS ; restore this many vectors +SaveVectors: + xor ax,ax ; zero AH + mov al,es:[di] ; AX = vector to save + inc di ; skip to save position + shl ax,1 + shl ax,1 ; point at address + xchg ax,si ; DS:SI -> location to save + movsw + movsw ; save this vector + loop SaveVectors ; go and do another + + mov i0off,CG:Int0Trap + mov i0seg,cs ; now grab int0 vector + mov i1off,CG:Int1Trap + mov i1seg,cs ; now grab int1 vector + mov i3off,CG:Int1Trap + mov i3seg,cs ; now grab int3 vector + mov i4off,CG:Int1Trap + mov i4seg,cs ; now grab int4 vector + mov i19off,CG:Int19Trap + mov i19seg,cs ; now grab int19 vector + + popx + + Assume DS:CGROUP, ES:CGROUP + + call get_boot_options ; look for user keypress + mov boot_options,ax ; return any options + + mov ah,EXT_MEMORY + int SYSTEM_INT ; find out how much extended memory + jnc bios_extmem + xor ax,ax ; say we have no memory +bios_extmem: + mov ext_mem_size,ax ; we have and store for reference + + mov init_buf,3 ; assume default of 3 buffers + int MEMORY_INT ; get amount of conventional memory + cmp ax,128 + jbe bios_mem + mov init_buf,5 ; use 5 buffers if > 128K of memory +bios_mem: ; get amount of conventional memory + mov cl,6 ; in kilobytes (AX) + shl ax,cl ; convert Kb's to paragraphs + mov mem_size,ax ; set end of TPA + +bios_exit: +; The following code performs the fixups necessary for ROM executable +; internal device drivers. + mov ax,cs ; check if we are on a rommed system + cmp ax,rcode_seg + jne keep_rcode ; if so no relocation required + mov ax,CG:RCODE + mov rcode_offset,ax ; fixup variable need + mov bx,CG:IDATA + sub bx,ax + mov icode_len,bx ; during init we need RCODE and ICODE + mov bx,CG:RESUMECODE + sub bx,ax + mov rcode_header,bx + mov rcode_len,bx ; afterwards we just need RCODE +keep_rcode: + +; If the system ROM BIOS supports RESUME mode then it will call Int 6C +; when returning from sleep mode. We take this over and reset the clock +; based upon the RTC value. To save space we only relocate the code if +; required. +; + mov ax,4100h ; does the BIOS support resume mode + xor bx,bx + int 15h ; lets ask it + jc resume_exit + push ds + xor ax,ax + mov ds,ax ; DS = vectors +Assume DS:IVECT + mov i6Coff,CG:Resume + mov i6Cseg,cs ; point Int 6C at resume code +Assume DS:CGROUP + pop ds + mov ax,cs ; check if we are on a rommed system + cmp ax,rcode_seg + jne resume_exit ; if so nothing extra to keep + mov ax,CG:RESBIOS + sub ax,CG:RCODE + mov rcode_header,ax ; keep Resume code as well... + mov rcode_len,ax ; afterwards we just need RCODE +resume_exit: + mov ax,CG:ENDCODE ; discard RCODE (we will relocate it) + mov endbios,ax + mov rcode_fixups,CG:bios_fixup_tbl + + mov bx,CG:con_drvr ; get first device driver in chain + mov word ptr device_root+0,bx + mov word ptr device_root+2,ds + +init1: + cmp word ptr [bx],0FFFFh ; last driver in BIOS? + je init3 + mov 2[bx],ds ; fix up segments in driver chain + mov bx,[bx] + jmps init1 +init3: + jmp biosinit ; jump to BIOS code + +init0 endp + +get_boot_options: +;---------------- +; On Entry: +; None +; On Exit: +; AX = boot options + mov si,offset CGROUP:starting_dos_msg + lodsb ; get 1st character (never NULL) +get_boot_options10: + mov ah,0Eh + mov bx,7 + int VIDEO_INT ; TTY write of character + lodsb ; fetch another character + test al,al ; end of string ? + jnz get_boot_options10 + call option_key ; poll keyboard for a while + jnz get_boot_options20 ; if key available return that + mov ah,2 ; else ask ROS for shift state + int 16h + and ax,3 ; a SHIFT key is the same as F5KEY + jz get_boot_options20 + mov ax,F5KEY ; ie. bypass everything +get_boot_options20: + ret + +option_key: +;---------- +; On Entry: +; None +; On Exit: +; AX = keypress if interesting (F5/F8) +; ZF clear if we have an interesting key +; +; Poll keyboard looking for a key press. We do so for a maximum of 36 ticks +; (approx 2 seconds). +; + xor ax,ax + int 1Ah ; get ticks in DX + mov cx,dx ; save in CX for later +option_key10: + push cx + mov ah,1 + int 16h ; check keyboard for key + pop cx + jnz option_key30 ; stop if key available + push cx + xor ax,ax + int 1Ah ; get ticks in DX + pop cx + sub dx,cx ; work out elapsed time + cmp dx,36 ; more than 2 secs ? + jb option_key10 +option_key20: + xor ax,ax ; timeout, set ZF, no key pressed + ret + +option_key30: + cmp ax,F5KEY ; if it is a key we want then + je option_key40 ; read it, else just leave + cmp ax,F8KEY ; in the type-ahead buffer + jne option_key20 +option_key40: + xor ax,ax + int 16h ; read the key + test ax,ax ; clear ZF to indicate we have a key + ret + +ICODE ends + +INITDATA segment 'INITDATA' + +; This is a zero terminated list of locations to be fixed up with the +; segment of the relocated BIOS RCODE + + +bios_fixup_tbl dw CG:MemFixup + dw CG:OutputBSFixup + dw CG:DriverFunctionFixup + dw CG:Int0Fixup + dw CG:Int13DeblockFixup + dw CG:Int13UnsureFixup + dw CG:Int2FFixup + dw CG:ResumeFixup +IFDEF EMBEDDED + dw CG:RdiskFixup +endif + dw 0 + +INITDATA ends + +CODE segment 'CODE' +IFDEF EMBEDDED + extrn RdiskFixup:word +endif +CODE ends + + +RCODE_ALIGN segment public para 'RCODE' +ifndef ROMSYS + db 1100h dup(0) ; reserve space for command.com +endif +RCODE_ALIGN ends + +RCODE segment public word 'RCODE' + +rcode_header dw 0 + + Public DataSegment + +DataSegment dw 0070h ; segment address of low data/code + +; Called to vector to appropriate sub-function in device driver +; The Function table address immediately follows the near call, so we can index +; into it using the return address. If the offset is in the range 0-6 it's +; actually a device number for the serial/parallel driver +; +; +; On Entry to subfunctions ES:BX -> req_hdr, DX = devno (serial/parallel) +; + +FunctionTable struc +FunctionTableMax db ? +FunctionTableEntry dw ? +FunctionTable ends + + Public DriverFunction + +DriverFunction proc far + cld + sub sp,(size P_STRUC)-4 ; make space for stack variables + push bp ; (BP and RET are included) + mov bp,sp ; set up stack frame + pushx + pushx ; save all registers + mov ds,cs:DataSegment + mov si,(size P_STRUC)-2[bp] ; get return address = command table + lodsw ; AX = following word + xchg ax,dx ; DX = device number (0-6) + mov si,offset CGROUP:SerParCommonTable + cmp dx,6 ; if not a device number it's a table + jbe DriverFunction10 + mov si,dx ; DS:SI -> table +DriverFunction10: + les bx,req_ptr ; ES:BX -> request header + mov REQUEST_OFF[bp],bx + mov REQUEST_SEG[bp],es + mov al,es:RH_CMD[bx] ; check if legal command + cmp al,cs:FunctionTableMax[si] + ja cmderr ; skip if out of range + cbw ; convert to word + add ax,ax ; make it a word offset + add si,ax ; add index to function table + call cs:FunctionTableEntry[si] + les bx,REQUEST[bp] +cmddone: + or ax,RHS_DONE ; indicate request is "done" + mov es:RH_STATUS[bx],ax ; update the status for BDOS + popx ; restore all registers + popx + pop bp + add sp,(size P_STRUC)-2 ; discard stack variables + ret + +cmderr: + mov ax,RHS_ERROR+3 ; "invalid command" error + jmps cmddone ; return the error + +DriverFunction endp + + + +OutputBS proc far +;------- +; pushx ; these are on the stack + pushx + mov ah,3 ; get cursor address + mov bh,0 ; on page zero + int VIDEO_INT ; BH = page, DH/DL = cursor row/col + test dx,dx ; row 0, col 0 + jz OutputBS10 ; ignore if first line + dec dl ; are we in column 0? + jns OutputBS10 ; no, normal BS + dec dh ; else move up one line + push ds + xor ax,ax + mov ds,ax + mov dl,ds:byte ptr [44ah] ; DL = # of columns + dec dx ; DL = last column + pop ds + mov ah,2 ; set cursor, DH/DL = cursor, BH = page + int VIDEO_INT ; set cursor address + jmps OutputBS20 + +OutputBS10: + mov ax,0E08h ; use ROS TTY-like output function + mov bx,7 ; use the normal attribute + int VIDEO_INT ; output the character in AL +OutputBS20: + popx + popx + iret + +OutputBS endp + + +Int0Handler proc far +;---------- + cld + push cs + pop ds + mov si,CG:div_by_zero_msg ; DS:SI points at ASCIZ message + mov bx,STDERR ; to STDERR - where else ? + mov cx,1 ; write one at a time +int0_loop: + mov dx,si ; DS:DX points at a char + lodsb ; lets look at it first + test al,al ; end of string ? + je int0_exit + mov ah,MS_X_WRITE ; write out the error + int DOS_INT + jnc int0_loop ; if it went OK do another +int0_exit: + mov ax,MS_X_EXIT*256+1 ; time to leave - say we got an error + int DOS_INT ; go for it! + +Int0Handler endp + +RCODE ends + + end init diff --git a/IBMBIO/INITMSGS.ASM b/IBMBIO/INITMSGS.ASM new file mode 100644 index 0000000..3f7d8ee --- /dev/null +++ b/IBMBIO/INITMSGS.ASM @@ -0,0 +1,82 @@ +NUL equ 0 +BS equ 8 +TAB equ 9 +LF equ 10 +CR equ 13 + +CGROUP group INITDATA + +INITDATA segment word public 'INITDATA' + assume ds:CGROUP, cs:CGROUP + +; Source .TFT file: 'TMP1.$$$' + public _yes_char + public yes_char +yes_char label byte +_yes_char db "Yy", NUL + public _no_char + public no_char +no_char label byte +_no_char db "Nn", NUL + public _bad_command + public bad_command +bad_command label byte +_bad_command db "Invalid command in CONFIG.SYS file.$", NUL + public _bad_filename + public bad_filename +bad_filename label byte +_bad_filename db "Bad or missing file $", NUL + public _bad_shell + public bad_shell +bad_shell label byte +_bad_shell db "Invalid SHELL filename $", NUL + public _bad_lastdrive + public bad_lastdrive +bad_lastdrive label byte +_bad_lastdrive db "Invalid last drive character (use A..Z) $", NUL + public _bad_break + public bad_break +bad_break label byte +_bad_break db "Invalid break switch (use ON or OFF)$", NUL + public _bad_buffers + public bad_buffers +bad_buffers label byte +_bad_buffers db "Invalid number of buffers $", NUL + public _bad_files + public bad_files +bad_files label byte +_bad_files db "Invalid number of files (use 5..255)", CR, LF, "$", NUL + public _bad_fcbs + public bad_fcbs +bad_fcbs label byte +_bad_fcbs db "Invalid number of FCBS", CR, LF, "$", NUL + public _bad_fopen + public bad_fopen +bad_fopen label byte +_bad_fopen db "Invalid number of FASTOPEN entries (use 128..32768)", CR, LF, "$", NUL + public _bad_drivparm + public bad_drivparm +bad_drivparm label byte +_bad_drivparm db "Invalid or missing DRIVPARM parameters, usage:", CR, LF, "DRIVPARM = /D:d [/C] [/F:f] [/H:h] [/N] [/S:s] [/T:t]", CR, LF, "$", NUL + public _bad_history + public bad_history +bad_history label byte +_bad_history db "Invalid HISTORY parameters, usage:", CR, LF, "HISTORY = ON|OFF [,nnn[, ON|OFF]]", CR, LF, "$", NUL + public _bad_country + public bad_country +bad_country label byte +_bad_country db "Invalid country code $", NUL + public _bad_exec + public bad_exec +bad_exec label byte +_bad_exec db "Bad or missing command interpreter.", CR, LF, "Please enter a valid filename.", CR, LF, "$", NUL + public _dos_msg + public dos_msg +dos_msg label byte +_dos_msg db CR, LF, "Can't load DOS file.$", NUL + +INITDATA ends + + + end + \ No newline at end of file diff --git a/IBMBIO/INITMSGS.DEF b/IBMBIO/INITMSGS.DEF new file mode 100644 index 0000000..069c933 --- /dev/null +++ b/IBMBIO/INITMSGS.DEF @@ -0,0 +1,32 @@ + extrn _bad_break : byte + extrn bad_break : byte + extrn _bad_buffers : byte + extrn bad_buffers : byte + extrn _bad_command : byte + extrn bad_command : byte + extrn _bad_country : byte + extrn bad_country : byte + extrn _bad_drivparm : byte + extrn bad_drivparm : byte + extrn _bad_exec : byte + extrn bad_exec : byte + extrn _bad_fcbs : byte + extrn bad_fcbs : byte + extrn _bad_filename : byte + extrn bad_filename : byte + extrn _bad_files : byte + extrn bad_files : byte + extrn _bad_fopen : byte + extrn bad_fopen : byte + extrn _bad_history : byte + extrn bad_history : byte + extrn _bad_lastdrive : byte + extrn bad_lastdrive : byte + extrn _bad_shell : byte + extrn bad_shell : byte + extrn _dos_msg : byte + extrn dos_msg : byte + extrn _no_char : byte + extrn no_char : byte + extrn _yes_char : byte + extrn yes_char : byte diff --git a/IBMBIO/INITMSGS.H b/IBMBIO/INITMSGS.H new file mode 100644 index 0000000..dde58b4 --- /dev/null +++ b/IBMBIO/INITMSGS.H @@ -0,0 +1,16 @@ +extern char near bad_break[]; +extern char near bad_buffers[]; +extern char near bad_command[]; +extern char near bad_country[]; +extern char near bad_drivparm[]; +extern char near bad_exec[]; +extern char near bad_fcbs[]; +extern char near bad_filename[]; +extern char near bad_files[]; +extern char near bad_fopen[]; +extern char near bad_history[]; +extern char near bad_lastdrive[]; +extern char near bad_shell[]; +extern char near dos_msg[]; +extern char near no_char[]; +extern char near yes_char[]; diff --git a/IBMBIO/MAKE.BAT b/IBMBIO/MAKE.BAT new file mode 100644 index 0000000..4047b71 --- /dev/null +++ b/IBMBIO/MAKE.BAT @@ -0,0 +1,119 @@ +@ECHO off +SET TOOLS=C:\TOOLS + +SET MASM=%TOOLS%\MASM.EXE +SET LINK=%TOOLS%\LINK.EXE +SET LIBR=%TOOLS%\LIB.EXE + +REM +REM YOU SHOULD NOT HAVE TO CHANGE ANYTHING BELOW THIS LINE. +REM + +REM Define local Caldera tools +SET LOCTOOLS=..\LTOOLS + +IF NOT EXIST BIN\*.* MD BIN + +REM Check if tools exist + +ECHO Checking for %MASM% +if not exist %MASM% goto badtool +ECHO Checking for %LINK% +if not exist %LINK% goto badtool +ECHO Checking for %LIBR% +if not exist %LIBR% goto badtool + + +REM ************************************* +REM Build .ASM files first, get the obj's +REM ************************************* + +%MASM% /t initmsgs,.\BIN\initmsgs; +IF ERRORLEVEL 1 GOTO FAILED +%MASM% /t biosmsgs,.\BIN\biosmsgs; +IF ERRORLEVEL 1 GOTO FAILED +%MASM% /t init,.\BIN\init; +IF ERRORLEVEL 1 GOTO FAILED +%MASM% /t clock,.\BIN\clock; +IF ERRORLEVEL 1 GOTO FAILED +%MASM% /t console,.\BIN\console; +IF ERRORLEVEL 1 GOTO FAILED +%MASM% /t disk,.\BIN\disk; +IF ERRORLEVEL 1 GOTO FAILED +%MASM% /t serpar,.\BIN\serpar; +IF ERRORLEVEL 1 GOTO FAILED +%MASM% /t biosgrps,.\BIN\biosgrps; +IF ERRORLEVEL 1 GOTO FAILED +%MASM% /t stacks,.\BIN\stacks; +IF ERRORLEVEL 1 GOTO FAILED + +REM ****************************************** +REM Build the library so that we can link into +REM ****************************************** +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\confstub.a86 .\BIN\confstub.obj $szpz /DDRDOS35=0 /DADDDRV=0 +IF ERRORLEVEL 1 GOTO FAILED +%LOCTOOLS%\fixupp .\BIN\confstub.obj +IF ERRORLEVEL 1 GOTO FAILED +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\bdosstub.a86 .\BIN\bdosstub.obj $szpz /DDRDOS35=0 /DADDDRV=0 +IF ERRORLEVEL 1 GOTO FAILED +%LOCTOOLS%\fixupp .\BIN\bdosstub.obj +IF ERRORLEVEL 1 GOTO FAILED +%LIBR% .\BIN\biosstub.LIB -+ .\BIN\bdosstub.obj -+ .\BIN\confstub.obj; +IF ERRORLEVEL 1 GOTO FAILED + +REM ****************************************** +REM Build the .A86 files next, get the obj's +REM ****************************************** +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\biosinit.a86 .\BIN\biosinit.obj $szpz /DDRDOS35=0 /DADDDRV=0 +IF ERRORLEVEL 1 GOTO FAILED +%LOCTOOLS%\fixupp .\BIN\biosinit.obj +IF ERRORLEVEL 1 GOTO FAILED +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\config.a86 .\BIN\config.obj $szpz /DDRDOS35=0 /DADDDRV=0 +IF ERRORLEVEL 1 GOTO FAILED +%LOCTOOLS%\fixupp .\BIN\config.obj +IF ERRORLEVEL 1 GOTO FAILED +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\bdosldr.a86 .\BIN\bdosldr.obj $szpz /DDRDOS35=0 /DADDDRV=0 +IF ERRORLEVEL 1 GOTO FAILED +%LOCTOOLS%\fixupp .\BIN\bdosldr.obj +IF ERRORLEVEL 1 GOTO FAILED +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\genercfg.a86 .\BIN\genercfg.obj $szpz /DDRDOS35=0 /DADDDRV=0 +IF ERRORLEVEL 1 GOTO FAILED +%LOCTOOLS%\fixupp .\BIN\genercfg.obj +IF ERRORLEVEL 1 GOTO FAILED +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\nlsfunc.a86 .\BIN\nlsfunc.obj $szpz /DDRDOS35=0 /DADDDRV=0 +IF ERRORLEVEL 1 GOTO FAILED +%LOCTOOLS%\fixupp .\BIN\nlsfunc.obj +IF ERRORLEVEL 1 GOTO FAILED + +REM *************************************************** +REM Link the OBJ's and LIBR file to create the BIOS.EXE +REM and then use EXE2BIN to create the IBMBIO.COM file. +REM *************************************************** +%LINK% @bios.lnk +IF ERRORLEVEL 1 GOTO FAILED +%LOCTOOLS%\exe2bin.exe .\bin\bios.exe .\bin\ibmbio.com +IF ERRORLEVEL 1 GOTO FAILED +del .\bin\bios.exe +%LOCTOOLS%\compbios .\bin\ibmbio.com +IF ERRORLEVEL 1 GOTO FAILED +goto exit + +:failed +ECHO Error in Build! +goto exit + +:badtool +ECHO Can't find that tool! + +:exit +REM ********* +REM CLEANUP +REM ********* + +SET TOOLS= +SET LOCTOOLS= +SET MASM= +SET TASM= +SET LINK= +SET LIBR= + \ No newline at end of file diff --git a/IBMBIO/MODFUNC.DEF b/IBMBIO/MODFUNC.DEF new file mode 100644 index 0000000..5321881 --- /dev/null +++ b/IBMBIO/MODFUNC.DEF @@ -0,0 +1,327 @@ +; File : $Workfile: MODFUNC.DEF$ +; +; Description : Standard VLADIVAR include file +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +;****************************************************************; +;* *; +;* OS386 Inter-Module Function Definitions *; +;* *; +;****************************************************************; + +OS386_FUNC equ 2780h ; AX value +OS386_INT equ 02Fh ; interrupt number + + ; Module definitions +USER equ 0 +SUP equ 1 +RTM equ 2 +MEM equ 3 +DOM equ 4 +VM equ 5 +DPMI equ 6 +DPMS equ 7 +MIN_MODULE equ 5 +MAX_MODULE equ 15 + + ; Internal SUP functions +F_NotImp equ SUP + 0100h * 00 ; Function Not Implemented +F_Illegal equ SUP + 0100h * 01 ; Illegal Function +F_ModuleReg equ SUP + 0100h * 02 ; Register Module +F_SysDatAlloc equ SUP + 0100h * 03 ; allocate SYSDAT memory +F_SysDat equ SUP + 0100h * 04 ; return SYSDAT selector +F_MoveReal equ SUP + 0100h * 05 ; move real mode memory to protected mode +F_Reboot equ SUP + 0100h * 06 +F_Debug equ SUP + 0100h * 07 +F_ForeCheck equ SUP + 0100h * 08 ; Check for foreground +F_RegisterVxD equ SUP + 0100h * 09 ; Register VxD with system +F_UnloadVxD equ SUP + 0100h * 10 ; Unload VxD hook +F_PostInit equ SUP + 0100h * 11 ; end of initialisation phase +F_AllocWindow equ SUP + 0100h * 12 ; allocate a 4K mapping window +F_RegisterBoot equ SUP + 0100h * 13 ; register reboot addresses +F_EnquireBoot equ SUP + 0100h * 14 ; enquire if reboot active +F_GetDebugLevel equ SUP + 0100h * 15 ; get debug level +F_SetDebugLevel equ SUP + 0100h * 16 ; set debug level +F_Version equ SUP + 0100h * 17 ; version check +F_V86BPInstall equ SUP + 0100h * 18 ; install v86 break point +F_V86BPRemove equ SUP + 0100h * 19 ; remove v86 break point +F_V86BPOffer equ SUP + 0100h * 20 ; offer int 3 as v86 break point +F_LoaderCleanup equ SUP + 0100h * 21 ; offer the chance to cleanup +F_RegisterVxDWindow equ SUP + 0100h * 22 ; Register VxD mapping window +F_RegisterPNW equ SUP + 0100h * 23 ; Register PNW info + + ; Internal RTM functions +F_PDCount equ RTM + 0100h * 01 +F_FlgWait equ RTM + 0100h * 02 +F_FlgSet equ RTM + 0100h * 03 +F_QMake equ RTM + 0100h * 04 +F_QOpen equ RTM + 0100h * 05 +F_QDelete equ RTM + 0100h * 06 +F_QRead equ RTM + 0100h * 07 +F_CQread equ RTM + 0100h * 08 +F_QWrite equ RTM + 0100h * 09 +F_CQWrite equ RTM + 0100h * 10 +F_Delay equ RTM + 0100h * 11 +F_Dispatch equ RTM + 0100h * 12 +F_PTerm equ RTM + 0100h * 13 +F_PCreat equ RTM + 0100h * 14 +F_SetPrior equ RTM + 0100h * 15 +F_PDAddr equ RTM + 0100h * 16 +F_PAbort equ RTM + 0100h * 17 +F_Sleep equ RTM + 0100h * 18 +F_Wakeup equ RTM + 0100h * 19 +F_FindPDName equ RTM + 0100h * 20 +F_SetFlags equ RTM + 0100h * 21 +F_EndOfInterrupt equ RTM + 0100h * 22 ; Register PIC end of interrupt +F_NoAbort equ RTM + 0100h * 23 +F_OkAbort equ RTM + 0100h * 24 +F_FlagStatus equ RTM + 0100h * 25 +F_QRdMX equ RTM + 0100h * 26 +F_QWrMX equ RTM + 0100h * 27 +F_FlgAlloc equ RTM + 0100h * 28 +F_FlgFree equ RTM + 0100h * 29 +F_NumFlags equ RTM + 0100h * 30 +F_NDQRead equ RTM + 0100h * 31 +F_FlgWWTO equ RTM + 0100h * 32 +F_UdaAlloc equ RTM + 0100h * 33 +F_UdaFree equ RTM + 0100h * 34 +F_PFreeze equ RTM + 0100h * 35 +F_PThaw equ RTM + 0100h * 36 +F_CritEnter equ RTM + 0100h * 37 +F_CritExit equ RTM + 0100h * 38 +F_PCreate equ RTM + 0100h * 39 +F_PDList equ RTM + 0100h * 40 +F_PDToName equ RTM + 0100h * 41 +F_PDToStatus equ RTM + 0100h * 42 +F_PDToDomain equ RTM + 0100h * 43 +F_GetPrior equ RTM + 0100h * 44 +F_QDList equ RTM + 0100h * 45 +F_QDToName equ RTM + 0100h * 46 +F_QDToMsgLen equ RTM + 0100h * 47 +F_QDToMaxMsgs equ RTM + 0100h * 48 +F_QDToNqPD equ RTM + 0100h * 49 +F_QDToDqPD equ RTM + 0100h * 50 +F_QDToNumMsgs equ RTM + 0100h * 51 +F_QDToFlags equ RTM + 0100h * 52 +F_NameToQD equ RTM + 0100h * 53 +F_NameToPD equ RTM + 0100h * 54 +F_MutexAlloc equ RTM + 0100h * 55 +F_MutexFree equ RTM + 0100h * 56 +F_MutexEnter equ RTM + 0100h * 57 +F_MutexCEnter equ RTM + 0100h * 58 +F_MutexExit equ RTM + 0100h * 59 +F_Slice equ RTM + 0100h * 60 +F_TickLength equ RTM + 0100h * 61 +F_ProcessID equ RTM + 0100h * 62 +F_QClose equ RTM + 0100h * 63 +F_QDispose equ RTM + 0100h * 64 +F_PDToFlags equ RTM + 0100h * 65 +F_PDToDParam equ RTM + 0100h * 66 +F_ReleaseMX equ RTM + 0100h * 67 +F_SimulateInt equ RTM + 0100h * 68 +F_SetQFlags equ RTM + 0100h * 69 +F_TickRate equ RTM + 0100h * 70 + + ; Internal MEMORY functions +F_PdirGet equ MEM + 0100h * 01 +F_PdirSet equ MEM + 0100h * 02 +F_PageAlloc equ MEM + 0100h * 03 +F_RealAllocG equ MEM + 0100h * 04 +F_RealAllocI equ MEM + 0100h * 05 +F_PtblRead equ MEM + 0100h * 06 +F_PtblWrite equ MEM + 0100h * 07 +F_PageGet equ MEM + 0100h * 08 +F_PageSet equ MEM + 0100h * 09 +F_PagesAlloc equ MEM + 0100h * 10 +F_PageFree equ MEM + 0100h * 11 +F_MemAlloc equ MEM + 0100h * 12 +F_MemFree equ MEM + 0100h * 13 +F_MemSize equ MEM + 0100h * 14 +F_MemResize equ MEM + 0100h * 15 +F_DescAlloc equ MEM + 0100h * 16 +F_DescFree equ MEM + 0100h * 17 +F_DescGet equ MEM + 0100h * 18 +F_DescSet equ MEM + 0100h * 19 +F_DescMemAlloc equ MEM + 0100h * 20 +F_DescMemFree equ MEM + 0100h * 21 +F_DescMemSize equ MEM + 0100h * 22 +F_DescMemResize equ MEM + 0100h * 23 +F_PageLock equ MEM + 0100h * 24 +F_PageUnlock equ MEM + 0100h * 25 +F_PageLockAny equ MEM + 0100h * 26 +F_PageUnlockReuse equ MEM + 0100h * 27 +F_PageLockNone equ MEM + 0100h * 28 +F_PageUnlockNone equ MEM + 0100h * 29 +F_CallRealRaw equ MEM + 0100h * 30 ; Call real mode (SS:ESP supplied) +F_IntRealRaw equ MEM + 0100h * 31 ; Do real mode interrupt (SS:ESP supplied) +F_CallReal equ MEM + 0100h * 32 ; Call real mode with RETF frame +F_IntReal equ MEM + 0100h * 33 ; Do real mode interrupt +F_PagedCallReal equ MEM + 0100h * 34 ; Paged real mode call +F_PagedIntReal equ MEM + 0100h * 35 ; Paged real mode interrupt +F_CallIretReal equ MEM + 0100h * 36 ; Call real mode with IRET frame +F_CallIretRealRaw equ MEM + 0100h * 37 ; Call real mode with IRET frame (SS:ESP supplied) +F_CallProt16 equ MEM + 0100h * 38 ; Call protected mode 16 bit code +F_CallProt32 equ MEM + 0100h * 39 ; Call protected mode 32 bit code +F_IAddPage equ MEM + 0100h * 40 ; add kernel instance data +F_BankPageLock equ MEM + 0100h * 41 +F_BankPageUnlock equ MEM + 0100h * 42 +F_BankPageLockAny equ MEM + 0100h * 43 +F_BankPageUnlockReuse equ MEM+0100h * 44 +F_BankPageLockNone equ MEM + 0100h * 45 +F_BankPageUnlockNone equ MEM+ 0100h * 46 +F_GateAlloc equ MEM + 0100h * 47 +F_GateFree equ MEM + 0100h * 48 +F_MemTotalFree equ MEM + 0100h * 49 +F_AddressSpace equ MEM + 0100h * 50 +F_MemTotal equ MEM + 0100h * 51 +F_DescRead equ MEM + 0100h * 52 +F_DescWrite equ MEM + 0100h * 53 +F_GetStack equ MEM + 0100h * 54 +F_SetStack equ MEM + 0100h * 55 + + ; Internal DOMain functions + +F_DAlloc equ DOM + 0100h * 00 ; create a new domain +F_DFree equ DOM + 0100h * 01 ; free up a domain +F_DGet equ DOM + 0100h * 02 ; get current domain +F_DSet equ DOM + 0100h * 03 ; switch to another domain +F_SWIntHandler equ DOM + 0100h * 04 ; Install Software Interrupt handler +F_PFaultHandler equ DOM + 0100h * 05 ; Install Page Fault handler +F_IOExHandler equ DOM + 0100h * 06 ; Install I/O Exception handler +F_GenExHandler equ DOM + 0100h * 07 ; Install General Exception handler +F_HWIntHandler equ DOM + 0100h * 08 ; Install HW int handler +F_IOBitGet equ DOM + 0100h * 09 ; Get domain IO bitmap +F_IOBitSet equ DOM + 0100h * 10 ; Set domain IO bitmap +F_BankIOBitGet equ DOM + 0100h * 11 ; Get domain banked IO bitmap +F_BankIOBitSet equ DOM + 0100h * 12 ; Set domain banked IO bitmap +F_BankMemGet equ DOM + 0100h * 13 ; Read domain banked memory +F_BankMemSet equ DOM + 0100h * 14 ; Write domain banked memory +F_BankPageGet equ DOM + 0100h * 15 ; Get domain banked page table entry +F_BankPageSet equ DOM + 0100h * 16 ; Set domain banked page table entry +F_RegInstData equ DOM + 0100h * 17 ; register DOS instance data +F_NProcesses equ DOM + 0100h * 18 ; Get number of processes in domain +F_DFreeze equ DOM + 0100h * 19 ; Suspend domain +F_DThaw equ DOM + 0100h * 20 ; Unsuspend domain +F_DFork equ DOM + 0100h * 21 ; Fork domain +F_DAbort equ DOM + 0100h * 22 ; Abort all processes in domain +F_UnlinkHandler equ DOM + 0100h * 23 ; Uninstall a handler +F_HWIntDfltHandler equ DOM + 0100h * 24 ; Install HW int default handler +F_VHWIntHandler equ DOM + 0100h * 25 ; Install Virtual HW int handler +F_VHWIntDfltHandler equ DOM + 0100h * 26 ; Install Virtual HW int default handler +F_SwapInHandler equ DOM + 0100h * 27 ; Install process swap in handler +F_SwapOutHandler equ DOM + 0100h * 28 ; Install process swap out handler +F_DosStartup equ DOM + 0100h * 29 ; Statup a DOS session +F_DosShutdown equ DOM + 0100h * 30 ; Terminate a DOS session +F_PCreateHandler equ DOM + 0100h * 31 ; Install process create handler +F_PDeleteHandler equ DOM + 0100h * 32 ; Install process terminate handler +F_RootPD equ DOM + 0100h * 33 ; Get Domain Root Process +F_DForeground equ DOM + 0100h * 34 ; Domain has just switched to foreground +F_DBackground equ DOM + 0100h * 35 ; Domain will be switching to background +F_MapHMA equ DOM + 0100h * 36 ; Map Domains HMA +F_AddInstData equ DOM + 0100h * 37 ; add DOS instance data +F_DMemFree equ DOM + 0100h * 38 ; get memory available to this domain +F_DMemTotal equ DOM + 0100h * 39 ; get memory allocated to this domain +F_DGetMemLimit equ DOM + 0100h * 40 ; get limit on local memory allocations +F_DSetMemLimit equ DOM + 0100h * 41 ; set limit on local memory allocations +F_ReflectInt21 equ DOM + 0100h * 42 ; support for protected mode Int 21's +F_DTestRegion equ DOM + 0100h * 43 ; test region for global/local memory +F_Switcher equ DOM + 0100h * 44 ; make task switcher call +F_HandlerCleanup equ DOM + 0100h * 45 ; debugger hook - remove all handlers for a selector +F_DFlagGet equ DOM + 0100h * 46 ; get Domain Flags +F_DFlagSet equ DOM + 0100h * 47 ; set Domain Flags +F_DSwitchHandler equ DOM + 0100h * 48 ; Install domain switch handler +F_GIOExHandler equ DOM + 0100h * 49 ; Install Global I/O Exception handler + +;------------ + +; VM Functions + +F_VMProtInit equ VM + 0100h * 00 ; Protected Mode initialisation internal) + +F_LoadMT equ VM + 0100h * 01 ; Load MultiTasking +F_UnloadMT equ VM + 0100h * 02 ; Unload MultiTasking +F_ConsoleFree equ VM + 0100h * 03 ; Save Console if enabled, then free it +F_ConsoleGet equ VM + 0100h * 04 ; Get Console, then restore if enabled +F_ConsoleSaveEnable equ VM +0100h * 05 ; Enable Console save/restore +F_ConsoleSaveDisable equ VM +0100h * 06 ; Disable Console save/restore + +F_TMInit equ VM + 0100h * 07 ; Task Manager Init +F_GetKey equ VM + 0100h * 08 ; Domain Manager to Keyboard Handler +F_KeyScanEnable equ VM + 0100h * 09 ; Enable hotkey scanning +F_KeyScanDisable equ VM + 0100h * 10 ; Disable hotkey scanning +F_ConsoleOwner equ VM + 0100h * 11 ; Get console owner domain id +F_DMAHandlerEnable equ VM + 0100h * 12 ; Re-enable DMA address translation +F_DMAHandlerDisable equ VM + 0100h * 13 ; Disable DMA address translation +F_SetSerialTimeout equ VM + 0100h * 14 ; Set Serial Port Timeout +F_SetParallelTimeout equ VM+ 0100h * 15 ; Set Parallel Port Timeout +F_VCPIEntry equ VM + 0100h * 16 ; Domain is going into VCPI mode +F_VCPIExit equ VM + 0100h * 17 ; Domain has probably come out of VCPI mode +F_SetGlobalMsgMode equ VM + 0100h * 18 ; Enter global message display mode +F_DisplayGlobalMsg equ VM + 0100h * 19 ; Ditto, plus display message +F_ExitGlobalMsgMode equ VM + 0100h * 20 ; Exit global message display mode +F_SetDomainMsgMode equ VM + 0100h * 21 ; Enter domain message display mode +F_DisplayDomainMsg equ VM + 0100h * 22 ; Ditto, plus display message +F_ExitDomainMsgMode equ VM + 0100h * 23 ; Exit domain message display mode +F_DisplayFatalMsg equ VM + 0100h * 24 ; Display fatal message +F_SetSerialBase equ VM + 0100h * 25 ; Set Serial port base address +F_SetParallelBase equ VM + 0100h * 26 ; Set Parallel port base address +F_SetSerialIRQ equ VM + 0100h * 27 ; Set Serial port IRQ number +F_SetParallelIRQ equ VM + 0100h * 28 ; Set Parallel port IRQ number +F_ResetVideo equ VM + 0100h * 29 ; EMERGENCY reset of the video system +F_SetMouseIRQ equ VM + 0100h * 30 ; Set mouse IRQ +F_CheckNotIdle equ VM + 0100h * 31 ; Check if we are idle or not +F_GetMouseInfo equ VM + 0100h * 32 +F_GetSerialOwner equ VM + 0100h * 33 +F_GetSerialTimeout equ VM + 0100h * 34 +F_GetParallelOwner equ VM + 0100h * 35 +F_GetParallelTimeout equ VM+ 0100h * 36 + +LAST_VM_FUNC equ 36 + +;------------ + +; DPMI Functions + +; These "DPMI" functions are those that are provided by the DPMI module via the +; Vladivar interface. True DPMI functions should be accessed via int 31h as per +; the DPMI spec. + +F_InitDPMI equ DPMI + 0100h * 0 ; used internally by DPMI. Do not call. +F_DescAllocLDT equ DPMI + 0100H * 1 ; allocate an LDT descriptor +F_DescFreeLDT equ DPMI + 0100H * 2 ; free an LDT descriptor +F_DescGetLDT equ DPMI + 0100H * 3 ; same as F_DescGet, but for LDT +F_DescSetLDT equ DPMI + 0100H * 4 ; same as F_DescSet, but for LDT +F_DescAllocInt21 equ DPMI + 0100H * 5 ; allocate an LDT descriptor for pmode + ; int 21 memory allocation. +F_WhereIsDPMI equ DPMI + 0100H * 6 ; return address of DPMI global data + +LAST_DPMI_FUNC equ 6 + diff --git a/IBMBIO/MSDOS.EQU b/IBMBIO/MSDOS.EQU new file mode 100644 index 0000000..6b4738f --- /dev/null +++ b/IBMBIO/MSDOS.EQU @@ -0,0 +1,131 @@ +; File : $Workfile: MSDOS.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; MSDOS.EQU 1.1 92/11/10 10:48:56 +; Added to appslib source directory. +; ENDLOG + +MS_P_TERMCPM equ 00H +MS_C_READ equ 01H +MS_C_WRITE equ 02H +MS_A_READ equ 03H +MS_A_WRITE equ 04H +MS_L_WRITE equ 05H +MS_C_RAWIO equ 06H +MS_C_RAWIN equ 07H +MS_C_NOECHO equ 08H +MS_C_WRITESTR equ 09H +MS_C_READSTR equ 0aH +MS_C_STAT equ 0bH +MS_C_FLUSH equ 0cH +MS_DRV_ALLRESET equ 0dH +MS_DRV_SET equ 0eH +MS_F_OPEN equ 0fH +MS_F_CLOSE equ 10H +MS_F_SFIRST equ 11H +MS_F_SNEXT equ 12H +MS_F_DELETE equ 13H +MS_F_READ equ 14H +MS_F_WRITE equ 15H +MS_F_MAKE equ 16H +MS_F_RENAME equ 17H +MS_DRV_GET equ 19H +MS_F_DMAOFF equ 1aH +MS_DRV_ALLOC equ 1bH +MS_DRV_ALLOCSPEC equ 1cH +MS_F_READRAND equ 21H +MS_F_WRITERAND equ 22H +MS_F_SIZE equ 23H +MS_F_RANDREC equ 24H +MS_S_SETINT equ 25H +MS_P_MKPSP equ 26H +MS_F_READBLK equ 27H +MS_F_WRITEBLK equ 28H +MS_F_PARSE equ 29H +MS_T_GETDATE equ 2aH +MS_T_SETDATE equ 2bH +MS_T_GETTIME equ 2cH +MS_T_SETTIME equ 2dH +MS_F_VERIFY equ 2eH +MS_F_DMAGET equ 2fH +MS_S_BDOSVER equ 30H +MS_P_TERMKEEP equ 31H +MS_S_BREAK equ 33H +MS_S_GETINT equ 35H +MS_DRV_SPACE equ 36H +MS_S_COUNTRY equ 38H +MS_X_MKDIR equ 39H +MS_X_RMDIR equ 3aH +MS_X_CHDIR equ 3bH +MS_X_CREAT equ 3cH +MS_X_OPEN equ 3dH +MS_X_CLOSE equ 3eH +MS_X_READ equ 3fH +MS_X_WRITE equ 40H +MS_X_UNLINK equ 41H +MS_X_LSEEK equ 42H +MS_X_CHMOD equ 43H +MS_X_IOCTL equ 44H +MS_X_DUP equ 45H +MS_X_DUP2 equ 46H +MS_X_CURDIR equ 47H +MS_M_ALLOC equ 48H +MS_M_FREE equ 49H +MS_M_SETBLOCK equ 4aH +MS_X_EXEC equ 4bH +MS_X_EXIT equ 4cH +MS_X_WAIT equ 4dH +MS_X_FIRST equ 4eH +MS_X_NEXT equ 4fH +MS_P_SETPSP equ 50H +MS_F_GETVERIFY equ 54H +MS_X_RENAME equ 56H +MS_X_DATETIME equ 57H +MS_M_STRATEGY equ 58h +MS_F_ERROR equ 59H +MS_X_MKTEMP equ 5aH +MS_X_MKNEW equ 5bH +MS_F_LOCK equ 5cH +MS_X_EXPAND equ 60H +MS_P_GETPSP equ 62H +MS_X_GETCP equ 6601h +MS_X_SETCP equ 6602h +MS_X_SETHC equ 67h +MS_X_COMMIT equ 68h + +DOS_INT equ 21h ; DOS Entry Point +; +STDIN equ 0 ; Standard Console Input Handle +STDOUT equ 1 ; Standard Console Output Handle +STDERR equ 2 ; Standard Error Output +STDAUX equ 3 ; Auxilary Device Handle +STDPRN equ 4 ; Printer Device Handle diff --git a/IBMBIO/MSERROR.EQU b/IBMBIO/MSERROR.EQU new file mode 100644 index 0000000..814bb1f --- /dev/null +++ b/IBMBIO/MSERROR.EQU @@ -0,0 +1,121 @@ +; File : $MSERROR.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG + +ED_FUNCTION equ -01 ; invalid function number +ED_FILE equ -02 ; file not found +ED_PATH equ -03 ; path not found +ED_HANDLE equ -04 ; too many open files +ED_ACCESS equ -05 ; file access denied +ED_H_MATCH equ -06 ; invalid handle number +ED_DMD equ -07 ; memory descriptor destroyed +ED_MEMORY equ -08 ; insufficient memory +ED_BLOCK equ -09 ; invalid memory block addr +ED_ENVIRON equ -10 ; invalid environment +ED_FORMAT equ -11 ; invalid format +ED_ACC_CODE equ -12 ; invalid access code +ED_DATA equ -13 ; invalid data +ED_DRIVE equ -15 ; invalid drive specified +ED_DIR equ -16 ; can't remove current dir +ED_DEVICE equ -17 ; not same device +ED_ROOM equ -18 ; no more files + +ED_PROTECT equ -19 ; disk write protected +ED_BADUNIT equ -20 ; invalid drive specified +ED_NOTREADY equ -21 ; drive doesn't respond +ED_BADCMD equ -22 ; invalid command to driver +ED_BADDATA equ -23 ; data CRC error +ED_BADRHLEN equ -24 ; (shouldn't happen) +ED_BADSEEK equ -25 ; can't seek to track +ED_BADMEDIA equ -26 ; unrecognizable medium +ED_RNF equ -27 ; record/sector not found +ED_NOPAPER equ -28 ; printer error +ED_WRFAIL equ -29 ; write failed +ED_RDFAIL equ -30 ; read failed +ED_GENFAIL equ -31 ; anything failed +ED_SHAREFAIL equ -32 ; sharing conflict +ED_LOCKFAIL equ -33 ; locking conflict +ED_DISKCHG equ -34 ; invalid disk change +ED_NOFCBS equ -35 ; FCB table exhausted +ED_NOLOCKS equ -36 ; lock list items exhausted +ED_NET equ -50 ; Network Request Not Supported + +ED_NETACCESS equ -65 ; file access denied + +ED_NETPWD equ -73 ; Server Password Error +ED_NETVER equ -74 ; Incorrect Server version +ED_NETREQ equ -75 ; No Local Network Resources +ED_NETTIME equ -76 ; Network Time Out Error +ED_NETCOMM equ -77 ; Network Communications Error +ED_NETSRVR equ -78 ; No Server Network Resources +ED_NETLOG equ -79 ; Server Not Logged In + +ED_EXISTS equ -80 ; file already exists +ED_MAKE equ -82 ; Cannot Make (Files ??) +ED_FAIL equ -83 ; FAIL code returned from INT 24 +ED_STRUCT equ -84 ; Out of Structures +ED_ASSIGN equ -85 ; Already Assigned +ED_PASSWORD equ -86 ; Invalid Password +ED_PARAM equ -87 ; Invalid Parameter +ED_NETWRITE equ -88 ; Network write fault +ED_NETFUNC equ -89 ; Function not supported on network +ED_COMPONENT equ -90 ; system component not installed +ED_LASTERROR equ -90 ; Last Error Number Used + +CLASS_RESOURCE equ 1 ; Out of Resource +CLASS_TEMP equ 2 ; Temporary Situation +CLASS_AUTHOR equ 3 ; Authorization Error +CLASS_INTERNAL equ 4 ; Internal System Software Error +CLASS_HARDWARE equ 5 ; Hardware Failure +CLASS_SYSTEM equ 6 ; Serious System Failure +CLASS_APPLIC equ 7 ; Application Program Error +CLASS_LOST equ 8 ; File/Item Not Found +CLASS_FORMAT equ 9 ; File/Item Illegal Format +CLASS_LOCKED equ 10 ; File/Item Locked +CLASS_MEDIA equ 11 ; Media Failure +CLASS_EXISTS equ 12 ; Item Already Exists +CLASS_UNKNOWN equ 13 ; Unknown Classification + +ACT_RETRY equ 1 ; Retry a few times then prompt user +ACT_DELAY equ 2 ; Delay then as ACT_RETRY +ACT_USER equ 3 ; Prompt user to re-enter data +ACT_ABORT equ 4 ; Clean Up then ABORT the process +ACT_TERM equ 5 ; Terminate immeadiately NO CLEAN UP +ACT_IGNORE equ 6 ; Ignore the Error +ACT_URETRY equ 7 ; Retry the error after user intervention + +LOC_UNKNOWN equ 1 ; Unknown error location +LOC_BLOCK equ 2 ; Block Device Failure +LOC_NET equ 3 ; Network Failure +LOC_CHAR equ 4 ; Related to Serial/Character devices +LOC_MEMORY equ 5 ; Failure related to Memory diff --git a/IBMBIO/NLSFUNC.A86 b/IBMBIO/NLSFUNC.A86 new file mode 100644 index 0000000..adbd592 --- /dev/null +++ b/IBMBIO/NLSFUNC.A86 @@ -0,0 +1,417 @@ +; File : $NLSFUNC.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; NLSFUNC.A86 1.6 93/12/01 18:30:10 +; Read in full 258 bytes of collating info +; ENDLOG + +; +; We have a problem with NLSFUNC.EXE - if this isn't loaded with an INSTALL= +; in CONFIG.SYS then the calls to set language/codepage will fail. +; So we provide the same functionality that NLSFUNC.EXE does here in the +; initialisation code. "nls_hook" is called by CONFIG before the country is +; set, then "nls_unhook" is called afterwards so we can throw away this code. +; + +VALID_SIG equ 0EDC1h ; valid signature in COUNTRY.SYS file + +DH_NEXT equ ds:dword ptr 0 ; Dword Pointer to Next DEV +DH_ATTRIB equ ds:word ptr 4 ; device attribute bits +DH_NAME equ ds:byte ptr 10 ; 8-BYTE device name + +DA_CHARDEV equ 8000h ; 1=character device, 0=block device +DA_IOCTL equ 4000h ; device supports IOCTL string I/O +DA_GETSET equ 0040h ; supports 3.2 level functionality + + include config.equ + include i:msdos.equ + include i:mserror.equ + + +CGROUP GROUP INITCODE +INITCODE CSEG PARA 'INITCODE' + +; We share our NLS buffer with other temporary users + + extrn nls_temp_area:byte + + Public nls_hook, nls_unhook + +nls_hook: +;-------- +; On Entry: +; none +; On Exit: +; none +; + push es + mov ah,MS_S_GETINT + mov al,2fh + int DOS_INT ; read and save old INT 2F vector + mov old_int2f_off,bx + mov old_int2f_seg,es + mov ah,MS_S_SETINT + mov al,2fh + mov dx,offset int2f_handler ; install our own INT 2F handler + int DOS_INT + pop es + ret + +nls_unhook: +;---------- +; On Entry: +; none +; On Exit: +; none +; + push ds + mov dx,old_int2f_off + mov ds,old_int2f_seg + mov ah,MS_S_SETINT ; restore INT 2F vector + mov al,2fh + int DOS_INT + pop ds + ret + + +old_int2f rd 0 + +old_int2f_off dw 0 +old_int2f_seg dw 0 + +int2f_handler: +;------------- + cmp ah,014h ; is it for us ? + je int2f_handler10 + jmpf old_int2f ; no, pass it on + +int2f_handler10: + cmp al,0 ; installation check ? + jne int2f_handler20 + mov al,0ffh ; we are already installed + iret + +int2f_handler20: + cmp al,0ffh ; Codepage Prep ? + jne int2f_handler30 + call f66_prep + retf 2 ; iret, keeping flags + +int2f_handler30: + cmp al,0feh ; Country Get Data ? + jne int2f_handler40 + call f65_locate_and_read + retf 2 ; iret, keeping flags + +int2f_handler40: + stc ; CY to indicate an error + mov ax,-ED_FUNCTION ; function not supported + retf 2 ; return an error + + +f66_cp dw 0 ; INT21/66 Local Variable +cp_packet dw 2 ; Packet Size +cp_cpid dw 0 ; Request CodePage + db 0,0 ; Packet Terminators + +preperr dw 0 ; Prepare function Error Code +prepname rb 9 ; Reserved for ASCIIZ Device Name + +; +; Area for country.sys current pointer table +; (these are all offsets into country.sys) +; +f65xx_code dw 0 ; Country code +f65xx_cp dw 0 ; Code page + dw 0 ; +1 reserved +f65xx_data dw 0 ; Data area + dw 0 ; Upper case table + dw 0 ; +1 reserved + dw 0 ; Filename upper case table + dw 0 ; Legal file characters + dw 0 ; Collating table + dw 0 ; Double byte character set lead byte table +f65xx_ptable_len equ 20 + +f65xx_codepage dw 0 +f65xx_country dw 0 +f65xx_sig dw 0 ; Signature +c_handle dw 0 + + +f66_prep: +; +; This function scans the complete device list and prepares +; all devices which support codepage. +; +; On Entry BX Requested CodePage +; +; On Exit AX Last Error Code +; +DA_CODEPAGE equ DA_CHARDEV+DA_IOCTL+DA_GETSET + + push ds + push es + push cs + pop es + mov f66_cp,bx ; Save requested CodePage + mov preperr,0000 ; Initialize Prepare Error + mov ax,122ch ; magic hook get Device List + int 2fh ; after the NUL entry + mov ds,bx ; BX:AX -> header after INT 2F + mov bx,ax ; DS:BX -> header to be useful +f66_p10: + push ds + push bx + mov ax,DH_ATTRIB[bx] + and ax,DA_CODEPAGE ; Check for a Character Device which + cmp ax,DA_CODEPAGE ; supports IOCTL strings and GETSET + jnz f66_p40 ; otherwise skip the device + + lea si,DH_NAME[bx] ; Found a matching device so + mov di,offset prepname ; open the device and select the + mov cx,8 ; requested codepage + +f66_p20: + lodsb + cmp al,' ' + je f66_p30 + stosb + loop f66_p20 + +f66_p30: + xor al,al + stosb + push cs + pop ds + mov dx,offset prepname ; Write Access + mov cl,1 ; Open for write + mov ax,1226h + int 2fh ; call magic hook + jc f66_perr + mov bx,ax ; Save Device Handle in BX + + mov si,f66_cp ; Get Requested CodePage in SI + mov dx,offset cp_packet ; Offset of CodePage Struct + mov cx,006Ah ; Get Unknown CodePage + push bp + mov bp,0ch ; Generic IOCTL + mov ax,122bh + int 2fh ; call magic hook + pop bp + jc f66_p32 ; Error so Select requested Code Page + + cmp si,cp_cpid + je f66_p35 ; If this the currently selected +f66_p32: ; skip the select CodePage + mov cp_cpid,si + mov dx,offset cp_packet ; Offset of CodePage Struct + mov cx,004Ah ; Select Unkown CodePage + push bp + mov bp,0ch ; Generic IOCTL + mov ax,122bh + int 2fh ; call magic hook + pop bp + jnc f66_p35 ; No Error so skip the error +f66_p33: + mov preperr,ax ; save + +f66_p35: + mov ax,1227h + int 2fh ; magic hook to close handle + jmp f66_p40 + +f66_perr: + mov preperr,ax ; Save the error code and try the +f66_p40: ; next device in the chain + pop bx ; Restore the Device offset + pop ds + lds bx,DH_NEXT[bx] ; check next character device for + cmp bx,0FFFFh ; Codepage support + jne f66_p10 + + mov ax,preperr ; All devices have been prepared + pop es + pop ds + or ax,ax ; now return the last error code + ret ; in AX + +; +; ********************************************************************** +; *** Function 65 support - routines for seeking a country/codepage *** +; *** and loading the required information into the temp data area *** +; ********************************************************************** +; +; ************************************************** +; *** Open country.sys and search for the *** +; *** table of offsets for the given country/ *** +; *** codepage, read it in and exit. *** +; ************************************************** + +f65_locate_and_read: +;------------------- +; Locate and Read info CL for Country DX Codepage BX using file DS:DI + test di,di ; valid filename ? + stc + jz f65_lr_exit + + push cx + call f65x_find_info ; Will need to load up the info + pop ax + jc f65_lr_exit ; so do it if we can. + + mov dx,offset nls_temp_area + mov cx,258 ; read 258 bytes into local buffer + push ax + call f65x_load_info ; Load required info + pop ax + jc f65_lr_exit + mov bx,c_handle ; Close the file first + mov ax,1227h + int 2fh ; magic hook to close handle + jc f65_lr_exit + mov si,offset nls_temp_area ; Tell subroutines where info is +f65_lr_exit: + ret +; +; Entry: dx=country code, bx=codepage +; Exit : carry set, and country.sys closed if failure +; country.sys open ready for more reads if success +; +f65x_find_info: + mov f65xx_country,dx + mov f65xx_codepage,bx + mov dx,di + xor cx,cx ; Open for read + mov ax,1226h + int 2fh ; call magic hook + push cs ; get DS pointing to this segment + pop ds ; for future reads + jnc f65x_10 + ret ; Successful open? +f65x_10: + mov c_handle,ax ; Save handle + mov dx,f65xx_country + cmp f65xx_code,dx ; do we already have the information? + jne f65x_30 ; No - get it from country.sys +f65x_20: + cmp f65xx_cp,bx ; Does codepage agree too? + je f65x_35 ; Yes so exit with no more ado +f65x_30: + mov dx,007Eh + xor cx,cx ; Seek within country.sys + mov bx,c_handle + push bp + mov bp,0 ; seek from begining + mov ax,1228h + int 2fh + pop bp + jc f65x_err + mov bx,c_handle ; check them + mov cx,2 + mov dx,offset f65xx_sig + mov ax,1229h + int 2fh ; read the signature bytes + jc f65x_err + cmp f65xx_sig,VALID_SIG + jne f65x_err ; If signature bad exit +f65x_32: + mov bx,c_handle ; Read from country.sys header until + mov cx,f65xx_ptable_len ; Country/codepage found or NULL + mov dx,offset f65xx_code + mov ax,1229h + int 2fh + jc f65x_err + cmp f65xx_code,0 ; Found NULL so reqd combination + je f65x_err ; was not found + mov dx,f65xx_code ; Get the country/codepage values + mov bx,f65xx_cp ; read from Country.SYS + cmp dx,f65xx_country ; Check against the requested + jne f65x_32 ; Country. + cmp f65xx_codepage,0 ; If a codepage match is not + jz f65x_35 ; then return success + cmp bx,f65xx_codepage ; Check against the requested + jne f65x_32 ; Codepage +f65x_35: + mov f65xx_country,dx ; Force the Search Country and + mov f65xx_codepage,bx ; CodePage to be Updated + ret + +f65x_err: + mov bx,c_handle ; and set the carry flag before + mov ax,1227h + int 2fh ; magic hook to close handle + stc + ret + +; +; ************************************************** +; *** Load the type of information requested *** +; *** For the country currently active in the *** +; *** offset table *** +; ************************************************** +; +; Entry: al=type of info, dx=offset of buffer to read info into cx=no of bytes +; Exit : carry set, and country.sys closed if failure +; +f65x_load_info: + push es + push cx + push dx + push ds ; Make es=ds + pop es + dec al ; 1=Data , 2=uppercase, 4=fuppercase + sub bh,bh ; 5=filechars, 6=Collating table + mov bl,al ; 7=DBCS table + shl bx,1 ; Retrieve relevant offset + mov dx,f65xx_data[bx] + xor cx,cx ; Seek within country.sys + mov bx,c_handle + push bp + mov bp,0 ; seek from begining + mov ax,1228h + int 2fh + pop bp + pop dx ; Get buffer address back + pop cx ; and number of bytes to read + jc f65x_err + test ax,ax ; zero offset is a problem + jz f65x_err ; (probably DBCS with old COUNTRY.SYS) + mov bx,c_handle ; Now read that info into our data area + mov ax,1229h + int 2fh + jc f65x_err + pop es + ret + + + end diff --git a/IBMBIO/PATCH.COD b/IBMBIO/PATCH.COD new file mode 100644 index 0000000..1778bc5 --- /dev/null +++ b/IBMBIO/PATCH.COD @@ -0,0 +1,104 @@ +; File : $PATCH.COD$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +;***************************************************** +;* +;* PATCH AREA -- 256 bytes long +;* +;***************************************************** + +patch: + + nop ! nop ! nop ! nop ! nop ! nop ;00-0f + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;10-1f + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;20-2f + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;30-3f + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;40-4f + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;50-5f + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;60-6f + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;70-7f + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;80-8f + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;90-9f + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;a0-af + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;b0-bf + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;c0-cf + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;d0-df + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;e0-ef + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;f0-ff + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop diff --git a/IBMBIO/PSP.DEF b/IBMBIO/PSP.DEF new file mode 100644 index 0000000..80efd32 --- /dev/null +++ b/IBMBIO/PSP.DEF @@ -0,0 +1,108 @@ +; File : $PSP.DEF$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG + +; Program Segment Prefix +; ---------------------- +; This structure holds vital information for DOS programs +; +;******************************************************************************* +;* +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 00 | int 20 | memory | *** | jmpf|longjmp off| +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 08 |longjmp seg| int22 Off | int22 Seg | int22 Off | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 10 | int22 Seg | int24 Off | int24 Seg | Parent | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 18 | Default Handle Table | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 20 | XFT (20 entries) | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 28 | XFT contd. | Environ | User SP | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 30 | User SS | xfnmax | xftoff | xftseg | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 38 | res1 | res2 | ric | *** | ********* | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 40 | version | ********* | ********* | ********* | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 48 | ********* | ********* | ********* | ********* | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 50 | int 21 | retf| *** | ********* | ********* | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 58 | ********* | ********* | PSP fcb 1 | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ + +PSP_INT20 equ es:word ptr .0000h +PSP_MEMORY equ es:word ptr .0002h +;PSP_??? equ es:byte ptr .0004h +PSP_LONGCALL equ es:byte ptr .0005h +PSP_LONGOFF equ es:word ptr .0006h +PSP_LONGSEG equ es:word ptr .0008h +PSP_TERM_IP equ es:word ptr .000Ah +PSP_TERM_CS equ es:word ptr .000Ch +PSP_BREAK_IP equ es:word ptr .000Eh +PSP_BREAK_CS equ es:word ptr .0010h +PSP_ERROR_IP equ es:word ptr .0012h +PSP_ERROR_CS equ es:word ptr .0014h +PSP_PARENT equ es:word ptr .0016h +PSP_XFT equ es:byte ptr .0018h +; +; The Default Handle Table is HERE !! +; +PSP_ENVIRON equ es:word ptr .002ch +PSP_USERSP equ es:word ptr .002eh +PSP_USERSS equ es:word ptr .0030h +PSP_XFNMAX equ es:word ptr .0032h +PSP_XFTPTR equ es:dword ptr .0034h +PSP_XFTOFF equ es:word ptr .0034h +PSP_XFTSEG equ es:word ptr .0036h +PSP_RES1 equ es:word ptr .0038h ; DOS Reserved 0FFFFh +PSP_RES2 equ es:word ptr .003Ah ; DOS Reserved 0FFFFh +PSP_RIC equ es:byte ptr .003Ch ; Return Interim Character flag +PSP_VERSION equ es:word ptr .0040h ; DOS version number + + +PSP_DOSCALL equ es:word ptr .0050h +PSP_DOSRETF equ es:byte ptr .0052h + +PSP_FCB1 equ es:byte ptr .005Ch +PSP_FCB2 equ es:byte ptr .006Ch +PSP_COMLEN equ es:byte ptr .0080h +PSP_COMLINE equ es:byte ptr .0081h + +XFNMAX equ 20 + +PSPLEN equ 100h +PSPILEN equ 60h diff --git a/IBMBIO/REQHDR.EQU b/IBMBIO/REQHDR.EQU new file mode 100644 index 0000000..52d96d3 --- /dev/null +++ b/IBMBIO/REQHDR.EQU @@ -0,0 +1,167 @@ +; File : $REQHDR.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG + + +CMD_INIT equ 0 ; Initialize the Device Driver +CMD_MEDIA_CHECK equ 1 ; Request Media Check +CMD_BUILD_BPB equ 2 ; Build Drive BPB +CMD_INPUT_IOCTL equ 3 ; IOCTL input +CMD_INPUT equ 4 ; Input +CMD_INPUT_NOWAIT equ 5 ; Non destructive input no wait +CMD_INPUT_STATUS equ 6 ; Input status +CMD_INPUT_FLUSH equ 7 ; Input flush +CMD_OUTPUT equ 8 ; Output +CMD_OUTPUT_VERIFY equ 9 ; Output with verify +CMD_OUTPUT_STATUS equ 10 ; Output status +CMD_OUTPUT_FLUSH equ 11 ; Output flush +CMD_OUTPUT_IOCTL equ 12 ; IOCTL output +CMD_DEVICE_OPEN equ 13 ; Device OPEN +CMD_DEVICE_CLOSE equ 14 ; Device CLOSE +CMD_FIXED_MEDIA equ 15 ; Removeable Media Check +CMD_GENERIC_IOCTL equ 19 ; Generic IOCTL +CMD_GET_DEVICE equ 23 ; Get the Logical Device +CMD_SET_DEVICE equ 24 ; Set the Logical Device +CMD_QUERY_IOCTL equ 25 ; query ioctl support + +; Generic Request Header Format + +RH_LEN equ es:byte ptr 0[bx] +RH_UNIT equ es:byte ptr 1[bx] +RH_CMD equ es:byte ptr 2[bx] +RH_STATUS equ es:word ptr 3[bx] + RHS_DONE equ 0100h + RHS_BUSY equ 0200h + RHS_IC equ 0400h ; Interim Character + RHS_RM equ 0800h + RHS_ERROR equ 8000h + +;****** +;* No longer safe to use - some device drivers trample on them.... +;* +;* RH_STRATEGY equ es:dword ptr 5[bx] ; Device Strategy Routine +;* RH_STRATOFF equ es:word ptr 5[bx] ; Strategy Offset +;* RH_STRATSEG equ es:word ptr 7[bx] ; Strategy Segment +;* RH_INTERRUPT equ es:dword ptr 9[bx] ; Device Interrupt Routine +;* RH_INTOFF equ es:word ptr 9[bx] ; Intterupt Offset +;* RH_INTSEG equ es:word ptr 11[bx] ; Interrupt Segment +;***** + +; Request header for initialization + +RH0_NUNITS equ es:byte ptr 13[bx] +RH0_RESIDENT equ es:word ptr 14[bx] +RH0_BPBOFF equ es:word ptr 18[bx] +RH0_BPBSEG equ es:word ptr 20[bx] +RH0_DRIVE equ es:byte ptr 22[bx] +RH0_LEN equ 22 + +; Request header for media check + +RH1_MEDIA equ es:byte ptr 13[bx] ; BDOS: current media byte +RH1_RETURN equ es:byte ptr 14[bx] ; driver: return code (00, 01, FF) +RH1_VOLID equ es:dword ptr 15[bx] ; driver: volume label address +RH1_LEN equ 15 + +; Request header for "build BPB" + +RH2_MEDIA equ es:byte ptr 13[bx] ; BDOS or driver? +RH2_BUFFER equ es:dword ptr 14[bx] ; BDOS: scratch buffer for driver use +RH2_BPB equ es:dword ptr 18[bx] ; same as the following: +RH2_BPBOFF equ es:word ptr 18[bx] ; driver: address of new BPB +RH2_BPBSEG equ es:word ptr 20[bx] +RH2_LEN equ 24 + +; Request header for input/output + +RH4_MEDIA equ es:byte ptr 13[bx] ; BDOS: current media byte +RH4_RIC equ es:byte ptr 13[bx] ; BDOS: Return Interim Char flg +RH4_BUFFER equ es:dword ptr 14[bx] ; BDOS: disk transfer address +RH4_BUFOFF equ es:word ptr 14[bx] ; BDOS: Buffer Offset +RH4_BUFSEG equ es:word ptr 16[bx] ; BDOS: Buffer Segment +RH4_COUNT equ es:word ptr 18[bx] ; BDOS: sector count +RH4_SECTOR equ es:word ptr 20[bx] ; BDOS: starting sector +RH4_VOLID equ es:dword ptr 22[bx] ; driver: volume if illegal disk change +RH4_BIGSECTOR equ es:dword ptr 26[bx] +RH4_BIGSECTORLO equ es:word ptr 26[bx] +RH4_BIGSECTORHI equ es:word ptr 28[bx] + +RH4_LEN equ 30 + +; Request Header for Non-Destructive Input + +RH5_CHAR equ es:byte ptr 13[bx] ; Character Read from Device +RH5_RIC equ es:byte ptr 13[bx] ; BDOS: Return Interim Char flg +RH5_LEN equ 14 + +; Request Header for Device Open + +RH13_LEN equ 13 + +; Request Header for Device Close + +RH14_LEN equ 13 + +; Request header for generic IOCTL + +RH19_CATEGORY equ es:word ptr 13[bx] ; BDOS: major/minor function number +RH19_MAJOR equ es:byte ptr 13[bx] ; BDOS: Major Function Number +RH19_MINOR equ es:byte ptr 14[bx] ; BDOS: Minor Function Number +RH19_SI equ es:word ptr 15[bx] ; BDOS: User SI +RH19_DI equ es:word ptr 17[bx] ; BDOS: User DI +RH19_GENPB equ es:dword ptr 19[bx] ; BDOS: extra parameters +RH19_LEN equ 23 + +RQ19_SET equ 40h ; set device parameters +RQ19_GET equ 60h ; get device parameters +RQ19_WRITE equ 41h ; write tracks +RQ19_READ equ 61h ; read tracks +RQ19_FORMAT equ 42h ; format tracks +RQ19_VERIFY equ 62h ; verify tracks + +RQ19_PRP_START equ 4Ch ; start of codepage prepare +RQ19_PRP_END equ 4Dh ; end of codepage prepare +RQ19_SELECT equ 4Ah ; select code page +RQ19_QRY_SEL equ 6Ah ; query selected code page +RQ19_QRY_PRP equ 6Bh ; query prepared code page(s) +RQ19_DSP_SET equ 5Fh ; set display information +RQ19_DSP_GET equ 7Fh ; get display information + +; Request header for get/set drive + +RH24_CMD equ es:byte ptr 14[bx] ; BDOS: Command Code +RH24_STATUS equ es:word ptr 15[bx] ; BDOS: Status +RH24_RESVD equ es:dword ptr 17[bx] ; BDOS: Reserved +RH24_LEN equ 21 + +RH_SIZE equ 30 ; maximum size of request header diff --git a/IBMBIO/REQUEST.EQU b/IBMBIO/REQUEST.EQU new file mode 100644 index 0000000..fba0aeb --- /dev/null +++ b/IBMBIO/REQUEST.EQU @@ -0,0 +1,193 @@ +; File : $REQUEST.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; ENDLOG + + +P_DSTRUC struc + dw ? +REQUEST dd ? +P_DMA dd ? +P_DSTRUC ends + +P_STRUC struc + dw ? ; saved BP +REQUEST_OFF dw ? ; request header offset +REQUEST_SEG dw ? ; request header segment +P_DMAOFF dw ? ; transfer offset +P_DMASEG dw ? ; transfer segment +P_RETRY db ? ; retry count for disk errors +P_DIRECT db ? ; 0 if DMA deblocking required +P_ROSCMD db ? ; 2 = read, 3 = write, 4 = verify +P_SETTLE db ? ; for fast settle on reads +P_SECTOR db ? ; sector # (0..BPB_SPT-1) +P_HEAD db ? ; head # (0..BPB_HEADS-1) +P_CYL dw ? ; cylinder # (0..1023) +P_COUNT dw ? ; requested sector count +P_MCNT dw ? ; physical sector count +P_STRUC ends + + + +CMD_INIT equ 0 ; Initialize the Device Driver +CMD_MEDIA_CHECK equ 1 ; Request Media Check +CMD_BUILD_BPB equ 2 ; Build Drive BPB +CMD_INPUT_IOCTL equ 3 ; IOCTL input +CMD_INPUT equ 4 ; Input +CMD_INPUT_NOWAIT equ 5 ; Non destructive input no wait +CMD_INPUT_STATUS equ 6 ; Input status +CMD_INPUT_FLUSH equ 7 ; Input flush +CMD_OUTPUT equ 8 ; Output +CMD_OUTPUT_VERIFY equ 9 ; Output with verify +CMD_OUTPUT_STATUS equ 10 ; Output status +CMD_OUTPUT_FLUSH equ 11 ; Output flush +CMD_OUTPUT_IOCTL equ 12 ; IOCTL output +CMD_DEVICE_OPEN equ 13 ; Device OPEN +CMD_DEVICE_CLOSE equ 14 ; Device CLOSE +CMD_FIXED_MEDIA equ 15 ; Removeable Media Check +CMD_GENERIC_IOCTL equ 19 ; Generic IOCTL +CMD_GET_DEVICE equ 23 ; Get the Logical Device +CMD_SET_DEVICE equ 24 ; Set the Logical Device +CMD_QUERY_IOCTL equ 25 ; query ioctl support + +; Generic Request Header Format + +RH_LEN equ byte ptr 0 +RH_UNIT equ byte ptr 1 +RH_CMD equ byte ptr 2 +RH_STATUS equ word ptr 3 + RHS_DONE equ 0100h + RHS_BUSY equ 0200h + RHS_IC equ 0400h ; Interim Character + RHS_RM equ 0800h + RHS_ERROR equ 8000h + +;****** +;* No longer safe to use - some device drivers trample on them.... +;* +;* RH_STRATEGY equ dword ptr 5 ; Device Strategy Routine +;* RH_STRATOFF equ word ptr 5 ; Strategy Offset +;* RH_STRATSEG equ word ptr 7 ; Strategy Segment +;* RH_INTERRUPT equ dword ptr 9 ; Device Interrupt Routine +;* RH_INTOFF equ word ptr 9 ; Intterupt Offset +;* RH_INTSEG equ word ptr 11 ; Interrupt Segment +;***** + +; Request header for initialization + +RH0_NUNITS equ byte ptr 13 +RH0_RESIDENT equ word ptr 14 +RH0_BPBOFF equ word ptr 18 +RH0_BPBSEG equ word ptr 20 +RH0_DRIVE equ byte ptr 22 +RH0_LEN equ 22 + +; Request header for media check + +RH1_MEDIA equ byte ptr 13 ; BDOS: current media byte +RH1_RETURN equ byte ptr 14 ; driver: return code (00, 01, FF) +RH1_VOLID equ dword ptr 15 ; driver: volume label address +RH1_LEN equ 15 + +; Request header for "build BPB" + +RH2_MEDIA equ byte ptr 13 ; BDOS or driver? +RH2_BUFFER equ dword ptr 14 ; BDOS: scratch buffer for driver use +RH2_BPB equ dword ptr 18 ; same as the following: +RH2_BPBOFF equ word ptr 18 ; driver: address of new BPB +RH2_BPBSEG equ word ptr 20 +RH2_LEN equ 24 + +; Request header for input/output + +RH4_MEDIA equ byte ptr 13 ; BDOS: current media byte +RH4_RIC equ byte ptr 13 ; BDOS: Return Interim Char flg +RH4_BUFFER equ dword ptr 14 ; BDOS: disk transfer address +RH4_BUFOFF equ word ptr 14 ; BDOS: Buffer Offset +RH4_BUFSEG equ word ptr 16 ; BDOS: Buffer Segment +RH4_COUNT equ word ptr 18 ; BDOS: sector count +RH4_SECTOR equ word ptr 20 ; BDOS: starting sector +RH4_VOLID equ dword ptr 22 ; driver: volume if illegal disk change +RH4_BIGSECTOR equ dword ptr 26 +RH4_BIGSECTORLO equ word ptr 26 +RH4_BIGSECTORHI equ word ptr 28 + +RH4_LEN equ 30 + +; Request Header for Non-Destructive Input + +RH5_CHAR equ byte ptr 13 ; Character Read from Device +RH5_RIC equ byte ptr 13 ; BDOS: Return Interim Char flg +RH5_LEN equ 14 + +; Request Header for Device Open + +RH13_LEN equ 13 + +; Request Header for Device Close + +RH14_LEN equ 13 + +; Request header for generic IOCTL + +RH19_CATEGORY equ word ptr 13 ; BDOS: major/minor function number +RH19_MAJOR equ byte ptr 13 ; BDOS: Major Function Number +RH19_MINOR equ byte ptr 14 ; BDOS: Minor Function Number +RH19_SI equ word ptr 15 ; BDOS: User SI +RH19_DI equ word ptr 17 ; BDOS: User DI +RH19_GENPB equ dword ptr 19 ; BDOS: extra parameters +RH19_LEN equ 23 + +RQ19_SET equ 40h ; set device parameters +RQ19_GET equ 60h ; get device parameters +RQ19_WRITE equ 41h ; write tracks +RQ19_READ equ 61h ; read tracks +RQ19_FORMAT equ 42h ; format tracks +RQ19_VERIFY equ 62h ; verify tracks +RQ19_SETMEDIA equ 46h ; set media ID +RQ19_GETMEDIA equ 66h ; get media ID + +RQ19_PRP_START equ 4Ch ; start of codepage prepare +RQ19_PRP_END equ 4Dh ; end of codepage prepare +RQ19_SELECT equ 4Ah ; select code page +RQ19_QRY_SEL equ 6Ah ; query selected code page +RQ19_QRY_PRP equ 6Bh ; query prepared code page(s) +RQ19_DSP_SET equ 5Fh ; set display information +RQ19_DSP_GET equ 7Fh ; get display information + +; Request header for get/set drive + +RH24_CMD equ byte ptr 14 ; BDOS: Command Code +RH24_STATUS equ word ptr 15 ; BDOS: Status +RH24_RESVD equ dword ptr 17 ; BDOS: Reserved +RH24_LEN equ 21 + +RH_SIZE equ 30 ; maximum size of request header diff --git a/IBMBIO/SERPAR.ASM b/IBMBIO/SERPAR.ASM new file mode 100644 index 0000000..c6d703f --- /dev/null +++ b/IBMBIO/SERPAR.ASM @@ -0,0 +1,332 @@ +; File : $Workfile: SERPAR.ASM$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; SERPAR.ASM 1.7 93/07/22 19:44:27 +; switch over to REQUEST.EQU +; SERPAR.ASM 1.6 93/07/19 18:57:59 +; Add header +; +; ENDLOG + + include BIOSGRPS.EQU + include DRMACROS.EQU ; standard DR macros + include IBMROS.EQU ; ROM BIOS equates + include REQUEST.EQU ; request header equates + include DRIVER.EQU ; device driver equates + +page +CGROUP group CODE, RCODE, ICODE + +CG equ offset CGROUP + + Assume CS:CGROUP, DS:CGROUP, ES:CGROUP, SS:CGROUP + +CODE segment 'CODE' + + extrn endbios:word ; for device driver INIT function + extrn serparFlag:byte + extrn serparChar:byte + +CODE ends + +RCODE segment 'RCODE' + + Public SerParCommonTable + +SerParCommonTable: + db 19 ; Last supported function + dw CG:dd_init ; 0-initialize driver + dw CG:dd_error ; 1-media change check (disks only) + dw CG:dd_error ; 2-build BPB (disks only) + dw CG:dd_error ; 3-IOCTL string input + dw CG:dd_input ; 4-input + dw CG:dd_poll ; 5-nondestructive input (char only) + dw CG:dd_instat ; 6-input status (char only) + dw CG:dd_inflush ; 7-input flush + dw CG:dd_output ; 8-output + dw CG:dd_output ; 9-output with verify + dw CG:dd_outstat ; 10-output status (char only) + dw CG:dd_outflush ; 11-output flush (char only) + dw CG:dd_error ; 12-IOCTL string output + dw CG:dd_open ; 13-device open + dw CG:dd_close ; 14-device close + dw CG:dd_error ; 15-removable media check (disks only) + dw CG:dd_error ; 16-n/a + dw CG:dd_error ; 17-n/a + dw CG:dd_error ; 18-n/a + dw CG:dd_genioctl ; 19-generic IOCTL + + + Assume DS:CGROUP, ES:Nothing, SS:Nothing + +page +driver proc near + +dd_error: ; used for all unsupported driver functions +;-------- + mov ax,RHS_ERROR+3 ; "invalid command" error + ret + + page + +poll_char: +;--------- +; exit: ZF = 1 => no character ready +; ZF = 0 => AL = character + + cmp serparFlag[si],TRUE ; do we have local character? + jne poll_c2 ; skip if not + mov al,serparChar[si] ; get the local charcater + jmps poll_c4 ; and return it +poll_c2: ; need to check ROS keyboard status + mov ah,3 ; get serial status status + int ASYNC_INT ; read serial status + test ah,1 ; test "received data" bit + jz poll_c9 ; skip if no character there + mov ah,2 ; read the character + int ASYNC_INT ; character returned in AL + mov serparChar[si],al ; save it for look ahead + mov serparFlag[si],TRUE ; we've got a local character +poll_c4: ; return the character in AL + or ah,TRUE ; indicate "ready" status + ret +poll_c9: + sub ax,ax ; indicate "not-ready" status + ret ; (driver is busy) + + +char_read: +;--------- + xor ax,ax + cmp serparFlag[si],TRUE ; do we have local character? + jne rdchr1 + mov serparFlag[si],FALSE ; tell them buffer is invalid + mov al,serparChar[si] ; get the local character + ret ; and return it +rdchr1: + mov ah,2 ; read character from serial port + int ASYNC_INT ; call the ROM BIOS + and ah,0eh ; only worry about these error bits + ret ; and return the character + + page +dd_input: ; 4-input +;-------- + push es ; save ES (-> request header!) + mov cx,es:RH4_COUNT[bx] ; get # of characters to output + jcxz input9 ; return if nothing to input + sub dx,3 ; convert to serial port # + jb input9 ; return none read if parallel port + mov si,dx ; SI = serial port index + les di,es:RH4_BUFFER[bx] ; get address of string to input +input2: + call char_read ; read 8-bit character + test ah,ah ; did we read OK ? + jnz input9 ; if we have an error stop now + stosb ; store it in input buffer + loop input2 ; repeat for all characters +input9: + pop es + sub es:RH4_COUNT[bx],cx ; update to actual number xfered + sub ax,ax + ret + +dd_poll: ; 5-nondestructive input (console only) +;------- + cmp dx,3 ; check if a parallel port + jb poll_busy ; they are never ready + sub dx,3 + mov si,dx ; SI = serial port index + call poll_char ; check keyboard status + jz poll_busy + mov es:RH5_CHAR[bx],al ; return the character + sub ax,ax + ret +poll_busy: + mov ax,RHS_BUSY ; indicate no character waiting + ret + +dd_instat: ; 6-input status (char only) +;--------- + cmp dx,3 ; check if a parallel port + jb poll_busy ; if so it's always busy + sub dx,3 + mov si,dx ; SI = serial port index + call poll_char ; check keyboard status + jz poll_busy + sub ax,ax ; indicate "not ready" status + ret + +dd_inflush: ; 7-input flush +;--------- + cmp dx,3 ; check if a parallel port + jae inflsh1 ; skip if serial port + mov ax,RHS_ERROR+11 ; return "read error" if attempting + ret ; to read from the parallel port +inflsh1: + sub dx,3 + mov si,dx ; SI = serial port index +inflsh2: + call poll_char ; check keyboard status + jz inflsh_ret ; skip if not ready + call char_read ; else read next character + jmps inflsh2 ; repeat until buffer empty +inflsh_ret: ; keyboard buffer empty + sub ax,ax ; return success + ret + +dd_output: ; 8-output +;--------- + mov cx,es:RH4_COUNT[bx] ; get # of characters to output + jcxz output5 ; return if nothing to output + push es ; save ES (-> request header!) + les si,es:RH4_BUFFER[bx] ; get address of string to output + sub dx,3 ; test if parallel port + jae output2 ; skip if serial port + add dx,3 ; back to parallel port number +output1: + lods es:byte ptr [si] ; get next character to output + mov ah,0 ; output AL to parallel port + int PRINTER_INT ; output to parallel port + mov al,2 ; "not ready" error + test ah,PRN_TIMEOUT ; printer not ready? + jnz output4 ; yes, return error + mov al,9 ; "printer out of paper" error + test ah,PRN_PAPER ; printer out paper? + jnz output4 ; yes, return error + inc ax ; "write fault" error + test ah,PRN_ERROR ; test if other errors + jnz output4 ; skip if any errors occurred + loop output1 ; else repeat for all characters + jmps output4 ; return successfully when done + +output2: ; output is for serial port + lods es:byte ptr [si] ; get next character to output + mov ah,1 ; output AL to serial port + int ASYNC_INT ; output to serial port + mov al,2 ; "not ready" error + test ah,AUX_ERROR ; test if time out etc. + jnz output4 ; skip if any errors occurred + loop output2 ; else repeat for all characters +output4: + mov ah,RHS_ERROR shr 8 ; assume an error code + pop es + sub es:RH4_COUNT[bx],cx ; update to actual number xfered + jz output6 ; none xfered is an error +output5: + sub ax,ax ; return successfully when done +output6: + ret + + + +dd_outstat: ; 10-output status (char only) +;---------- + cmp dx,3 ; test if parallel port + jae outstat1 + mov ah,2 ; read parallel port status + int PRINTER_INT ; call the ROM BIOS + test ah,80h ; test "not busy" bit + jnz outstat_ready ; if not busy then ready for output + jmps outstat_busy ; else we must be still busy +outstat1: + sub dx,3 + mov ah,3 ; get status for serial port + int ASYNC_INT + test ah,20h ; transmit buffer register emmpty? + jz outstat_busy + test al,20h ; data set ready? + jz outstat_busy +outstat_ready: + sub ax,ax ; always ready, return no busy + ret +outstat_busy: + mov ax,RHS_BUSY + ret + +dd_outflush: ; 11-output flush (char only) +;----------- + sub ax,ax ; unbuffered, perform no operation + ret + + + page +dd_open: ; 13-device open +;------- + sub ax,ax ; no operation + ret + + +dd_close: ; 14-device close +;-------- + sub ax,ax ; no operation + ret + + + page +dd_genioctl: ; 19-generic IOCTL +;----------- + sub ax,ax + ret + +driver endp + +RCODE ends ; end of device driver code + +page + +ICODE segment 'ICODE' ; initialization code + +dd_init: ; 0-initialize driver +;------- + cmp dx,3 ; check if serial or parallel + jae init1 ; skip if serial port setup + mov ah,1 ; initialize parallel port + int PRINTER_INT ; call the ROM BIOS + jmps init2 +init1: + sub dx,3 + mov ah,0 ; initialize serial port + mov al,0A3h ; 2400 Bd, no parity, 8 data, 1 stop + int ASYNC_INT ; call the ROM BIOS +init2: + les bx,REQUEST[bp] ; ES:BX -> request header + + mov ax,endbios + mov es:RH0_RESIDENT[bx],ax ; set end of device driver + mov es:RH0_RESIDENT+2[bx],ds + + sub ax,ax ; initialization succeeded + ret ; (BIOS init always does...) + +ICODE ends + + end diff --git a/IBMBIO/STACKS.ASM b/IBMBIO/STACKS.ASM new file mode 100644 index 0000000..fe4dd90 --- /dev/null +++ b/IBMBIO/STACKS.ASM @@ -0,0 +1,365 @@ +; File : $STACKS.ASM$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; STACKS.ASM 1.6 93/10/26 19:08:13 +; Fix bug when we run out of stacks +; STACKS.ASM 1.4 93/09/02 22:36:47 +; Add header to system allocations +; ENDLOG + +CGROUP group INITCODE, STACKS + +STACKS segment public para 'STACKS' + + Assume CS:STACKS, DS:Nothing, ES:Nothing, SS:Nothing + +StackCode: + +;************ +; FIXED DATA +;************ + + dw 0 +NumOfStacks dw 0 ; we have this many stacks +StackCB dw 0 ; NumOfStacks*8 = size of control array +StackSize dw 0 ; size of an individual stack +StackPtr label dword ; pointer to stack data +StackOff dw offset STACKS:StackHeap +StackSeg dw 0 +FirstStack dw offset STACKS:StackHeap +LastStack dw offset STACKS:StackHeap-STACK_CB_SIZE +NextStack dw offset STACKS:StackHeap-STACK_CB_SIZE + +;************ +; FIXED DATA +;************ + +STACK_CB_FLAGS equ word ptr 0 ; stack flags +STACK_CB_SP equ word ptr 2 ; old stack saved here +STACK_CB_SS equ word ptr 4 +STACK_CB_TOP equ word ptr 6 ; stack top lives here +STACK_CB_SIZE equ 8 + +STACK_FREE equ 0 ; stack is available to allocate +STACK_INUSE equ 1 ; stack is in use +STACK_OVERFLOW equ 2 ; stack has overflowed + +; +; Our hardware interrupt handlers which are of the form +; +; call SwapStack +; db 0EAh ; JMPF opcode +; dd oldIntHandler +; +; By looking at the near return address we can find the address of the old +; interrupt handler. +; We try to allocate a stack from our pool of stacks, working downward to +; reduce the problems of stack overflow. +; +; We check the top of the stack contains a pointer to our control block and +; if this is invalid we assume the stack has overflowed, and try the next one. +; We have no way of recovering a stack that has overflowed (eg. by zapping +; everything below us on exit). +; +; If we run out of stacks we just continue on the callers stack, rather than +; halting the system. +; + +Int02: + call SwapStack + db 0EAh ; JMPF +i02Off dw 4*02h,0 + +Int08: + call SwapStack + db 0EAh ; JMPF +i08Off dw 4*08h,0 + +Int09: + call SwapStack + db 0EAh +i09Off dw 4*09h,0 + +Int0A: + call SwapStack + db 0EAh ; JMPF +i0AOff dw 4*0Ah,0 + +Int0B: + call SwapStack + db 0EAh ; JMPF +i0BOff dw 4*0Bh,0 + +Int0C: + call SwapStack + db 0EAh ; JMPF +i0COff dw 4*0Ch,0 + +Int0D: + call SwapStack + db 0EAh ; JMPF +i0DOff dw 4*0Dh,0 + +Int0E: + call SwapStack + db 0EAh ; JMPF +i0EOff dw 4*0Eh,0 + +Int70: + call SwapStack + db 0EAh ; JMPF +i70Off dw 4*70h,0 + +Int72: + call SwapStack + db 0EAh ; JMPF +i72Off dw 4*72h,0 + +Int73: + call SwapStack + db 0EAh ; JMPF +i73Off dw 4*73h,0 + +Int74: + call SwapStack + db 0EAh ; JMPF +i74Off dw 4*74h,0 + +Int76: + call SwapStack + db 0EAh ; JMPF +i76Off dw 4*76h,0 + +Int77: + call SwapStack + db 0EAh ; JMPF +i77Off dw 4*77h,0 + +SwapStack proc near +; On Entry: +; As per INT except word on stack from near call, which gives old vector +; On Exit: +; None +; + cli ; just in case + push bp + push si ; save work registers + mov si,cs:NextStack ; start looking here for a stack +SwapStack10: + cmp cs:STACK_CB_FLAGS[si],STACK_FREE + jne SwapStack20 ; use this stack if possible + mov bp,cs:STACK_CB_TOP[si] ; get the top of this stack + cmp si,cs:word ptr [bp] ; does the check match ? + jne SwapStack20 ; no, try the next one + mov cs:NextStack,si ; remember where we are + mov cs:STACK_CB_FLAGS[si],STACK_INUSE + mov cs:STACK_CB_SS[si],ss ; save old stack + mov cs:STACK_CB_SP[si],sp + + mov bp,sp + xchg bx,ss:word ptr 4[bp] ; BX = return address, BX saved + + mov bp,cs + mov ss,bp + mov sp,cs:STACK_CB_TOP[si] ; switch stacks + pushf + call cs:dword ptr 1[bx] ; fake an INT to old handler + mov ss,cs:STACK_CB_SS[si] + mov sp,cs:STACK_CB_SP[si] ; swap back to the original stack + mov cs:STACK_CB_FLAGS[si],STACK_FREE + mov cs:NextStack,si ; update in case we were nested + pop si ; restore registers + pop bp + pop bx ; (was return address, now saved BX) + iret ; exit interrupt handler + +SwapStack20: + sub si,STACK_CB_SIZE ; it's not, so try the next + cmp si,cs:FirstStack ; if there is one + jae SwapStack10 + pop si ; restore registers + pop bp + ret ; back to JMPF as we can't swap stacks + +SwapStack endp + +i19Table dw 4*02H, offset STACKS:i02Off + dw 4*08H, offset STACKS:i08Off + dw 4*09H, offset STACKS:i09Off + dw 4*0AH, offset STACKS:i0AOff + dw 4*0BH, offset STACKS:i0BOff + dw 4*0CH, offset STACKS:i0COff + dw 4*0DH, offset STACKS:i0DOff + dw 4*0EH, offset STACKS:i0EOff + dw 4*70H, offset STACKS:i70Off + dw 4*72H, offset STACKS:i72Off + dw 4*73H, offset STACKS:i73Off + dw 4*74H, offset STACKS:i74Off + dw 4*76H, offset STACKS:i76Off + dw 4*77H, offset STACKS:i77Off + dw 0 + +Int19: +; Trap the Int 19 reboot and restore any hardware vectors we have hooked + cli + cld + xor ax,ax + mov es,ax ; ES = interrupt vectors + push cs + pop ds + lea si,i19Table ; DS:SI -> table to restore +Int1910: + lodsw + xchg ax,di ; ES:DI -> address to restore to + lodsw + xchg ax,si ; CS:SI -> value to restore + movsw + movsw + xchg ax,si ; restore position in table + cmp ds:word ptr [si],0 + jne Int1910 + db 0EAh ; JMPF +i19Off dw 4*19h,0 + + even ; word align our stacks + +StackHeap label word ; dynamically build stack CB's here + +RELOCATE_SIZE equ ($ - StackCode) + +STACKS ends + +INITCODE segment public para 'INITCODE' + + Assume CS:CGROUP, DS:CGROUP, ES:Nothing, SS:Nothing + + extrn alloc_hiseg:near + + Public InitStacks +;========== +InitStacks: +;========== +; On Entry: +; CX = number of stacks +; DX = size of stack +; Values are checked +; On Exit: +; None +; + push ds + push es + inc dx ; let's ensure stacks are WORD + and dx,0FFFEh ; aligned... + mov NumOfStacks,cx + mov StackSize,dx + mov ax,STACK_CB_SIZE + mul cx ; AX = bytes in control area + mov StackCB,ax + add LastStack,ax + add NextStack,ax + add StackOff,ax ; adjust our pointers + xchg ax,cx ; AX = NumOfStacks + mul StackSize ; AX bytes are required for stacks + add ax,StackOff ; add to start of stacks + push ax ; save length in bytes + add ax,15 ; allow for rounding + mov cl,4 + shr ax,cl ; convert it to para's + mov dl,'S' ; allocation signature is Stacks + call alloc_hiseg ; allocate some memory + pop cx ; CX = length in bytes + mov StackSeg,ax ; remember where + mov es,ax + Assume ES:STACKS + xor di,di + mov al,0CCh ; fill stacks with CC for debug + rep stosb + xor di,di + mov si,offset CGROUP:StackCode + mov cx,RELOCATE_SIZE + rep movsb ; relocate the code + + mov bx,FirstStack ; lets start building the CB's + mov cx,NumOfStacks + lds si,StackPtr ; SI = bottom of stack area + Assume DS:STACKS + sub si,WORD ; we want the word below top of stack +InitStacks10: + add si,StackSize ; SI = top of stack + mov ds:STACK_CB_FLAGS[bx],STACK_FREE + mov ds:STACK_CB_TOP[bx],si ; set top of stack + mov ds:word ptr [si],bx ; set backlink + add bx,STACK_CB_SIZE ; onto next control block + loop InitStacks10 + + xor ax,ax + mov ds,ax + Assume DS:Nothing + cli + mov si,offset CGROUP:iTable ; now we fixup the vectors +InitStacks20: + mov ax,cs:word ptr 0[si] ; ES:AX = entry point + mov di,cs:word ptr 2[si] ; ES:DI = fixup location + mov bx,es:word ptr [di] ; get the vector to fixup + xchg ax,ds:word ptr [bx] ; set entry offset while saving + stosw ; previous handler offset + mov ax,es + xchg ax,ds:word ptr 2[bx] ; now the segment + stosw + add si,2*WORD ; onto next entry + cmp cs:word ptr 0[si],0 ; (zero terminated) + jnz InitStacks20 + sti +InitStacks30: + pop es + pop ds + ret + +iTable dw offset STACKS:Int02, offset STACKS:i02Off + dw offset STACKS:Int08, offset STACKS:i08Off + dw offset STACKS:Int09, offset STACKS:i09Off + dw offset STACKS:Int0A, offset STACKS:i0AOff + dw offset STACKS:Int0B, offset STACKS:i0BOff + dw offset STACKS:Int0C, offset STACKS:i0COff + dw offset STACKS:Int0D, offset STACKS:i0DOff + dw offset STACKS:Int0E, offset STACKS:i0EOff + dw offset STACKS:Int70, offset STACKS:i70Off + dw offset STACKS:Int72, offset STACKS:i72Off + dw offset STACKS:Int73, offset STACKS:i73Off + dw offset STACKS:Int74, offset STACKS:i74Off + dw offset STACKS:Int76, offset STACKS:i76Off + dw offset STACKS:Int77, offset STACKS:i77Off + dw offset STACKS:Int19, offset STACKS:i19Off + dw 0 + +INITCODE ends + + end diff --git a/IBMBIO/UDSC.EQU b/IBMBIO/UDSC.EQU new file mode 100644 index 0000000..ebd3051 --- /dev/null +++ b/IBMBIO/UDSC.EQU @@ -0,0 +1,64 @@ +; File : $UDSC.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; ENDLOG + + +UDSC_BPB_LENGTH equ 25 + +UDSC struc +UDSC_NEXT dd ? ; link to next UDSC_ +UDSC_RUNIT db ? ; ROS drive number (0/1/80/81) +UDSC_DRIVE db ? ; logical drive +UDSC_BPB db UDSC_BPB_LENGTH dup (?) ; current BPB +UDSC_FATFLAG db ? +UDSC_OPNCNT dw ? ; # of files open on drive +UDSC_TYPE db ? ; floppy drive type (0/1/2/7) +UDSC_FLAGS dw ? ; various flags for drive +UDSC_NCYL dw ? ; # of cylinders per drive +UDSC_DEVBPB db UDSC_BPB_LENGTH dup (?) ; device BPB + db 7 dup (?) +UDSC_TIMER dw 2 dup (?) ; tick count for MEDCHK +UDSC_LABEL db 12 dup (?) ; ASCIIZ volume label +UDSC_SERIAL dd ? ; serial number +UDSC_FSTYPE db 9 dup (?) ; ASCIIZ "FAT12"/"FAT16" type +UDSC ends + +UDSC_LENGTH equ size UDSC + +UDF_HARD equ 0001h ; drive is a hard disk +UDF_CHGLINE equ 0002h ; drive support disk change line +UDF_UNSURE equ 0004h ; drive has just been formatted +UDF_VFLOPPY equ 0010h ; drive shares physical drive +UDF_OWNER equ 0020h ; logical drive "owns" physical drive +UDF_MEDIA equ 0100h ; media id is from bootsec, not default + +MAXPART equ 26 ; support up 26 drives diff --git a/IBMDOS/BDEVIO.A86 b/IBMDOS/BDEVIO.A86 new file mode 100644 index 0000000..3573608 --- /dev/null +++ b/IBMDOS/BDEVIO.A86 @@ -0,0 +1,1474 @@ +title 'BDEVIF - Block DEVice Input/Output support' +; File : $BDEVIO.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; BDEVIO.A86 1.27 94/11/30 16:25:22 +; added delayed retry for read/write to locked region +; added support for using multiple FAT copies on reads if one fails; +; BDEVIO.A86 1.26 94/02/22 17:11:25 +; Fix where corrupt dir entry results in read beyond end-of-chain (Filelink bug) +; BDEVIO.A86 1.25 93/12/15 03:07:11 +; New ddioif entry point so Int 25/26 bypasses address normalisation +; BDEVIO.A86 1.24 93/12/08 03:15:14 +; Force rebuild_ldt_root if root in JOIN's subdirectory +; BDEVIO.A86 1.23 93/11/19 18:29:29 +; Fix for SERVER print queue viewing problem +; BDEVIO.A86 1.22 93/09/21 12:43:37 +; On fdos read/write do EOF checks before SHARE LOCK checks +; BDEVIO.A86 1.21 93/09/14 20:02:50 +; Trust LFLG_PHYSICAL +; BDEVIO.A86 1.20 93/09/02 22:22:56 +; Use 32 bit sectors to read fat for build bpb if appropriate (SYQUEST bug) +; BDEVIO.A86 1.19 93/08/27 18:46:49 +; int 26 discards hash codes +; BDEVIO.A86 1.18 93/07/20 22:42:25 +; Even fewer checks on int 25/26 +; BDEVIO.A86 1.12 93/06/23 02:57:07 +; Add auto-commit to fdowrw +; BDEVIO.A86 1.11 93/05/14 13:47:41 +; Shorten media change code slightly +; BDEVIO.A86 1.9 93/03/16 22:30:21 IJACK +; UNDELETE support changes +; ENDLOG + + eject ! include i:mserror.equ ; F_DOS erros + eject ! include i:fdos.equ + eject ! include i:driver.equ + eject ! include i:doshndl.def + eject ! include bdos.equ + eject ! include rh.equ + +;***************************************************** +;* +;* bdos data area +;* +;***************************************************** + +PCMODE_DATA dseg word + extrn current_ddsc:dword + extrn current_dhndl:dword + extrn current_dsk:byte ; default drive + extrn current_ldt:dword ; currently selected LDT + extrn dma_offset:word ; DTA offset + extrn dma_segment:word ; DTA segment + extrn ddsc_ptr:dword + extrn err_drv:byte + extrn error_dev:dword ; failing device for Int 24's + extrn fdos_stub:dword + extrn ioexerr:byte + extrn last_drv:byte + extrn ldt_ptr:dword + extrn lock_bios:dword + extrn phys_drv:byte + extrn rwmode:byte + extrn share_stub:dword + extrn unlock_bios:dword + extrn verify_flag:byte + extrn net_retry:word + +BDOS_DATA dseg word + + extrn bcb_root:dword + extrn deblock_seg:word + extrn fdos_hds_drv:byte + extrn fdos_hds_blk:word + extrn fdos_hds_root:word + extrn fdos_ret:word + + public adrive + public clsize + public dosfat + public cur_dma + public cur_dma_seg + public datadd + public diradd + public dirinroot + public dirperclu + public fatadd + public hdsaddr + public lastcl + public logical_drv + public mult_sec + public nfatrecs + public nfats + public pblock + public physical_drv + public psecsiz + public req_hdr + public secperclu + +eject +; The following specify the drive selected for the current operation + +hdsaddr dw 0 ; current HDS address (0 means at root) +logical_drv db 0 ; logical drive number +physical_drv db 0 ; physical disk number + +; The following describe the currently active drive - not this may differ from +; the currently selected drive above due to eg. flushing dirty buffers + +; Local copy of DDSC_ variables - ORDER CRITICAL - must match DDSC_ + +local_ddsc rb 0 +psecsiz dw 0 ; byte size of sector +clmsk db 0 +clshf db 0 +fatadd dw 0 ; sector offset of 1st FAT sector +byte_nfats db 0 ; number of FAT's +dirinroot dw 0 ; # dir entries in root +datadd dw 0 ; sector offset of data sector +lastcl dw 0 ; # last cluster (after adjustment) +if DOS5 + dw 0 ; # sectors per FAT +else + db 0 ; # sectors per FAT (nb. may be inaccurate on large drives) +endif +diradd dw 0 ; sector offset of 1st root DIR sector + +LOCAL_DDSC_LEN equ offset $ - offset local_ddsc + +; some extra parameters calculated from local_ddsc for convenience + +nfats dw 0 ; # FAT's (WORD is handier) +nfatrecs dw 0 ; # sectors per FAT (accurate version) +clsize dw 0 ; cluster size in bytes +secperclu dw 0 ; # sectors per cluster +dirperclu dw 0 ; # dir enrties in subdir + +dosfat dw 0 ; FAT length indicator (FAT12 or FAT16) + +; The following specify the next block read/write operation on the active drive + +adrive db 0ffh ; currently active disk +pblock dw 0, 0 ; absolute block address +mult_sec dw 1 ; multi sector count passed to xios +cur_dma dw 0 +cur_dma_seg dw 0 + +fdrwreq dw 0 ; requested count (roundup) + + public fdrwflg +fdrwflg db 0 ; bdosrw flags +fdrwcnt dw 0 ; requested byte count for read/write +fdrwptr rd 0 ; disk transfer address for read/write +fdrwoff dw 0 ; offset for R/W DTA +fdrwseg dw 0 ; segment for R/W DTA + +fdrwsec rd 1 ; physical block for fdosrw +fdrwsecoff dw 0 ; offset within sector +fdrwdircnt dw 0 ; # sectors in direct xfer + +byteoff dw 0 ; fdosrw local variable + dw 0 ; byte offset with file + +blk dw 0 ; current cluster of filepos +blkidx dw 0 ; current cluster index within file +blkoffset dw 0 ; offset within cluster + +; static request header for DOS device driver I/O + + Public req_hdr + +req_hdr rb 0 +req_len db 22 +req_unit rb 1 +req_cmd rb 1 +req_status rw 1 +req_rwmode db 0 ; action hint for device drivers + rb 7 +req_media rb 1 + rb 16 + +req1_return equ byte ptr req_media+1 +req1_volid equ word ptr req_media+2 + +req2_buffer equ word ptr req_media+1 +req2_bpb equ word ptr req_media+5 + +req3_buffer equ word ptr req_media+1 +req3_count equ word ptr req_media+5 +req3_sector equ word ptr req_media+7 +req3_volid equ word ptr req_media+9 + +req4_buffer equ word ptr req_media+1 +req4_count equ word ptr req_media+5 +req4_sector equ word ptr req_media+7 +req4_volid equ dword ptr req_media+9 +req4_bigsector equ dword ptr req_media+13 + +eject +BDOS_CODE cseg + + extrn alloc_chain:near + extrn bpb2ddsc:near ; converts BPB to DDSC + extrn buffers_check:near ; look for buffers + extrn delfat:near + extrn discard_all:near ; discard all buffers + extrn discard_dir:near ; discard directory buffers + extrn discard_dirty:near ; discard all dirty buffers + extrn discard_files:near ; discard open files + extrn fdos_error:near + extrn fdos_restart:near + extrn file_update:near + extrn fixfat:near + extrn getnblk:near ; get block value from FAT + extrn get_ldt:near + extrn get_ldt_raw:near + extrn hdsblk:near ; get current HDS block + extrn hshdscrd:near + extrn locate_buffer:near + extrn rebuild_ldt_root:near + extrn timestamp_dhndl:near + extrn update_dat:near + extrn update_fat:near + extrn share_delay:near + + public block_device_driver + public clus2sec + public device_driver + public read_block + public select_adrive + public select_logical_drv + public select_physical_drv + public write_block + +eject + +eject + + Public get_ddsc + +get_ddsc: +;-------- +; On Entry: +; AL = physical drive +; On Exit: +; CY set if bad drive, else +; ES:BX -> DDSC_ +; (All other registers preserved) +; + cmp al,ss:phys_drv + jae get_ddsc30 + les bx,ss:ddsc_ptr +get_ddsc10: + cmp bx,0FFFFh ; end of the line + je get_ddsc30 + cmp al,es:DDSC_UNIT[bx] ; does the unit match ? + je get_ddsc20 ; no, try the next + les bx,es:DDSC_LINK[bx] + jmps get_ddsc10 +get_ddsc20: +; clc + ret +get_ddsc30: + stc + ret + +eject +; Read/Write from/to disk file + +; entry: CURRENT_DNHDL -> file handle +; BDRWFLG = 1 => read +; 0 => write +; ES:DI = buffer (32 bit: off/seg) +; CX = requested byte count (16 bit) + +; exit: FDOS_RET = number of bytes read/written +; CURRENT_DHNDL incremented by FDOS_RET + + public fdosrw ; read/write to/from disk file + +fdosrw: +;------ + call fdrw_prepare ; set up address, where we are in file + jc fdrw_error ; stop if we have a problem + call fdrw_size ; extend file if necessary + jc fdrw_error ; bail out if we can't + cmp fdrwcnt,0 ; are we truncating? + jne fdrw_loop ; read/write if non-zero count + test fdrwflg,1 ; writing zero bytes? + jnz fdrw_error ; (reading has no meaning) + call fdw_trunc ; writing truncates the file + jmps fdrw_nobigger +fdrw_error: + ret + +fdrw_loop: ; loop here for long reads/writes + call fdrw_seek ; seek to position for xfer + jc fdrw_exit ; should get error's now... + jnz fdrw_buffered ; deblocking required if not aligned + mov cx,fdrwcnt ; CX = requested transfer size + cmp cx,psecsiz ; at least one sector transferred? + jb fdrw_buffered ; if less, need deblocked transfer + mov fdrwreq,cx ; requested count for direct r/w + call direct_rw ; transfer straight to/from TPA + jmps fdrw_more +fdrw_buffered: ; perform deblocked read/write + call deblock_rw ; transfer via BDOS buffer +fdrw_more: + add fdrwoff,ax ; adjust buffer address + add fdos_ret,ax ; adjust return code + + add byteoff,ax ; adjust file offset + adc byteoff+2,0 + + sub fdrwcnt,ax ; adjust remaining count + ja fdrw_loop ; still more to do +fdrw_exit: + les bx,current_dhndl + mov ax,fdos_ret ; get total xfered and update position + add es:DHNDL_POSLO[bx],ax + adc es:DHNDL_POSHI[bx],0 + test fdrwflg,1 + jnz fdrw_return ; skip if reading + mov ax,byteoff ; has the file grown ? + mov dx,byteoff+WORD + sub ax,es:DHNDL_SIZELO[bx] + sbb dx,es:DHNDL_SIZEHI[bx] + jb fdrw_nobigger ; yes, update the file size + add es:DHNDL_SIZELO[bx],ax + adc es:DHNDL_SIZEHI[bx],dx +fdrw_nobigger: + call timestamp_dhndl ; record the current time + test es:DHNDL_MODE[bx],DHM_COMMIT + jz fdrw_return ; is auto-commit in place ? + call file_update ; yes, commit the file +fdrw_return: + ret + + + +fdw_trunc: +;--------- +; On Entry: +; BLKIDX = block number within file +; BLKOFFSET = block offset +; On Exit: +; DHNDL_SIZE adjusted, any excess clusters freed +; + + les bx,current_dhndl + mov cx,blkoffset ; get offset within current block + mov ax,blkidx ; get logical block number + jcxz fdw_t10 ; skip if no data in last block + inc ax ; else add in another cluster +fdw_t10: ; AX = # of clusters required in file + test ax,ax + jnz fdw_t20 + xchg ax,es:DHNDL_BLK1[bx] ; forget about chain + jmps fdw_t50 + +fdw_t20: + xchg ax,cx ; CX = # of blocks to keep + mov ax,es:DHNDL_BLK1[bx] ; get first block in file +fdw_t30: ; scan all block we want to keep + push cx + push ax + call getnblk ; get next block + pop bx + pop cx + cmp ax,lastcl ; stop on premature end of chain + ja fdw_t60 + loop fdw_t30 + push ax ; yep, remember what + mov ax,dosfat + xchg ax,bx ; truncate chain at cluster AX + call fixfat ; as thats all we need + pop ax +fdw_t50: + call delfat ; release the chain +fdw_t60: + les bx,current_dhndl + mov ax,byteoff ; now truncate the file + mov es:DHNDL_SIZELO[bx],ax + mov ax,byteoff+2 + mov es:DHNDL_SIZEHI[bx],ax + xor ax,ax ; cause reads/writes to scan + mov es:DHNDL_BLK[bx],ax ; block chain from start + mov es:DHNDL_IDX[bx],ax + mov fdos_ret,ax ; no logical errors + ret + + + +fdrw_prepare: +;------------ +; Normalise the xfer address and count +; Calculate current position in the file +; +; On Entry: +; ES:DI -> buffer +; CX = bytes to xfer +; On Exit: +; FDRWSEG:FDRWOFF -> normalised buffer +; FDRWCNT = bytes to xfer +; FDOS_RET = bytes xfer'd (0) +; PREREAD = TRUE +; BYTEOFF = current offset in file +; BLKIDX = cluster containing current file position +; BLKOFFSET = offset within cluster +; CY set if current position theoretically impossible +; + + xor ax,ax ; AX = 0 + mov fdos_ret,ax ; initialize byte return count + mov fdrwcnt,cx ; save byte count for read/write + mov ax,000Fh + and ax,di ; get offset within paragraph + mov fdrwoff,ax ; save normalized offset for read/write + add ax,cx ; do we overflow 64k ? + jnc fdrw_p10 ; yes, then forget about what would + sub fdrwcnt,ax ; overflow this segment +fdrw_p10: + mov cl,4 + shr di,cl ; DI = paragraph offset + mov ax,es + add ax,di ; AX = effective segment + jnc fdrw_p20 ; if above 1 MByte base it at FFFF + inc ax ; AX = para's above FFFF + shl ax,cl ; make it bytes + add fdrwoff,ax ; add to offset + mov ax,0ffffh ; use our magic segment +fdrw_p20: + mov fdrwseg,ax ; save normalized segment for read/write + les bx,current_dhndl + mov ax,es:DHNDL_POSLO[bx] + mov byteoff,ax ; copy position to local variables + mov ax,es:DHNDL_POSHI[bx] + mov byteoff+WORD,ax + mov cx,clsize + mov ax,lastcl + mul cx ; DX:AX = maximum size of disk + sub ax,byteoff + sbb dx,byteoff+WORD ; beyond this we can't go + jc fdrw_p30 + mov ax,byteoff ; DX:AX = current file size + mov dx,byteoff+WORD + div clsize + mov blkidx,ax ; save it for later + mov blkoffset,dx ; DX = offset within cluster + clc ; theoretically possible +fdrw_p30: + ret + + + + +fdrw_size: +;--------- +; On reads check xfer starts within file, and clip size to reflect EOF. +; On writes try to extend to cluster chain so it is big enough to contain +; the data we wish to write. +; +; On Entry: +; BYTEOFF = current position in file +; FDRWCNT = extra bytes requested +; On Exit: +; FDRWCNT adjusted if read past EOF +; CY set if problem extending file +; + les bx,current_dhndl + mov ax,es:DHNDL_SIZELO[bx] ; are we past the end of file + mov dx,es:DHNDL_SIZEHI[bx] ; if so we may wish to extend on write + sub ax,byteoff ; AX,DX = current offset + sbb dx,byteoff+WORD ; are we already beyond EOF ? + jb fdrw_s40 + sub ax,fdrwcnt ; will we be going beyond EOF ? + sbb dx,0 + jnb fdrw_s10 ; no, whole xfer is OK + test fdrwflg,1 ; check if we're reading + jz fdrw_s50 ; if we are just adjust the + add fdrwcnt,ax ; amount we can xfer +fdrw_s10: +; We call share concerning the XFER to check if any of the proposed +; file region is locked. + +; les bx,current_dhndl ; check for locked regions + mov cx,net_retry +fdrw_s15: + push cx + mov cx,fdrwcnt ; in the file + callf share_stub+S_FDOSRW + pop cx + jnc fdrw_s20 ; CY set on error + dec cx + jz fdrw_s30 + call share_delay + jmps fdrw_s15 +fdrw_s20: + ret + +fdrw_s30: + jmp fdos_error ; CY clear, AX = error code + + +fdrw_s40: +; We are going beyond EOF - if it is a read we fail it, if a write +; try to extend the file + test fdrwflg,1 ; check if we're reading + stc ; assume failure + jnz fdrw_s20 ; reads fail now, writes extend file +fdrw_s50: + call fdrw_s10 ; make sure SHARE doesn't object +; jmp fdwrite_extend ; if not try to extend the file + + +fdwrite_extend: +;-------------- +; Try to extend to file to the required size before we write to it +; On Entry: +; ES:BX -> DHNDL_ +; BYTEOFF = current position in file +; FDRWCNT = extra requested +; On Exit: +; CY clear if cluster chain now big enough for desired file size +; + + mov ax,byteoff ; AX,DX = current offset + mov dx,byteoff+2 + add ax,fdrwcnt ; AX,DX = offset after r/w if success + adc dx,0 ; add offset from lower 16 bits + div clsize ; AX whole blocks required + test dx,dx ; any remainder ? + jz fdw_e05 ; yes, we have a partial block + inc ax ; round up blocks required +fdw_e05: + xchg ax,cx ; CX blocks are required + mov ax,es:DHNDL_BLK1[bx] ; assume we need to follow from start + test ax,ax + jz fdw_e30 ; if no starting block do the lot + dec cx ; else count # extra blocks required + mov dx,es:DHNDL_BLK[bx] ; do we have a current block ? + test dx,dx ; if not we have to start + jz fdw_e10 ; with the first block + mov ax,dx ; new starting block as this must + sub cx,es:DHNDL_IDX[bx] ; be less than extended size +fdw_e10: + jcxz fdw_e20 ; bail out of we have enough +fdw_e15: + push ax ; save current block + push cx ; save # required + call getnblk ; AX = next block in chain + pop cx ; restore # required + pop bx ; recover previous block + cmp ax,lastcl ; end of chain yet ? + ja fdw_e40 + loop fdw_e15 ; try another one +fdw_e20: + clc ; chain is already long enough + ret + +fdw_e30: +; We have no initial block, so allocate them all +; xor ax,ax ; no preconceptions over where we + call alloc_chain ; allocate chain of CX clusters + jc fdw_e35 + les bx,current_dhndl + mov es:DHNDL_BLK1[bx],ax ; remember initial block + clc +fdw_e35: + ret + +fdw_e40: +; We have a partial chain, ending at cluster BX + push bx ; save current end of chain + xchg ax,bx ; start allocating from cluster AX a + call alloc_chain ; a chain of CX clusters + pop bx + jc fdw_e45 + xchg ax,bx ; AX = previous cluster, link cluster + call fixfat ; BX to end of the chain + clc +fdw_e45: + ret + + + +fdrw_seek: +;--------- +; On Entry: +; BYTEOFF = offset within file +; On Exit: +; BLK = cluster containing current filepos +; BLKOFFSET = offset within cluster +; BLKIDX = cluster index within file +; PBLOCK = sector containing current filepos +; POFFSET = offset within sector (reflected in ZF) +; + mov ax,byteoff ; where are we now ? + mov dx,byteoff+WORD + div clsize + mov blkidx,ax ; save cluster + mov blkoffset,dx ; and offset within it + les bx,current_dhndl + cmp ax,es:DHNDL_IDX[bx] ; do we know this block ? + jb fdrw_seek10 ; we can't go backwards, use 1st block + mov cx,es:DHNDL_BLK[bx] ; get last index block + jcxz fdrw_seek10 ; use 1st block if it isn't valid + sub ax,es:DHNDL_IDX[bx] ; skip this many + jmps fdrw_seek20 +fdrw_seek10: + mov cx,es:DHNDL_BLK1[bx] ; start with 1st block +fdrw_seek20: + xchg ax,cx ; AX = starting cluster + jcxz fdrw_seek40 ; CX = clusters to skip +fdrw_seek30: + push cx + call getnblk ; get next block + pop cx + cmp ax,lastcl ; stop on premature end of chain + ja fdrw_seek_error ; (file size must be wrong..) + loop fdrw_seek30 +fdrw_seek40: + les bx,current_dhndl + mov dx,blkidx + mov es:DHNDL_IDX[bx],dx ; remember this position for next time + mov es:DHNDL_BLK[bx],ax + mov blk,ax ; save the block for coniguous checks + mov bx,blkoffset + call clus2sec ; convert to sector/offset + mov word ptr fdrwsec,ax ; remember this block + mov word ptr fdrwsec+WORD,dx + mov fdrwsecoff,bx ; and offset within it + test bx,bx ; set ZF +; clc ; no problems + ret + +fdrw_seek_error: + stc ; we hit unexpected end of chain + ret ; (shouldn't happen) + +; Read/write partial sector via deblocking code +; On Entry: +; FDRWSEC = sector address on disk +; FDRWSECOFF = offset within sector +; FDRWCNT = byte count for read/write +; On Exit: +; AX = # of bytes transferred + +deblock_rw: +;---------- + mov cx,0FF00h+BF_ISDAT ; CH = preread, buffer is data + mov dx,word ptr fdrwsec ; set sector to xfer from + mov ah,byte ptr fdrwsec+WORD + call locate_buffer ; ES:SI -> buffer + mov bx,fdrwsecoff ; BX = offset within sector + mov ax,psecsiz + mov dx,ax ; DX = physical sector size + sub ax,bx ; AX = bytes left in sector + cmp ax,fdrwcnt ; more than we want to transfer? + jb deblkrw10 ; yes, only do up to end of sector + mov ax,fdrwcnt ; else do up to end of request +deblkrw10: + mov cx,ax ; AX, CX = byte count + ; (AX for return, CX for MOVSW) + push ds + test fdrwflg,1 ; check if reading or writing + jz dblkrw30 ; skip if writing + + push es + les di,fdrwptr ; destination is user memory + pop ds ; source segment is data buffer + lea si,BCB_DATA[si+bx] ; DS:SI -> data + jmps dblkrw40 ; copy the data + +dblkrw30: ; we're writing + or es:BCB_FLAGS[si],BF_DIRTY; mark buffer as dirty + lea di,BCB_DATA[si+bx] ; ES:DI -> data + lds si,fdrwptr ; source is user memory + +dblkrw40: + shr cx,1 ; make it a word count + rep movsw ; move the words + jnc dblkrw50 ; skip if even # of bytes + movsb ; else move last byte +dblkrw50: + pop ds ; restore registers + ret + + +; entry: BYTEOFF = 32-bit offset into file +; BLKOFFSET = byte offset within cluster +; PRVBLK = block in which transfer starts +; FDRWREQ = requested transfer length + +;--------- +direct_rw: +;--------- + sub dx,dx ; assume no extra blocks required + mov ax,fdrwreq ; total byte count + mov cx,clsize ; get number of bytes + sub cx,blkoffset ; CX = bytes remaining in this block + sub ax,cx ; if wholly containined within block + jbe direct_rw10 ; then leave it alone + div clsize ; else get # of extra clusters + xchg ax,dx ; DX = clusters, AX = remainder + or ax,ax ; round up if any remainder + jz direct_rw10 ; skip if even number + inc dx ; else one more cluster +direct_rw10: ; DX = # of contiguous clusters req'd + call check_cont ; check how many contiguous blocks + mov ax,clsize ; space = cnt * dpbptr->clsize; + mul cx ; AX:DX = # of bytes transferrable + sub ax,blkoffset ; BX = skipped bytes in 1st cluster + sbb dx,0 + ; AX:DX = max # of bytes transferrable + ; from current position + test dx,dx + jnz direct_rw20 ; if > 64 K, use up request + cmp ax,fdrwreq ; if less than we requested + jb direct_rw30 ; then lets do it +direct_rw20: + xor dx,dx + mov ax,fdrwreq ; else use requested count +direct_rw30: + div psecsiz ; AX = # complete sectors + mov fdrwdircnt,ax ; save direct sector count + mov mult_sec,ax ; set multi sector count + mul psecsiz ; AX = bytes to xfer + push ax ; save for later + + mov ax,fdrwoff ; FDRWPTR = disk transfer address + mov cur_dma,ax + mov ax,fdrwseg + mov cur_dma_seg,ax + mov ax,word ptr fdrwsec ; set sector to xfer from + mov word ptr pblock,ax + mov ax,word ptr fdrwsec+WORD + mov word ptr pblock+WORD,ax + mov rwmode,0000$0110b ;data read/write + mov cl,fdrwflg + and cl,1 ; CL = read/write flag + jz direct_rw40 + xor cx,cx ; indicate no retries + call read_block ; read in the data + jmps direct_rw50 +direct_rw40: + call write_block ; write out the data +direct_rw50: + call SynchroniseBuffers ; synchronize BCBs with direct transfer + pop ax ; recover bytes xfered + push ds ! pop es ; restore ES = SYSDAT + ret + + +check_cont: ; check for adjacent blocks or space +;---------- +; entry: DX = # of extra contiguous blocks req'd +; exit: CX = # of contiguous blocks available + +; We first check all adjacent allocated clusters. +; If we'd like more and we find the end of file +; and we are writing and the adjacent blocks aren't +; allocated, then we count them as well and link +; them into the file. + + mov ax,blk ; current block number + xor cx,cx ; contiguous blocks found = 0 + test dx,dx ; any extra required ? + jz check_cont20 +check_cont10: ; get link of current block + push ax ; save current block + push cx ; save extra blocks so far + push dx ; save extra blocks we'd like + call getnblk ; get the link + pop dx + pop cx + pop bx + inc bx ; BX = current block + 1 + cmp ax,bx ; check if next block is contiguous + jne check_cont20 ; and try for another + inc cx ; extra contiguous cluster + dec dx ; one less block to check + jnz check_cont10 ; try again if we still want more +check_cont20: ; we can do CX extra clusters + inc cx ; include 1st cluster too.. + ret + + +;------------------ +SynchroniseBuffers: ; synchronize BCBs after multi sector transfer +;------------------ +; On Entry: +; FDRWSEG:FDRWOFF = transfer address for IO_READ/IO_WRITE +; FDRWDIRCNT = physical sector count for direct transfer +; FDRWSEC = sector address for transfer +; FDWRFLG = even for write, odd for read +; On Exit: +; direct transfer buffer or BCB updated if BCB overlap +; +; If any data buffer is found, that falls into the region affected +; by the direct sector transfer, the following action is performed: +; If the operation was a read and the sector buffer is clean, +; no action is required. If it was dirty, the buffer contents is +; copied to the corresponding location in the DTA buffer. +; If the operation was a write, the sector buffer is discarded. +; +; + mov dx,word ptr fdrwsec + mov ah,byte ptr fdrwsec+WORD + mov al,adrive ; get our drive number + lds bx,bcb_root ; DS:BX -> 1st buffer +SynchroniseBuffers10: + test ds:BCB_FLAGS[bx],BF_ISDAT; is this a data buffer? + jz SynchroniseBuffers30 ; skip if directory or FAT + cmp al,ds:BCB_DRV[bx] ; does the drive match? + jne SynchroniseBuffers30 ; skip if different + mov si,ds:BCB_REC[bx] ; compute bcb->rec - prec + sub si,dx ; result in SI,CL (lsb..msb) + mov cl,ds:BCB_REC2[bx] + sbb cl,ah ; get bits 16-23 of result + jne SynchroniseBuffers30 ; skip if bcb->rec < prec + cmp si,ss:fdrwdircnt ; else check against transfer length + jae SynchroniseBuffers30 ; skip if beyond transfer length + + test ss:fdrwflg,1 ; test direction: read or write + jz SynchroniseBuffers20 ; skip if disk write + + test ds:BCB_FLAGS[bx],BF_DIRTY; if buffer dirty, did read old data + jz SynchroniseBuffers30 ; else data read was valid + + push ax ! push dx ; save record address + + mov ax,ss:psecsiz ; # of bytes in sector buffer + mov cx,ax + shr cx,1 ; CX = words per sector + mul si ; AX = byte offset from start buffer + add ax,ss:fdrwoff ; AX = offset + xchg ax,di ; DI = offset + mov es,ss:fdrwseg ; ES:DI -> data to be replaced + lea si,BCB_DATA[bx] + rep movsw ; move CX words (one physical sector) + pop dx ! pop ax ; restore record address + jmps SynchroniseBuffers30 + +SynchroniseBuffers20: ; multi sector write + mov ds:BCB_DRV[bx],0FFh ; discard this sector +SynchroniseBuffers30: +if DOS5 + mov bx,ds:BCB_NEXT[bx] + cmp bx,ss:word ptr bcb_root +else + lds bx,ds:BCB_NEXT[bx] ; get next buffer address + cmp bx,0ffffh +endif + jne SynchroniseBuffers10 ; if so stop + push ss ! pop ds ; restore DS + ret + +eject + Public blockif, ddioif + +;======= ================================ +blockif: ; disk read/write bios interface +;======= ================================ +; entry: AL = BIOS Request function number +; ADRIVE = block device to xfer to/from +; RWMODE = read/write mode +; CUR_DMA_SEG:CUR_DMA -> xfer address +; PBLOCK = starting block of xfer +; MULT_CNT = # blocks to xfer +; exit: AX = BX = output + + mov req_cmd,al + mov al,rwmode ; copy rwmode to where the device + mov req_rwmode,al ; driver can get the hint + mov ax,cur_dma ; get DMA offset + push ax ; (save it) + and ax,000Fh ; get offset within paragraph + mov req4_buffer,ax ; set transfer offset + pop ax ; (restore offset) + mov cl,4 + shr ax,cl ; convert to paragraphs + add ax,cur_dma_seg ; add in the segment + mov req4_buffer+2,ax ; set transfer segment + mov ax,mult_sec ; get requested sector count + mov req4_count,ax ; set requested sector count +;------ +ddioif: +;------ + push es + mov al,adrive ; get selected drive + call get_ddsc ; ES:BX -> DDSC + mov ax,word ptr pblock + mov dx,word ptr pblock+WORD ; DX:AX = starting block + push es + les si,es:DDSC_DEVHEAD[bx] ; ES:SI -> device driver +if DOS5 +; DOS 4 support + mov word ptr req4_bigsector,ax + mov word ptr req4_bigsector+2,dx + mov req_len,RH4_LEN ; set length of request header + test es:DH_ATTRIB[si],DA_BIGDRV ; large sector number support? + jz blockif10 ; no, normal request header + mov ax,-1 ; indicate we use 32-bit sector number +blockif10: + mov req4_sector,ax ; set requested sector address +else + mov word ptr req4_bigsector,ax + mov word ptr req4_bigsector+2,dx + + mov req4_sector,ax ; set requested sector address + mov req4_sector+2,dx ; (support large DOS drives) + mov req_len,RH4_LEN ; assume 22 bytes in request header + test es:DH_ATTRIB[si],DA_BIGDRV ; large sector number support? + jz blockif10 ; no, normal request header + mov req_len,RH4_LEN+2 ; else indicate long request +blockif10: +endif + pop es + + call block_device_driver ; make call to device driver + js blockif20 + xor ax,ax ; no error +blockif20: + mov mult_sec,1 ; reset sector count + mov bx,ax ; AX, BX = return code + pop es + ret + + + +block_device_driver: +;------------------ +; entry: ES:BX -> DDSC, req_hdr partly filled in +; exit: AX = status after function +; SF = 1 if error occurred +; note: BX preserved + + mov al,es:DDSC_MEDIA[bx] + mov req_media,al ; set current media byte + mov al,es:DDSC_RUNIT[bx] ; get relative unit # + mov req_unit,al ; set the unit + push ds + push es + push bx + push ds + lds si,es:DDSC_DEVHEAD[bx] + pop es + mov bx,offset req_hdr ; ES:BX -> request packet + call device_driver ; do operation + pop bx + pop es + pop ds + ret + +; On Entry: +; DS:SI Device Header +; ES:BX Current Request Header +; +; On Exit: +; AX Request Header Status +; +device_driver: +;------------ + xor ax,ax + mov es:RH_STATUS[bx],ax ; Initialise return status + push es + push bx + push bp + callf ss:lock_bios ; lock access to BIOS + push cs + call device_driver10 ; fake a callf + callf ss:unlock_bios ; unlock access to BIOS + pop bp + pop bx + pop es + sti + cld ; Restore Flags + mov ax,es:RH_STATUS[bx] ; Return the Status to the caller + test ax,ax ; set SF=1 if error + ret + +device_driver10: + push ds + push ds:DH_INTERRUPT[si] ; interrupt routine address on stack + push ds + push ds:DH_STRATEGY[si] ; strategy routine address on stack + retf ; retf to strategy, interrupt, us + +eject +; Select drive and check for door open ints +; Build fdos_hds to refer to the drive + +; Exit: DL = drive to be selected (0-15) + +select_logical_drv: +;------------------ +; On Entry: +; AL = logical drive to select (with change media checks) +; On Exit: +; ES:BX -> LDT_ +; + cmp al,last_drv ; is it a legal drive ? + jae select_drv_bad ; no, reject it now + mov logical_drv,al ; save logical drive + call get_ldt ; ES:BX -> LDT_ for drive + jc select_physical_drv ; no LDT_ during init, must be physical + mov word ptr current_ldt,bx + mov word ptr current_ldt+WORD,es + mov al,es:byte ptr LDT_FLAGS+1[bx] ; is the drive valid ? + test al,(LFLG_NETWRKD+LFLG_JOINED)/100h + jnz select_drv_bad ; reject networked/joined drives + test al,LFLG_PHYSICAL/100h + jz select_drv_bad ; reject non-physical drives + mov al,es:LDT_NAME[bx] ; get the drive from the ascii name + and al,1fh ; as the drive may require rebuilding + dec ax ; make it zero based + push es ! push bx + call select_physical_drv ; select the physical root + pop bx ! pop es + cmp es:LDT_ROOTLEN[bx],2 ; if logical and physical roots + jbe select_logical_drv30 ; are the same we are OK now +if JOIN + mov al,es:LDT_DRV[bx] ; should we be on a different + cmp al,fdos_hds_drv ; physical drive ? + jne select_logical_drv10 ; if so then we'd better rebuild +endif + cmp es:LDT_BLK[bx],0FFFFh ; did we have a media change ? + jne select_logical_drv20 ; then we'd better rebuild +select_logical_drv10: + call rebuild_ldt_root ; the LDT_ root block +select_logical_drv20: + mov ax,es:LDT_ROOT[bx] ; get virtual root from LDT + mov fdos_hds_root,ax ; move there + mov fdos_hds_blk,ax +if JOIN + mov al,es:LDT_DRV[bx] ; same with drive + mov fdos_hds_drv,al +endif +select_logical_drv30: + ret + +select_physical_drv: +;------------------- +; On Entry: +; AL = physical drive to select (with change media checks) +; On Exit: +; None +; + xor dx,dx + mov fdos_hds_blk,dx ; put it in the root by default + mov fdos_hds_root,dx + mov fdos_hds_drv,al ; set physical drive in working HDS + cmp al,phys_drv ; should we have a DDSC_ for this drive + jae select_drv_bad ; no, we can't select it then + mov physical_drv,al ; save physical drive number + call select_adrive ; no, better select it + jc select_drv_critical_error + ret + +select_drv_bad: +;-------------- +; An attempt has been made to select a bad drive, +; return a logical error "invalid drive" + mov ax,ED_DRIVE ; ED_DRIVE "invalid drive" + jmp fdos_error + +select_drv_critical_error: +;------------------------- +; The drive is logically correct, so all error at this point must +; be physical ones - so we want a critical error + jmp generate_critical_error + +eject +select_adrive: +;------------- +; This entry is called to physically select a drive (eg. when flushing buffers) +; It does not alter the current physical_drv setting, which must be re-selected +; afterwards by the caller. +; +; On Entry: +; AL = disk to select (range validated) +; On Exit: +; CY set if a problem selecting the drive + + mov adrive,al + mov err_drv,al ; save error drive + call get_ddsc ; ES:BX -> DDSC_ for drive + mov al,1 ; AL = "Unknown Unit" + jc select_drv_err ; error if no DDSC_ + mov ax,es:word ptr DDSC_DEVHEAD[bx] + mov word ptr error_dev+0,ax + mov ax,es:word ptr DDSC_DEVHEAD+2[bx] + mov word ptr error_dev+2,ax + push es ; remember driver address for error's + push bx ; preserve DDSC_ + call check_media ; see if media has changed + pop bx ; restore DDSC_ + pop es + jc select_drv_err + +; select the disk drive and fill the drive specific variables +; entry: ES:BX -> DDSC_ of disk to select +; AX <> 0 if drive requires BPB rebuilt +; exit: CY flag set on error + + test ax,ax ; device driver, new select? + jz select_ddsc ; use current DDSC if old select + call build_ddsc_from_bpb ; else get BPB and build new DDSC + jc select_drv_err ; carry flag reset + call select_ddsc ; use to DDSC for select +if DELWATCH + mov ah,DELW_NEWDISK ; we have a new disk so I guess + mov al,physical_drv ; I'd better tell delwatch + les bx,current_ddsc ; about the new disk so it + callf fdos_stub ; knows to update itself +endif + clc ;select disk function ok + ret + +select_drv_err: +; On Entry: +; AL = extended error code +; CY set +; + mov ioexerr,al ; save error code + ret + + +select_ddsc: +;----------- +; On Entry: +; ES:BX -> DDSC_ of drive to be selected + mov word ptr current_ddsc,bx + mov word ptr current_ddsc+WORD,es + push ds ! push es + pop ds ! pop es ; swap ES and DS + lea si,DDSC_SECSIZE[bx] ; DS:SI -> DDSC_ original + mov di,offset local_ddsc ; ES:DI -> DDSC_ copy + mov cx,LOCAL_DDSC_LEN + rep movsb ; make a local copy of interesting bits + push es ! pop ds ; DS=ES=local data segment + mov ax,psecsiz ; now initialise some other vaiiables + mov cl,clshf + shl ax,cl ; AX = bytes per cluster + mov clsize,ax + xor ax,ax + mov al,clmsk + inc ax ; AX = sectors per cluster + mov secperclu,ax + mov al,byte_nfats ; AX = number of FATs + mov nfats,ax ; (it's handier as a word + mov ax,diradd ; number of FAT records can be + sub ax,fatadd ; bigger than 255 + xor dx,dx + div nfats + mov nfatrecs,ax + mov cx,FCBLEN + mov ax,clsize ; convert from cluster size + xor dx,dx ; to number of dir entries + div cx ; per cluster - handy for + mov dirperclu,ax ; subdirectories + mov ax,FAT12 + cmp lastcl,MAX12 ; is it a 12 bit FAT ? + jbe select_ddsc10 + mov ax,FAT16 ; no, it's 16 bit +select_ddsc10: + mov dosfat,ax ; remember which for later + clc ; drive all selected + ret + + + + +eject + +build_ddsc_from_bpb: ; call device driver to build BPB, convert to DDSC_ +;------------------- +; On Entry: +; ES:BX -> DDSC_ to rebuild +; On Exit: +; ES:BX preserved +; CY set on error +; AL = error code + + push es + push bx ; save DDSC_ address + xor di,di + mov ax,deblock_seg + mov es,ax ; ES:DI -> deblock seg + test ax,ax ; if we are deblocking spare buffer + jnz build_bpb10 ; might be in high memory + dec ax ; AX = FFFF + mov dx,ax ; compute impossible record # + mov cx,BF_ISDIR ; locate directory sector w/o preread + call locate_buffer ; this will find the cheapest buffer + mov es:BCB_DRV[si],0FFh ; don't really want this... + lea di,BCB_DATA[si] ; ES:DI -> disk buffer +build_bpb10: + mov req4_buffer,di ; xfer to ES:DI + mov req4_buffer+2,es + pop bx ; restore DDSC_ address + pop es + + push ds + lds si,es:DDSC_DEVHEAD[bx] ; DS:SI -> device header + mov ax,ds:DH_ATTRIB[si] ; non-FAT ID driver ("non-IBM") bit + pop ds ; in device header attributes + test ax,DA_NONIBM + jnz bldbpb30 ; skip if media byte in FAT not used + + mov req_rwmode,0 ; read of system area + mov req_len,RH4_LEN ; set length field + mov req_cmd,CMD_INPUT ; read first FAT sector off disk +if DOS5 + test ax,DA_BIGDRV ; large sector numbers ? +endif + mov ax,1 + mov req4_count,ax ; read 1st FAT sector + cwd ; DS:AX = sector 1 + mov word ptr req4_bigsector,ax + mov word ptr req4_bigsector+2,dx +if DOS5 + jz bldbpb20 + dec ax ! dec ax ; AX = 0FFFFh +bldbpb20: +endif + mov req4_sector,ax ; set requested sector address + mov req4_sector+2,dx ; (support large DOS drives) + call block_device_driver ; try to read FAT sector, AX = status + js bldbpb_err ; skip if errors (AX negative) +bldbpb30: + mov req_len,RH2_LEN ; length of req + mov req_cmd,CMD_BUILD_BPB ; "build bpb" + call block_device_driver ; call the device driver + js bldbpb_err ; skip if errors (AX negative) + push ds + push es + push bx + mov di,bx ; ES:DI -> DDSC_ to initialise + lds si,dword ptr req2_bpb ; DS:SI -> BPB to convert + call bpb2ddsc ; rebuild the DDSC_ + pop bx + pop es + pop ds + clc ; success - we have a new DDSC_ + ret + + +bldbpb_err: + stc ; we had a problem + ret + + +eject + +;----------- +check_media: ; check media if DPH media flag set +;----------- +; On Entry: +; ES:BX -> DDSC_ of physical drive to check +; On Exit: +; CY set on error, AX = error code +; else +; AX <> 0 if disk requires BPB rebuild +; If definite/possible change then LDT's marked as invalid +; If possible then buffers/hashing discarded provided they are clean +; If definite then all buffers/hashing for drive discarded even if dirty +; + mov req_len,RH1_LEN ; set length field + mov req_cmd,CMD_MEDIA_CHECK ; media check routine + call block_device_driver ; call the device driver + jns chkmed10 + stc ; we have a problem, generate + ret ; an error +chkmed10: + mov al,req_media+1 ; else get returned value + xor ah,ah ; watch out for 1st access too.. + xchg ah,es:DDSC_FIRST[bx] ; treat never accessed as changed + cmp al,1 ; 1 = no change + jne chkmed20 + dec ax ; AL=0, build bpb only if DDSC_FIRST +; clc ; it all went OK + ret + +chkmed20: + mov dl,adrive ; media may have/has changed + call mark_ldt_unsure ; so force LDT's to unsure + +; AL = 00 if maybe changed, FF for definitely changed + test al,al + jz chkmed_maybe ; media may have changed + +chkmed_changed: ; disk has changed for sure + call discard_files ; discard open files + jmps chkmed30 ; discard buffers, build bpb required + +chkmed_maybe: ; disk has possibly changed + call discard_dir ; we can always discard dir as they + mov ah,BF_DIRTY ; won't be dirty + mov al,adrive + call buffers_check ; any dirty buffers on adrive? + jnz chkmed40 ; yes, can't discard FAT +chkmed30: + call discard_all ; discard buffers for drive +chkmed40: + or ax,0FFFFh ; better rebuild bpb +; clc + ret + + + Public mark_ldt_unsure + +mark_ldt_unsure: +;--------------- +; On Entry: +; DL = physical drive +; On Exit: +; All corresponding LDT's marked as unsure +; All reg preserved +; + push es + push ax + push bx + xor ax,ax ; start with drive A: +mlu10: + call get_ldt_raw ; ES:BX -> LDT_ + jc mlu30 ; CY = no more LDT's + test es:LDT_FLAGS[bx],LFLG_NETWRKD+LFLG_JOINED + jnz mlu20 ; if networked leave it alone + cmp dl,es:LDT_DRV[bx] ; does the physical drive match ? + jne mlu20 + mov es:LDT_BLK[bx],0FFFFh ; indicate we shouldn't trust BLK +mlu20: + inc ax ; onto next LDT + jmps mlu10 +mlu30: + pop bx + pop ax + pop es + ret + +;----------- +write_block: +;----------- +; entry: RWMODE = write type +; bit 0: +; 1 - write, not read +; bits 2-1 (affected disk area) +; 0 0 - system area +; 0 1 - FAT area +; 1 0 - root or sub directory +; 1 1 - data area + + or rwmode,1 ; mark it as a write + xor cx,cx ; indicate no second attempt + mov al,CMD_OUTPUT ; assume normal write + cmp verify_flag,0 ; is verify on ? + je rdwr_block + mov al,CMD_OUTPUT_VERIFY ; assume use write w/ verify + jmps rdwr_block + +;---------- +read_block: +;---------- +; entry: RWMODE = read type +; bit 0: +; 0 - read, not write +; bits 2-1 (affected disk area) +; 0 0 - system area +; 0 1 - FAT area +; 1 0 - root or sub directory +; 1 1 - data area +; CX <> 0 if FAT retry possible (critical error should then +; be avoided) +; exit: SF = 0 if success +; SF = 1 if failure (CX was non-zero on call) + + and rwmode,not 1 ;mark it as a read + mov al,CMD_INPUT +rdwr_block: + push cx + call blockif ;current drive, track,.... + pop cx + jns rdwrb5 + jcxz rdwrb10 ; test if any disk error detected +rdwrb5: + ret ; skip if yes +rdwrb10: + mov ioexerr,al ; save extended error + test al,al ; is it write protect error ? + jnz rdwrb20 ; we have dirty buffers we can't write + call discard_dirty ; out, so throw 'em away +rdwrb20: + mov al,adrive ; if error on different drive + cmp al,physical_drv ; treat error as media change + je generate_critical_error ; if same drive, report error + call discard_all ; discard all buffers on drive + call discard_files ; and flush files + jmp fdos_restart ; try to restart the instruction + +generate_critical_error: +;----------------------- +; On Entry: +; err_drv, rwmode, ioexerr set up +; On Exit: +; None - we don't come back +; + mov al,ioexerr ; AL = BIOS error return byte + cbw ; make it a word + cmp ax,15 ; only handle sensible errors + jb gen_crit_err10 ; anything else becomes + mov ax,12 ; general failure +gen_crit_err10: + neg ax ; convert to our negative errors + add ax,ED_PROTECT ; and start with write protect + jmp fdos_error ; now return with error + +eject + +clus2sec: ; convert from cluster/offset to sector/offset +;-------- +; On Entry: +; AX = cluster +; BX = byte offset in cluster +; On Exit: +; DX:AX = sector +; BX = byte offset in sector +; + xchg ax,cx ; remember cluster in CX + xor dx,dx + xchg ax,bx ; DX:AX = byte offset + div psecsiz ; AX = sector offset, DX = byte offset + mov bx,dx ; BX = byte offset in sector + xchg ax,cx ; AX = cluster, CX = sector offset + dec ax + dec ax ; forget about 2 reserved clusters + mul secperclu ; DX:AX = offset of cluster + add ax,datadd + adc dx,0 ; DX:AX = offset of start of dir + add ax,cx ; DX:AX - add in sector offset + adc dx,0 + ret + + + end diff --git a/IBMDOS/BDOS.EQU b/IBMDOS/BDOS.EQU new file mode 100644 index 0000000..f585989 --- /dev/null +++ b/IBMDOS/BDOS.EQU @@ -0,0 +1,80 @@ +; File : $BDOS.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; ENDLOG +; +; Search variables +; + +NEXT equ 0 +EMPTY equ 1 + +DOT equ 2eh ; '.' + +DRIVEN equ 0dh ; (0 rel) +DRIVEP equ 0fh ; (0 rel) + +DSKMAP equ 16 + +; struct pcfcb + +DRIVE equ 0 ;drive +FNAME equ 1 ;file name & type +EXTENT equ 12 ;extent (0 - 31) +CHKSUM equ 13 ;checksum +MODULE equ 14 ;module (0 - 63) + ; 0x80 - file extended flag + ; 0x40 - file write flag +RCDCNT equ 15 ;record count (0 - 128) +PCFCB1 equ 16 ;PCDOS fcb flag byte + ; 0x1f - high byte of file's dcnt + ; 0x20 - hidden + ; 0x40 - sub-directory + ; 0x80 - always one +PCFCB2 equ 17 ;same as pcfcb1 +LOWDCNT equ 18 ;low byte of file's dcnt +CBFLAG equ 19 ;current block flag +CBLOCK equ 20 ;current block (2 bytes) +CBLKIDX equ 22 ;current block index (2 bytes) +TIME equ 22 ;time (hhhhhmmmmmmsssss) +DATE equ 24 ;date (yyyyyyymmmmddddd) +BLOCK1 equ 26 ;first block in file +CSIZE equ 28 ;current file size (2 words) +CR equ 32 ;current record +RR0 equ 33 ;random record field (byte 0) +RR1 equ 34 ;random record field (byte 1) +RR2 equ 35 ;random record field (byte 2) + + +;struct fcb + +FCBLEN equ 32 ; size of file control block +FCBSHF equ 5 ; log2(fcblen) diff --git a/IBMDOS/BIN/BDEVIO.OBJ b/IBMDOS/BIN/BDEVIO.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..56309b0666b20b2fa42c65f8ac3279d0d65218db GIT binary patch literal 4352 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 literal 0 HcmV?d00001 diff --git a/IBMDOS/BIN/BUFFERS.OBJ b/IBMDOS/BIN/BUFFERS.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..42ab3d1f415a8c6faf3cccf1e912f06f953153fa GIT binary patch literal 2688 zcmchX`)?dq702(L*_l~;{Yv7*jq7+rL#9bwL)>-T5GTRonOX1RwRb!-9?#lsmZ;{9 z1PVJqpb$r~m29>Nr9~A&tI8Dd5D_9j7^zVtSlFQ@JVX-l15HW=i6|2-p=l$vJgO|; zJL`o01<1a8?>+a-IiK^rkA)^8jZP<%x@kRrVk05MRIG{q-9wuP-Zyw~^T5OX69*6V z?|x*>v-=1Ubk{bOh?>=O!Lk)~JfbOfW8O5XWvx7$Hb%@RW~dYBLhIgdN@N=$B2V9s zQA!|^KqY2-NQmNubTABVbtg$5Rhd!Z%MFh=>4bb01GT?#?tz%_mJ=CxnX0 zw3}4y=P2z^GMTK(yw%LKW$R{=QfW-LCr2~m&k@?XT4P>K>FW4LVOaHU*k9rhO0f;w zoaShUno=gm^gIlCebP2_WrUj5%`8F*5gJP(K`O7AX-A*nX{(mDRK?U7rJd_X<4pRt+g7J^2clH9dpS$FOksQ#cH~Yl=v_;0JnSTp{$H4vMYu_hyKZ;;HiF4n)ja zm{BpKShkv>Q6|B|mafvKB-<9to*t#5nz7QeIu*?swktH6vQkje)M#wROhdO(C^Al) z!!LBx%$l_AE+2rP6OB$Hi>a#?jj7XSUYk(zmOe&XEj^>Fc3uf3q0;IaZCMqn@o@{x zCgjX($Vw#xc;E?TS2T?_o4TT{GBjb$&`nf9TZ~lBN~=l+dON5gr9l!J9aTs3W;Sa> zLOtXTK}4fbgSbi}FkXvBC#Ewt98~&~<)ehhDID^936V?L_;o=ka8flynKL6J z!y+MHc-;t|BChwQTpx?q{=PC&6Ia@5+)8AbkRbf`hw$|tE#h^^i}OOES$N!e`sUTjTHSY<68i#*!#J)K}3y0q)N_-QbJ-c=-t7|4o)Ic-?X_8xK^jc4dVRKa+>Eaqo9I zx3(kaP6gXYZmCj;r;Y3Dri`GQ%wg8@j1_#GxVdXL-G5edZlKf?m48*2Dqb^GL*mld zrg#bcaP<(^S1H}X3LP0SoFH94;1;@Ielt-ai$5Br6TFoLZOzC?0zsjJZX!mT=gq48G}UZ}T6nPAPpS&!BW!3NN#FwQw$lT5HT z=$2po6bD3Fx>$%Nk>a99C*QufZRp?*6 zM1Lv|5MOfE`pux~29=C{0BtwgUNlB+pgoEM`C(La*y*~m{8hsLjr0C$Oqp`2zy;qU zvpE-PMdYF_$|vTd@`;SFc(cFHxQdKVpZqgR2$j!8 zNbsXO;ki8ZL?<&QDz|?K(U1LtF8qO9d*wzn)Q2m?7`(IkpwsE6oi*nf;B*8F#TvOQM^ZO{w~<|qNx}g&PF_+8-3U5 P`N&BQXR7=Ey#N0NH=sf$ literal 0 HcmV?d00001 diff --git a/IBMDOS/BIN/CDEVIO.OBJ b/IBMDOS/BIN/CDEVIO.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..75b5d3a44a9cd48bc6fe8dca3d3f1eabdfdde25c GIT binary patch literal 1408 zcmchV?@wE06vxkVfAroKS|)KAFeyaIRcz1!24>_1m)mxh`rFc#l7H_k-bp&h6U6(5=b-=&r|#xd~uTR zd7kr}^Eu}^84(F0TF|`(oOXwQ`J3GpGR$|vY+Y=AcB7=O6A8Gu1D2D zssV^o3G1v4s!cgPH9aeFQ!K6PT)2DUuU_`}9N3gy9N3&DF;z(l~ z0K;gb*SeMqQ(Vah+jG)%pi6o`AfP!DhEx#W`M#pt>xd<2o{5=8$gx^& zPS9%X7ZP0VnC7%kCfvC*qi;>$6+V=%O2<4TALm^JH!J@iC#fELj1b zlH7!hd9PgbY*hAWmA$(1yjZOzXzvEE^fgTz0F$ z`rCSNNoQ7thDrcOinR(RcWXM}K|65k!)d)<+EMw|hp(p&Rs!{ejv_O~h$&&?E$D4B z4XF?$9ETVbE)gqk|}qu+jRCerLIbu34RH&+ajVBV14Tsmd^F!krLenXZGhX2vZ1P@g=xGG9M-wjl z6q=cEeNBNj31T11dkHK+zIq4K-2o4PeU2+EFmPo1 zlcU8ZuTWTG!20v??Th!vgp}yJACxjDtMJni5&!A(cUYmgS2~EBTI`$iEz`C8qL6lZ z|Cnim9MMGEfk3rr^=MBeTsg1C+lNs1peg9Trg@UH31BCfD?e42wz(wYdY;>BNwNB` zJ4Ki)7x_)5=<;T_T+u}jMCroP^^;ZuZu)_pYf?V#&f1>ln{YnG{Bsv)GaYvz-r5Wg Rxo(Xe&ocmK)BpJY{{mPKx$*!2 literal 0 HcmV?d00001 diff --git a/IBMDOS/BIN/CIO.LST b/IBMDOS/BIN/CIO.LST new file mode 100644 index 0000000..754fca4 --- /dev/null +++ b/IBMDOS/BIN/CIO.LST @@ -0,0 +1,2496 @@ + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 1 + + += 0001 __RASM__ EQU 1 + + ; File : $CIO.A86$ + ; + ; Description : + ; + ; Original Author : DIGITAL RESEARCH + ; + ; Last Edited By : $CALDERA$ + ; + ;-----------------------------------------------------------------------; + ; Copyright Work of Caldera, Inc. All Rights Reserved. + ; + ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, + ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. + ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES + ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF + ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO + ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE + ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE + ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, + ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, + ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, + ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF + ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT + ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND + ; CIVIL LIABILITY. + ;-----------------------------------------------------------------------; + ; + ; *** Current Edit History *** + ; *** End of Current Edit History *** + ; $Log: $ + ; CIO.A86 1.20 94/12/01 10:05:21 + ; Made cooked_write and is_device aware of FCB writes; + ; CIO.A86 1.19 94/06/28 12:21:07 + ; Fix last_key_ext bug + ; CIO.A86 1.18 94/05/12 14:06:22 + ; The routine cooked_status now sets a flag last_key_ext if the keycode is 0 + ; On entry, it checks this flag to see if the last one was 0, and if so does + ; not do the checks for the control keys. In this way, Alt-R and Alt-Q can + ; be distinguished from Ctrl-S and Ctrl-P. + ; CIO.A86 1.17 93/12/21 17:58:15 + ; Preserve BX round clock read + ; Update char_error so DS:SI -> device driver header itself + ; CIO.A86 1.10 93/05/06 19:28:03 + ; Move int 23/28 support to CIO. + ; Read the clock in idle_dev, not int 28 loop. + ; CIO.A86 1.9 93/05/05 23:30:44 + ; int 2A/84 is now only generated on input-and-wait functions + ; CIO.A86 1.8 93/03/25 15:05:56 + ; tweak console block output + ; ENDLOG + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 2 + + + ; + ; This module contains all the Character I/O functions used by PCMODE + ; + ; 12 Nov 87 Disable Control-Break when the Console Output mode is RAW + ; 24 Feb 88 Display Control characters correctly. ie "^X" + ; 23 May 88 Support ^S to Pause screen output. + ; 25 May 88 Support Control-P for Cooked_Write and remove Kanji Character + ; check. + ; 26 May 88 Check for CTLC on CON_DEV when character input is redirected. + ; Correctly detect EOF on redirected input. + ; 17 Aug 88 Call PRN device with Open/Close on ^P + ; 30 Aug 88 Jump to correct exit when Open/Close is not supported by a + ; device driver for ^P. + ; 14 Sep 88 Break checking should only be carried out when the INDOS_FLAG + ; is 1. (Novell and Cntrl-C). + ; 03 Sep 88 Return the character output by INT21/04,05,06 in AL. + ; 10 Nov 88 Preserve ES when calling any Device Driver (Revalation DEVDRVR) + ; 15 Dec 88 Check STDERR for Control-C if it is a Device. + ; 15 Mar 89 Check for CTLC during Cooked Write. + ; 16 Mar 89 Explicitly allow INT 28 during char reads (SmartNotes bug) + ; 25 Apr 89 Execute break_check after getting the console status INT21/0B + ; 2 May 89 Save Device driver STRAT and INT address's on the stack + ; 10 May 89 Now check keyboard more often during cooked write + ; 25 May 89 Move INT28 flag to PCMIF.PCM + ; 6 Sep 89 Enter/Exit critical region round device request + ; 26 Oct 89 saving some bytes again... + ; 25 Jan 90 Insert IDLE Detection Code + ; 29 Jan 90 Int 2A critical section support added to device_callf + ; 7 Mar 90 Convert to register preserved function calls + ; 27 Mar 90 cooked_write checks STD_OUT for ctl-s ctl-p etc (STD_IN may + ; have been redirected) + ; 29 Mar 90 preserve BX round device_callf (3+Share CLOCK$ bug) + ; 12 Jun 90 get_doshndl parameter BX not AX + ; 15 Oct 90 Added support for Return Interim Character flag (see PSP_RIC). + ; 26 Oct 90 handle PSP=0 (ie. FCB device I/O) + ; 1 mar 91 break_check now goes to con_device, not STDERR + ; 17 jun 91 ij fix to cooked_out to avoid status checks if STDOUT redirected + += include pcmode.equ += ; File : $PCMODE.EQU$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 3 + + += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += ; This file contains all the general purpose definitions += ; and equates used by the PCMODE Module. += ; += += FFFF TRUE equ 0FFFFh ; value of TRUE += 0000 FALSE equ 0 ; value of FALSE += += 0006 TRUE_VERSION equ 6 += += FFFF IDLE_DETECT equ TRUE ; Check for IDLE Process's += += if IDLE_DETECT += 0001 IDLE_COMMAND equ 0001h ; Command Processor Active += 0002 IDLE_DOSFUNC equ 0002h ; DOS Function Called += 0004 IDLE_INT28 equ 0004h ; INT 28 Called += += 4000 IDLE_ON equ 4000h ; ReSet when Idle Checking Enabled += 8000 IDLE_INIT equ 8000h ; ReSet when $IDLE$ Loaded and Active += C000 IDLE_DISABLE equ IDLE_INIT + IDLE_ON += += 0001 PROC_IDLE equ 0001 ; Process is IDLE += 0002 PROC_INT28 equ 0002 ; INT28 Polling Loop += 0003 PROC_KEYIN equ 0003 ; Keyboard Input += 0004 PROC_DEVIN equ 0004 ; Device Input Routine += endif += += += 00C0 STACK_SIZE equ 192 ; Local Stack Size (Levels) += 0050 MAX_PATHLEN equ 80 ; Maximum Path length += 000D MAX_FILELEN equ 13 += += ; + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 4 + + += ; DOS process termination Codes += ; += 0000 TERM_NORMAL equ 0 ; Normal Termination += 0001 TERM_BREAK equ 1 ; Termination by Control Break += 0002 TERM_ERROR equ 2 ; Termination by Critical Error += 0003 TERM_RESIDENT equ 3 ; Terminate and Stay Resident += += ; += ; Critical Error responses from the default INT 24 handler and += ; the DO_INT24 routine. += ; += 0000 ERR_IGNORE equ 0 ; Ignore Error += 0001 ERR_RETRY equ 1 ; Retry the Operation += 0002 ERR_ABORT equ 2 ; Terminate the Process += 0003 ERR_FAIL equ 3 ; Fail Function += ; += 0008 OK_FAIL equ 0000$1000b ; Fail is a Valid Response += 0010 OK_RETRY equ 0001$0000b ; Retry is a Valid Response += 0020 OK_IGNORE equ 0010$0000b ; Ignore is a valid Response += 0038 OK_RIF equ 0011$1000b ; All Responsese are Valid += 0030 OK_RI equ 0011$0000b ; Retry and Ignore are Valid += 0018 OK_RF equ 0001$1000b ; Retry and Fail are Valid += ; += 0040 NO_CRIT_ERRORS equ 0100$0000b ; critical error shouldn't be generated += ; warning - must match FDOS.A86 += ; + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 5 + + += eject += ; The following equates define the format in which the users registers += ; are saved on the stack. This format is also seen by an application += ; when a critical error occurs. += ; += CodeMacro POP$DOS ; Pop User Registers a la MS-DOS += db 058h ! db 05Bh ; pop AX ! pop BX += db 059h ! db 05Ah ; pop BX ! pop CX += db 05Eh ! db 05Fh ; pop SI ! pop DI += db 05Dh ; pop BP += db 01Fh ! db 007h ; pop DS ! pop ES += EndM += += CodeMacro PUSH$DOS ; Push User Registers += db 006h ! db 01Eh ; push ES ! push DS += db 055h ; push BP += db 057h ! db 056h ; push DI ! push SI += db 052h ! db 051h ; push DX ! push CX += db 053h ! db 050h ; push BX ! push AX += EndM += += 0000 reg_AX equ word ptr .00 += 0000 reg_AL equ byte ptr .00 += 0001 reg_AH equ byte ptr .01 += += 0002 reg_BX equ word ptr .02 += 0002 reg_BL equ byte ptr .02 += 0003 reg_BH equ byte ptr .03 += += 0004 reg_CX equ word ptr .04 += 0004 reg_CL equ byte ptr .04 += 0005 reg_CH equ byte ptr .05 += += 0006 reg_DX equ word ptr .06 += 0006 reg_DL equ byte ptr .06 += 0007 reg_DH equ byte ptr .07 += += 0008 reg_SI equ word ptr .08 += 000A reg_DI equ word ptr .10 += 000C reg_BP equ word ptr .12 += += 000E reg_DS equ word ptr .14 += 0010 reg_ES equ word ptr .16 += += 0012 reg_IP equ word ptr .18 += 0014 reg_CS equ word ptr .20 += 0016 reg_FLAGS equ word ptr .22 += += ; Processor Flags += 0001 CARRY_FLAG equ 0001h ; Carry Flag += 0040 ZERO_FLAG equ 0040h ; Zero Flag += 0080 SIGN_FLAG equ 0080h ; Sign Flag + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 6 + + += 0200 INT_FLAG equ 0200h ; Interrupt Flag += 0400 DIR_FLAG equ 0400h ; Direction Flag += 0800 OFLW_FLAG equ 0800h ; OverFlow Flag += += 0000 DMD_ID equ es:byte ptr .0 ; id code ('M' or 'Z') += 0001 DMD_PSP equ es:word ptr .1 ; owner of memory block += 0003 DMD_LEN equ es:word ptr .3 ; length of memory block += 0006 DMD_IDLE_FLAGS equ es:word ptr .6 ; idle flags live here += 0008 DMD_NAME equ es:byte ptr .8 ; ASCIIZ name field += 0008 DMD_NAME_LEN equ 8 ; 8 Bytes long += 004D IDM equ 'M' ; not last id code += 005A IDZ equ 'Z' ; last id code += += PCMCODE GROUP PCM_HEADER, PCM_CODE, BDOS_CODE, PCM_RODATA += PCMCODE GROUP PCM_HISTORY, PCM_ICODE, PCM_CODEND += += PCM_HEADER CSEG PARA += PCM_CODE CSEG BYTE += PCM_RODATA CSEG WORD += BDOS_CODE CSEG WORD += PCM_HISTORY CSEG BYTE += PCM_ICODE CSEG BYTE += PCM_CODEND CSEG PARA += += += PCMDATA GROUP PCMODE_DATA, FDOS_DSEG, FIXED_DOS_DATA += PCMDATA GROUP PCMODE_CODE, GLOBAL_DATA, BDOS_DATA, PCMODE_DSIZE += += PCMODE_DATA DSEG WORD ; DOS Data += FDOS_DSEG DSEG WORD COMMON ; FDOS Parameter Block +=0000 fdos_data rw 7 += FIXED_DOS_DATA CSEG WORD 'DATA' ; Fixed DOS Data Area += PCMODE_CODE CSEG WORD 'DATA' ; DATA relative CODE += GLOBAL_DATA DSEG WORD ; GLOBAL DOS DATA (Process Independant) += BDOS_DATA DSEG WORD ; BDOS Data Area += PCMODE_DSIZE DSEG PARA ; End of DOS Data Area + += include i:driver.equ += ; File : $DRIVER.EQU$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 7 + + += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += ; Device driver header offsets. += += += 0000 DH_NEXT equ es:dword ptr 0 ; Dword Pointer to Next DEV += 0000 DH_NEXTOFF equ es:word ptr 0 ; Offset of next device += 0002 DH_NEXTSEG equ es:word ptr 2 ; Segment of next device += 0004 DH_ATTRIB equ es:word ptr 4 ; device attribute bits += 0006 DH_STRATEGY equ es:word ptr 6 ; offset of strategy entry += 0008 DH_INTERRUPT equ es:word ptr 8 ; offset of interupt entry += 000A DH_NAME equ es:byte ptr 10 ; 8-BYTE device name += += 8000 DA_CHARDEV equ 8000h ; 1=character device, 0=block device += 4000 DA_IOCTL equ 4000h ; device supports IOCTL string I/O += 2000 DA_NONIBM equ 2000h ; dosen't require FAT for login += 2000 DA_OTILBSY equ 2000h ; supports "output until busy" += 0800 DA_REMOVE equ 0800h ; supports "removable media" check += 0080 DA_QUERY equ 0080h ; supports query ioctl += 0040 DA_GETSET equ 0040h ; supports 3.2 level functionality += 0010 DA_SPECIAL equ 0010h ; fast console ouput via INT 29h += 0008 DA_ISCLK equ 0008h ; device is current clock device += 0004 DA_ISNUL equ 0004h ; device is NUL device (reserved) += 0002 DA_BIGDRV equ 0002h ; supports > 65535 sector per drive += 0002 DA_ISCOT equ 0002h ; device is standard output device += 0001 DA_ISCIN equ 0001h ; device is standard input device += += 0029 FASTCON_INT equ 29h ; fast console output interrupt += + += include i:reqhdr.equ += ; File : $REQHDR.EQU$ += ; += ; Description : += ; + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 8 + + += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += += 0000 CMD_INIT equ 0 ; Initialize the Device Driver += 0001 CMD_MEDIA_CHECK equ 1 ; Request Media Check += 0002 CMD_BUILD_BPB equ 2 ; Build Drive BPB += 0003 CMD_INPUT_IOCTL equ 3 ; IOCTL input += 0004 CMD_INPUT equ 4 ; Input += 0005 CMD_INPUT_NOWAIT equ 5 ; Non destructive input no wait += 0006 CMD_INPUT_STATUS equ 6 ; Input status += 0007 CMD_INPUT_FLUSH equ 7 ; Input flush += 0008 CMD_OUTPUT equ 8 ; Output += 0009 CMD_OUTPUT_VERIFY equ 9 ; Output with verify += 000A CMD_OUTPUT_STATUS equ 10 ; Output status += 000B CMD_OUTPUT_FLUSH equ 11 ; Output flush += 000C CMD_OUTPUT_IOCTL equ 12 ; IOCTL output += 000D CMD_DEVICE_OPEN equ 13 ; Device OPEN += 000E CMD_DEVICE_CLOSE equ 14 ; Device CLOSE += 000F CMD_FIXED_MEDIA equ 15 ; Removeable Media Check += 0013 CMD_GENERIC_IOCTL equ 19 ; Generic IOCTL += 0017 CMD_GET_DEVICE equ 23 ; Get the Logical Device += 0018 CMD_SET_DEVICE equ 24 ; Set the Logical Device += 0019 CMD_QUERY_IOCTL equ 25 ; query ioctl support += += ; Generic Request Header Format + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 9 + + += += 0000 RH_LEN equ es:byte ptr 0[bx] += 0001 RH_UNIT equ es:byte ptr 1[bx] += 0002 RH_CMD equ es:byte ptr 2[bx] += 0003 RH_STATUS equ es:word ptr 3[bx] += 0100 RHS_DONE equ 0100h += 0200 RHS_BUSY equ 0200h += 0400 RHS_IC equ 0400h ; Interim Character += 0800 RHS_RM equ 0800h += 8000 RHS_ERROR equ 8000h += += ;****** += ;* No longer safe to use - some device drivers trample on them.... += ;* += ;* RH_STRATEGY equ es:dword ptr 5[bx] ; Device Strategy Routine += ;* RH_STRATOFF equ es:word ptr 5[bx] ; Strategy Offset += ;* RH_STRATSEG equ es:word ptr 7[bx] ; Strategy Segment += ;* RH_INTERRUPT equ es:dword ptr 9[bx] ; Device Interrupt Routine += ;* RH_INTOFF equ es:word ptr 9[bx] ; Intterupt Offset += ;* RH_INTSEG equ es:word ptr 11[bx] ; Interrupt Segment += ;***** += += ; Request header for initialization += += 000D RH0_NUNITS equ es:byte ptr 13[bx] += 000E RH0_RESIDENT equ es:word ptr 14[bx] += 0012 RH0_BPBOFF equ es:word ptr 18[bx] += 0014 RH0_BPBSEG equ es:word ptr 20[bx] += 0016 RH0_DRIVE equ es:byte ptr 22[bx] += 0016 RH0_LEN equ 22 += += ; Request header for media check += += 000D RH1_MEDIA equ es:byte ptr 13[bx] ; BDOS: current media byte += 000E RH1_RETURN equ es:byte ptr 14[bx] ; driver: return code (00, 01, FF) += 000F RH1_VOLID equ es:dword ptr 15[bx] ; driver: volume label address += 000F RH1_LEN equ 15 += += ; Request header for "build BPB" += += 000D RH2_MEDIA equ es:byte ptr 13[bx] ; BDOS or driver? += 000E RH2_BUFFER equ es:dword ptr 14[bx] ; BDOS: scratch buffer for driver use += 0012 RH2_BPB equ es:dword ptr 18[bx] ; same as the following: += 0012 RH2_BPBOFF equ es:word ptr 18[bx] ; driver: address of new BPB += 0014 RH2_BPBSEG equ es:word ptr 20[bx] += 0018 RH2_LEN equ 24 += += ; Request header for input/output += += 000D RH4_MEDIA equ es:byte ptr 13[bx] ; BDOS: current media byte += 000D RH4_RIC equ es:byte ptr 13[bx] ; BDOS: Return Interim Char flg += 000E RH4_BUFFER equ es:dword ptr 14[bx] ; BDOS: disk transfer address + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 10 + + += 000E RH4_BUFOFF equ es:word ptr 14[bx] ; BDOS: Buffer Offset += 0010 RH4_BUFSEG equ es:word ptr 16[bx] ; BDOS: Buffer Segment += 0012 RH4_COUNT equ es:word ptr 18[bx] ; BDOS: sector count += 0014 RH4_SECTOR equ es:word ptr 20[bx] ; BDOS: starting sector += 0016 RH4_VOLID equ es:dword ptr 22[bx] ; driver: volume if illegal disk change += 001A RH4_BIGSECTOR equ es:dword ptr 26[bx] += 001A RH4_BIGSECTORLO equ es:word ptr 26[bx] += 001C RH4_BIGSECTORHI equ es:word ptr 28[bx] += += 001E RH4_LEN equ 30 += += ; Request Header for Non-Destructive Input += += 000D RH5_CHAR equ es:byte ptr 13[bx] ; Character Read from Device += 000D RH5_RIC equ es:byte ptr 13[bx] ; BDOS: Return Interim Char flg += 000E RH5_LEN equ 14 += += ; Request Header for Device Open += += 000D RH13_LEN equ 13 += += ; Request Header for Device Close += += 000D RH14_LEN equ 13 += += ; Request header for generic IOCTL += += 000D RH19_CATEGORY equ es:word ptr 13[bx] ; BDOS: major/minor function number += 000D RH19_MAJOR equ es:byte ptr 13[bx] ; BDOS: Major Function Number += 000E RH19_MINOR equ es:byte ptr 14[bx] ; BDOS: Minor Function Number += 000F RH19_SI equ es:word ptr 15[bx] ; BDOS: User SI += 0011 RH19_DI equ es:word ptr 17[bx] ; BDOS: User DI += 0013 RH19_GENPB equ es:dword ptr 19[bx] ; BDOS: extra parameters += 0017 RH19_LEN equ 23 += += 0040 RQ19_SET equ 40h ; set device parameters += 0060 RQ19_GET equ 60h ; get device parameters += 0041 RQ19_WRITE equ 41h ; write tracks += 0061 RQ19_READ equ 61h ; read tracks += 0042 RQ19_FORMAT equ 42h ; format tracks += 0062 RQ19_VERIFY equ 62h ; verify tracks += += 004C RQ19_PRP_START equ 4Ch ; start of codepage prepare += 004D RQ19_PRP_END equ 4Dh ; end of codepage prepare += 004A RQ19_SELECT equ 4Ah ; select code page += 006A RQ19_QRY_SEL equ 6Ah ; query selected code page += 006B RQ19_QRY_PRP equ 6Bh ; query prepared code page(s) += 005F RQ19_DSP_SET equ 5Fh ; set display information += 007F RQ19_DSP_GET equ 7Fh ; get display information += += ; Request header for get/set drive += + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 11 + + += 000E RH24_CMD equ es:byte ptr 14[bx] ; BDOS: Command Code += 000F RH24_STATUS equ es:word ptr 15[bx] ; BDOS: Status += 0011 RH24_RESVD equ es:dword ptr 17[bx] ; BDOS: Reserved += 0015 RH24_LEN equ 21 += += 001E RH_SIZE equ 30 ; maximum size of request header + += include i:msdos.equ += ; File : $MSDOS.EQU$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += += += 0000 MS_P_TERMCPM equ 00H += 0001 MS_C_READ equ 01H += 0002 MS_C_WRITE equ 02H += 0003 MS_A_READ equ 03H += 0004 MS_A_WRITE equ 04H += 0005 MS_L_WRITE equ 05H += 0006 MS_C_RAWIO equ 06H += 0007 MS_C_RAWIN equ 07H += 0008 MS_C_NOECHO equ 08H + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 12 + + += 0009 MS_C_WRITESTR equ 09H += 000A MS_C_READSTR equ 0aH += 000B MS_C_STAT equ 0bH += 000C MS_C_FLUSH equ 0cH += 000D MS_DRV_ALLRESET equ 0dH += 000E MS_DRV_SET equ 0eH += 000F MS_F_OPEN equ 0fH += 0010 MS_F_CLOSE equ 10H += 0011 MS_F_SFIRST equ 11H += 0012 MS_F_SNEXT equ 12H += 0013 MS_F_DELETE equ 13H += 0014 MS_F_READ equ 14H += 0015 MS_F_WRITE equ 15H += 0016 MS_F_MAKE equ 16H += 0017 MS_F_RENAME equ 17H += 0019 MS_DRV_GET equ 19H += 001A MS_F_DMAOFF equ 1aH += 001B MS_DRV_ALLOC equ 1bH += 001C MS_DRV_ALLOCSPEC equ 1cH += 0021 MS_F_READRAND equ 21H += 0022 MS_F_WRITERAND equ 22H += 0023 MS_F_SIZE equ 23H += 0024 MS_F_RANDREC equ 24H += 0025 MS_S_SETINT equ 25H += 0026 MS_P_MKPSP equ 26H += 0027 MS_F_READBLK equ 27H += 0028 MS_F_WRITEBLK equ 28H += 0029 MS_F_PARSE equ 29H += 002A MS_T_GETDATE equ 2aH += 002B MS_T_SETDATE equ 2bH += 002C MS_T_GETTIME equ 2cH += 002D MS_T_SETTIME equ 2dH += 002E MS_F_VERIFY equ 2eH += 002F MS_F_DMAGET equ 2fH += 0030 MS_S_BDOSVER equ 30H += 0031 MS_P_TERMKEEP equ 31H += 0033 MS_S_BREAK equ 33H += 0035 MS_S_GETINT equ 35H += 0036 MS_DRV_SPACE equ 36H += 0038 MS_S_COUNTRY equ 38H += 0039 MS_X_MKDIR equ 39H += 003A MS_X_RMDIR equ 3aH += 003B MS_X_CHDIR equ 3bH += 003C MS_X_CREAT equ 3cH += 003D MS_X_OPEN equ 3dH += 003E MS_X_CLOSE equ 3eH += 003F MS_X_READ equ 3fH += 0040 MS_X_WRITE equ 40H += 0041 MS_X_UNLINK equ 41H += 0042 MS_X_LSEEK equ 42H += 0043 MS_X_CHMOD equ 43H += 0044 MS_X_IOCTL equ 44H + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 13 + + += 0045 MS_X_DUP equ 45H += 0046 MS_X_DUP2 equ 46H += 0047 MS_X_CURDIR equ 47H += 0048 MS_M_ALLOC equ 48H += 0049 MS_M_FREE equ 49H += 004A MS_M_SETBLOCK equ 4aH += 004B MS_X_EXEC equ 4bH += 004C MS_X_EXIT equ 4cH += 004D MS_X_WAIT equ 4dH += 004E MS_X_FIRST equ 4eH += 004F MS_X_NEXT equ 4fH += 0050 MS_P_SETPSP equ 50H += 0054 MS_F_GETVERIFY equ 54H += 0056 MS_X_RENAME equ 56H += 0057 MS_X_DATETIME equ 57H += 0058 MS_M_STRATEGY equ 58h += 0059 MS_F_ERROR equ 59H += 005A MS_X_MKTEMP equ 5aH += 005B MS_X_MKNEW equ 5bH += 005C MS_F_LOCK equ 5cH += 0060 MS_X_EXPAND equ 60H += 0062 MS_P_GETPSP equ 62H += 6601 MS_X_GETCP equ 6601h += 6602 MS_X_SETCP equ 6602h += 0067 MS_X_SETHC equ 67h += 0068 MS_X_COMMIT equ 68h += += 0021 DOS_INT equ 21h ; DOS Entry Point += ; += 0000 STDIN equ 0 ; Standard Console Input Handle += 0001 STDOUT equ 1 ; Standard Console Output Handle += 0002 STDERR equ 2 ; Standard Error Output += 0003 STDAUX equ 3 ; Auxilary Device Handle += 0004 STDPRN equ 4 ; Printer Device Handle + += include i:fdos.equ += ; File : $FDOS.EQU$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 14 + + += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += ; += ; Structure of Buffer Control Blocks += ; ---------------------------------- += ; These BCBs immediately preceed the data buffers. BCBs are += ; always shared for all drives and therefore must be big += ; enough for the largest drive. += ; += += 0000 BCB_NEXT equ word ptr 00h ; link to next buffer += 0002 BCB_PREV equ word ptr 02h ; link to previous buffer += 0004 BCB_DRV equ byte ptr 04h ; drive of this buffer or 0FFh += 0005 BCB_FLAGS equ byte ptr 05h ; buffer flags += 0006 BCB_REC equ word ptr 06h ; low 16 bits of sector address += 0008 BCB_REC2 equ byte ptr 08h ; top 8 bits of record address += 000A BCB_COPIES equ byte ptr 0Ah ; number of copies to write += 000B BCB_SEPARATION equ word ptr 0Bh ; # sectors copies are apart += 000D BCB_DDSC equ dword ptr 0Dh ; DWORD ptr to DDSC_ += 0011 BCB_REMOTE equ word ptr 11h ; remote in-use count += 0014 BCB_DATA equ byte ptr 14h ; buffer data += += 0002 BF_ISFAT equ 0002h ; buffer marked as FAT sector += 0004 BF_ISDIR equ 0004h ; buffer marked as Directory sector += 0008 BF_ISDAT equ 0008h ; buffer marked as Data sector += 0040 BF_DIRTY equ 0040h ; buffer marked as modified += 0080 BF_REMOTE equ 0080h ; buffer is remote += += 0FF6 MAX12 equ 0FF6h ; max. disk size w/ 12-bit media += += ; Structure of Hash Control Block += ; ------------------------------- += ; Each hash control block refers to the hash codes of one += ; disrectory cluster or a root directory. += += 0000 HCB_LINK equ word ptr 0 ; link to next control block += 0002 HCB_DRV equ byte ptr 2 ; drive for this entry or 0FFh + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 15 + + += 0004 HCB_CLU equ word ptr 4 ; cluster number or 0000 if root += 0006 HCB_CNT equ word ptr 6 ; number of hashed entries += 0008 HCB_DATA equ word ptr 8 ; hash buffer data += += += ; Structure of DOS FCB += ; -------------------- += ; This is hopefully consistent with what DOS stores in an += ; open file control block for DOS 1.x functions += += 0000 MSF_EXTFLG equ byte ptr 0 ; if this is 0xFF, skip 1st 7 byte += 0006 MSF_ATTRIB equ byte ptr 6 ; file attributes if MSF_EXTFLG += 0000 MSF_DRIVE equ byte ptr 0 ; 1st byte normally drive code += 0001 MSF_NAME equ byte ptr 1 ; 8-bit ASCII file name, 11 characters += 000C MSF_BLOCK equ word ptr 12 ; current block number += 000E MSF_RECSIZE equ word ptr 14 ; current logical record size += 0010 MSF_SIZE equ word ptr 16 ; 32-bit file size += 0014 MSF_DATE equ word ptr 20 ; last date stamp += 0016 MSF_TIME equ word ptr 22 ; last time stamp += 0018 MSF_IFN equ byte ptr 24 ;; internal file number += 0019 MSF_IOCTL equ byte ptr 25 ;; file status += 001A MSF_BLOCK1 equ word ptr 26 ;; 1st block of file += 001C MSF_DBLK equ word ptr 28 ;; directory block += 001C MSF_DEVPTR equ dword ptr 28 ;; address of device driver += 001E MSF_DCNT equ word ptr 30 ;; directory count += 0020 MSF_CR equ byte ptr 32 ; current sequential record += 0021 MSF_RR equ word ptr 33 ; random record address (3 or 4 byte) += 0023 MSF_RR2 equ byte ptr 35 ; random record overflow += += += ; Structure of DOS DPB += ; -------------------- += ; The layout of this structure is a guess based on += ; examples. It is returned by PC MODE on functions 1Fh and += ; 32h and is required by various disk-related utilities += ; like disk editors and CHKDSK. += += 0000 DDSC_UNIT equ byte ptr 0 ; absolute drive number += 0001 DDSC_RUNIT equ byte ptr 1 ; relative unit number += 0002 DDSC_SECSIZE equ word ptr 2 ; sector size in bytes += 0004 DDSC_CLMSK equ byte ptr 4 ; sectors/cluster - 1 += 0005 DDSC_CLSHF equ byte ptr 5 ; log2 (sectors/cluster) += 0006 DDSC_FATADDR equ word ptr 6 ; sector address of FAT += 0008 DDSC_NFATS equ byte ptr 8 ; # of FAT copies += 0009 DDSC_DIRENT equ word ptr 9 ; size of root directory += 000B DDSC_DATADDR equ word ptr 11 ; sector address of cluster #2 += 000D DDSC_NCLSTRS equ word ptr 13 ; # of clusters on disk += 000F DDSC_NFATRECS equ word ptr 15 ; # of sectors per FAT += 0011 DDSC_DIRADDR equ word ptr 17 ; sector address of root dir += 0013 DDSC_DEVHEAD equ dword ptr 19 ; device driver header += 0013 DDSC_DEVOFF equ word ptr 19 += 0015 DDSC_DEVSEG equ word ptr 21 + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 16 + + += 0017 DDSC_MEDIA equ byte ptr 23 ; current media byte += 0018 DDSC_FIRST equ byte ptr 24 ; "drive never accessed" flag += 0019 DDSC_LINK equ dword ptr 25 ; next drive's DDSC += 001D DDSC_BLOCK equ word ptr 29 ; next block to allocate += 001F DDSC_FREE equ word ptr 31 ; total free clusters on drive += 0021 DDSC_LEN equ 33 += += += += ; DELWATCH hooks called by OS += += 0000 DELW_RDMASK equ 0 ; delete dir search mask += 0002 DELW_DELETE equ 2 ; delete this dir entry += 0003 DELW_FREECLU equ 3 ; free some clusters += 0004 DELW_FREERD equ 4 ; free root dir entry += 0005 DELW_SPACE equ 5 ; add "deletes" to free space += 0007 DELW_NEWDISK equ 7 ; new disk logged in += 000E DELW_PURGE equ 14 ; perge pd file += 000F DELW_UNDEL equ 15 ; undelete pd file += += ; SuperStore hook called by OS += += 0010 SSTOR_SPACE equ 10h ; enquire # physical free space += += ; Password hooks called by OS += += 0020 PASSWD_CREAT equ 20h ; initialise an entry += 0021 PASSWD_CHMOD equ 21h ; change an entry += 0022 PASSWD_CHECK equ 22h ; check an entry += += ; Share hooks in PCMODE data segment += ; += ; These point to a stub which does a "STC, RETF" += ; += += 000F NUM_SHARE_STUB_ENTRIES equ 15 += += 0000 S_LOCKS equ DWORD*0 ; share lock/unlock region += 0004 S_UPDATE equ DWORD*1 ; update DHNDL from share += 0008 S_RECORD equ DWORD*2 ; update share from DHNDL += 000C S_FDOSRW equ DWORD*3 ; validate proposed operation += 0010 S_DISCARD equ DWORD*4 ; discard all files on drive += 0014 S_OPEN equ DWORD*5 ; files is opening, remember it += 0018 S_CLOSE equ DWORD*6 ; files is closing, forget it += 001C S_OM_COMPAT equ DWORD*7 ; check open mode compatible += 0020 S_CLOSE_IF_OPEN equ DWORD*8 ; close if compat open, else deny += 0024 S_DENY_IF_OPEN equ DWORD*9 ; deny if open shared/by others += 0028 S_GET_LIST_ENTRY equ DWORD*10 ; get open file list entry += 002C S_CLOSE_FILES equ DWORD*11 ; close all files for given PSP/UID += += ; struct dirfcb += + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 17 + + += 0000 DNAME equ byte ptr 0 ;file name & type += 000B DATTS equ byte ptr 11 += 0001 DA_RO equ 01h ; 0x01 - read/only += 0002 DA_HIDDEN equ 02h ; 0x02 - hidden += 0004 DA_SYSTEM equ 04h ; 0x04 - system += 0008 DA_VOLUME equ 08h ; 0x08 - volume label += 0010 DA_DIR equ 10h ; 0x10 - sub-directory += 0020 DA_ARCHIVE equ 20h ; 0x20 - archive += 0080 DA_CLUSTER equ 80h ; 0x80 - return starting cluster from search (API ex + tenti += 0080 DA_DELWATCH equ 80h ; 0x88 - return pending delete files += 00D8 DA_FIXED equ 11011000b ; can't CHMOD label, dir, unused bits += FF27 DA_CHANGE equ not DA_FIXED ; all others are changeable += += ;DATTS2 equ 12 ;CP/M attributes += ; ; 0x80 - f1' modify default open rules += ; ; 0x40 - f2' partial close default += ; ; 0x20 - f3' ignore close checksum errors += ; ; 0x10 - f4' disable checksums += ; ; 0x08 - (reserved) += ; ; 0x04 - DELETE password += ; ; 0x02 - WRITE password += ; ; 0x01 - READ password += 000D DUNDEL equ 13 ;1st letter of deleted file += 000E DPWD equ word ptr 14 ;16-bit password hash code += 0010 DMODTIME equ word ptr 16 ;delwatch time (hhhhhmmmmmmsssss) += 0012 DMODDATE equ word ptr 18 ;delwatch date (yyyyyyymmmmddddd) += ;DRECSIZE equ 16 ;FlexOS record size += ;DUSER equ 18 ;FlexOS user ID of creator += ;DGROUP equ 19 ;FlexOS group ID of creator += 0014 DPWM equ word ptr 20 ;FlexOS access rights += 0016 DTIME equ 22 ;time (hhhhhmmmmmmsssss) += 0018 DDATE equ 24 ;date (yyyyyyymmmmddddd) += 001A DBLOCK1 equ 26 ;first block in file += 001C DSIZE equ 28 ;current file size += += ; DOS Media Password Definitions += ; ------------------------------ += += 000F PWM_OWNER equ 000Fh ; PWD Owner mask += 00F0 PWM_GROUP equ 00F0h ; PWD Group mask += 0F00 PWM_WORLD equ 0F00h ; PWD World mask += 0888 PWM_R equ 0888h ; PWD required for reading += 0444 PWM_W equ 0444h ; PWD required for writing += 0222 PWM_E equ 0222h ; PWD req'd for executing += 0111 PWM_D equ 0111h ; PWD required for deleting += 0DDD PWM_ANY equ PWM_R+PWM_W+PWM_D ; PWD required for anything += += += ; literal constants += += 0FFF FAT12 equ 00fffh ; 12 bit fat + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 18 + + += FFFF FAT16 equ 0ffffh ; 16 bit fat += += FFFF ENDDIR equ 0ffffh ;end of directory += + += include i:psp.def += ; File : $PSP.DEF$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += ; += ; Program Segment Prefix += ; ---------------------- += ; This structure holds vital information for DOS programs += ; += ;****************************************************************************** += ;* += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 00 | int 20 | memory | *** | jmpf|longjmp off| += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 08 |longjmp seg| int22 Off | int22 Seg | int22 Off | += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 10 | int22 Seg | int24 Off | int24 Seg | Parent | + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 19 + + += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 18 | Default Handle Table | += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 20 | XFT (20 entries) | += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 28 | XFT contd. | Environ | User SP | += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 30 | User SS | xfnmax | xftoff | xftseg | += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 38 | res1 | res2 | ric | *** | ********* | += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 40 | version | ********* | ********* | ********* | += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 48 | ********* | ********* | ********* | ********* | += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 50 | int 21 | retf| *** | ********* | ********* | += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 58 | ********* | ********* | PSP fcb 1 | += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += += 0000 PSP_INT20 equ es:word ptr .0000h += 0002 PSP_MEMORY equ es:word ptr .0002h += ;PSP_??? equ es:byte ptr .0004h += 0005 PSP_LONGCALL equ es:byte ptr .0005h += 0006 PSP_LONGOFF equ es:word ptr .0006h += 0008 PSP_LONGSEG equ es:word ptr .0008h += 000A PSP_TERM_IP equ es:word ptr .000Ah += 000C PSP_TERM_CS equ es:word ptr .000Ch += 000E PSP_BREAK_IP equ es:word ptr .000Eh += 0010 PSP_BREAK_CS equ es:word ptr .0010h += 0012 PSP_ERROR_IP equ es:word ptr .0012h += 0014 PSP_ERROR_CS equ es:word ptr .0014h += 0016 PSP_PARENT equ es:word ptr .0016h += 0018 PSP_XFT equ es:byte ptr .0018h += ; += ; The Default Handle Table is HERE !! += ; += 002C PSP_ENVIRON equ es:word ptr .002ch += 002E PSP_USERSP equ es:word ptr .002eh += 0030 PSP_USERSS equ es:word ptr .0030h += 0032 PSP_XFNMAX equ es:word ptr .0032h += 0034 PSP_XFTPTR equ es:dword ptr .0034h += 0034 PSP_XFTOFF equ es:word ptr .0034h += 0036 PSP_XFTSEG equ es:word ptr .0036h += 0038 PSP_RES1 equ es:word ptr .0038h ; DOS Reserved 0FFFFh += 003A PSP_RES2 equ es:word ptr .003Ah ; DOS Reserved 0FFFFh += 003C PSP_RIC equ es:byte ptr .003Ch ; Return Interim Character flag += 0040 PSP_VERSION equ es:word ptr .0040h ; DOS version number += += += 0050 PSP_DOSCALL equ es:word ptr .0050h += 0052 PSP_DOSRETF equ es:byte ptr .0052h + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 20 + + += += 005C PSP_FCB1 equ es:byte ptr .005Ch += 006C PSP_FCB2 equ es:byte ptr .006Ch += 0080 PSP_COMLEN equ es:byte ptr .0080h += 0081 PSP_COMLINE equ es:byte ptr .0081h += += 0014 XFNMAX equ 20 += += 0100 PSPLEN equ 100h += 0060 PSPILEN equ 60h + += include i:mserror.equ += ; File : $MSERROR.EQU$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += += FFFF ED_FUNCTION equ -01 ; invalid function number += FFFE ED_FILE equ -02 ; file not found += FFFD ED_PATH equ -03 ; path not found += FFFC ED_HANDLE equ -04 ; too many open files += FFFB ED_ACCESS equ -05 ; file access denied += FFFA ED_H_MATCH equ -06 ; invalid handle number + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 21 + + += FFF9 ED_DMD equ -07 ; memory descriptor destroyed += FFF8 ED_MEMORY equ -08 ; insufficient memory += FFF7 ED_BLOCK equ -09 ; invalid memory block addr += FFF6 ED_ENVIRON equ -10 ; invalid environment += FFF5 ED_FORMAT equ -11 ; invalid format += FFF4 ED_ACC_CODE equ -12 ; invalid access code += FFF3 ED_DATA equ -13 ; invalid data += FFF1 ED_DRIVE equ -15 ; invalid drive specified += FFF0 ED_DIR equ -16 ; can't remove current dir += FFEF ED_DEVICE equ -17 ; not same device += FFEE ED_ROOM equ -18 ; no more files += += FFED ED_PROTECT equ -19 ; disk write protected += FFEC ED_BADUNIT equ -20 ; invalid drive specified += FFEB ED_NOTREADY equ -21 ; drive doesn't respond += FFEA ED_BADCMD equ -22 ; invalid command to driver += FFE9 ED_BADDATA equ -23 ; data CRC error += FFE8 ED_BADRHLEN equ -24 ; (shouldn't happen) += FFE7 ED_BADSEEK equ -25 ; can't seek to track += FFE6 ED_BADMEDIA equ -26 ; unrecognizable medium += FFE5 ED_RNF equ -27 ; record/sector not found += FFE4 ED_NOPAPER equ -28 ; printer error += FFE3 ED_WRFAIL equ -29 ; write failed += FFE2 ED_RDFAIL equ -30 ; read failed += FFE1 ED_GENFAIL equ -31 ; anything failed += FFE0 ED_SHAREFAIL equ -32 ; sharing conflict += FFDF ED_LOCKFAIL equ -33 ; locking conflict += FFDE ED_DISKCHG equ -34 ; invalid disk change += FFDD ED_NOFCBS equ -35 ; FCB table exhausted += FFDC ED_NOLOCKS equ -36 ; lock list items exhausted += FFCE ED_NET equ -50 ; Network Request Not Supported += += FFBF ED_NETACCESS equ -65 ; file access denied += += FFB7 ED_NETPWD equ -73 ; Server Password Error += FFB6 ED_NETVER equ -74 ; Incorrect Server version += FFB5 ED_NETREQ equ -75 ; No Local Network Resources += FFB4 ED_NETTIME equ -76 ; Network Time Out Error += FFB3 ED_NETCOMM equ -77 ; Network Communications Error += FFB2 ED_NETSRVR equ -78 ; No Server Network Resources += FFB1 ED_NETLOG equ -79 ; Server Not Logged In += += FFB0 ED_EXISTS equ -80 ; file already exists += FFAE ED_MAKE equ -82 ; Cannot Make (Files ??) += FFAD ED_FAIL equ -83 ; FAIL code returned from INT 24 += FFAC ED_STRUCT equ -84 ; Out of Structures += FFAB ED_ASSIGN equ -85 ; Already Assigned += FFAA ED_PASSWORD equ -86 ; Invalid Password += FFA9 ED_PARAM equ -87 ; Invalid Parameter += FFA8 ED_NETWRITE equ -88 ; Network write fault += FFA7 ED_NETFUNC equ -89 ; Function not supported on network += FFA6 ED_COMPONENT equ -90 ; system component not installed + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 22 + + += FFA6 ED_LASTERROR equ -90 ; Last Error Number Used += += += 0001 CLASS_RESOURCE equ 1 ; Out of Resource += 0002 CLASS_TEMP equ 2 ; Temporary Situation += 0003 CLASS_AUTHOR equ 3 ; Authorization Error += 0004 CLASS_INTERNAL equ 4 ; Internal System Software Error += 0005 CLASS_HARDWARE equ 5 ; Hardware Failure += 0006 CLASS_SYSTEM equ 6 ; Serious System Failure += 0007 CLASS_APPLIC equ 7 ; Application Program Error += 0008 CLASS_LOST equ 8 ; File/Item Not Found += 0009 CLASS_FORMAT equ 9 ; File/Item Illegal Format += 000A CLASS_LOCKED equ 10 ; File/Item Locked += 000B CLASS_MEDIA equ 11 ; Media Failure += 000C CLASS_EXISTS equ 12 ; Item Already Exists += 000D CLASS_UNKNOWN equ 13 ; Unknown Classification += += 0001 ACT_RETRY equ 1 ; Retry a few times then prompt user += 0002 ACT_DELAY equ 2 ; Delay then as ACT_RETRY += 0003 ACT_USER equ 3 ; Prompt user to re-enter data += 0004 ACT_ABORT equ 4 ; Clean Up then ABORT the process += 0005 ACT_TERM equ 5 ; Terminate immeadiately NO CLEAN UP += 0006 ACT_IGNORE equ 6 ; Ignore the Error += 0007 ACT_URETRY equ 7 ; Retry the error after user intervention += += 0001 LOC_UNKNOWN equ 1 ; Unknown error location += 0002 LOC_BLOCK equ 2 ; Block Device Failure += 0003 LOC_NET equ 3 ; Network Failure += 0004 LOC_CHAR equ 4 ; Related to Serial/Character devices += 0005 LOC_MEMORY equ 5 ; Failure related to Memory + += include i:char.def += ; File : $CHAR.DEF$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 23 + + += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += ;************************************************; += ;* *; += ;* Character Definitions *; += ;* *; += ;************************************************; += += 0001 CTLA equ 'A' - '@' += 0002 CTLB equ 'B' - '@' += 0003 CTLC equ 'C' - '@' += 0004 CTLD equ 'D' - '@' += 0005 CTLE equ 'E' - '@' += 0006 CTLF equ 'F' - '@' += 0007 CTLG equ 'G' - '@' += 0007 BELL equ 'G' - '@' += 0008 CTLH equ 'H' - '@' += 0009 CTLI equ 'I' - '@' += 0009 TAB equ 'I' - '@' += 000A CTLJ equ 'J' - '@' += 000A LF equ 'J' - '@' += 000B CTLK equ 'K' - '@' += 000D CTLM equ 'M' - '@' += 000D CR equ 'M' - '@' += 0010 CTLP equ 'P' - '@' += 0011 CTLQ equ 'Q' - '@' += 0012 CTLR equ 'R' - '@' += 0013 CTLS equ 'S' - '@' += 0014 CTLT equ 'T' - '@' += 0015 CTLU equ 'U' - '@' += 0016 CTLV equ 'V' - '@' += 0017 CTLW equ 'W' - '@' += 0018 CTLX equ 'X' - '@' += 0019 CTLY equ 'Y' - '@' += 001A CTLZ equ 'Z' - '@' += 001B ESC equ '[' - '@' += 001C CTLBS equ '\' - '@' += 001F CTLUB equ '_' - '@' += 001E CTLUP equ '^' - '@' += 007F DEL equ 07Fh += 007F RUBOUT equ DEL + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 24 + + += += 005E CTL equ '^' + += include i:redir.equ += ; File : $REDIR.EQU$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += ; Int 2F AH=11 msnet redirector hook equates += += 1100 I2F_PRESCENCE equ 1100h += 1101 I2F_RMDIR equ 1101h += 1103 I2F_MKDIR equ 1103h += 1105 I2F_CHDIR equ 1105h += 1106 I2F_CLOSE equ 1106h += 1107 I2F_COMMIT equ 1107h += 1108 I2F_READ equ 1108h += 1109 I2F_WRITE equ 1109h += 110A I2F_LOCK equ 110Ah += 110B I2F_UNLOCK equ 110Bh += 110C I2F_SPACE equ 110Ch += 110E I2F_SET_ATTR equ 110Eh += 110F I2F_GET_ATTR equ 110Fh + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 25 + + += 1111 I2F_REN equ 1111h += 1113 I2F_DEL equ 1113h += 1116 I2F_OPEN equ 1116h += 1117 I2F_CREATE equ 1117h += 1118 I2F_XCREATE equ 1118h += 1119 I2F_XSFIRST equ 1119h += 111B I2F_SFIRST equ 111Bh += 111C I2F_SNEXT equ 111Ch += 111D I2F_PCLOSE equ 111Dh += 111E I2F_REDIR_5F equ 111Eh += 111F I2F_REDIR_5E equ 111Fh += 1120 I2F_FLUSH equ 1120h += 1121 I2F_LSEEK equ 1121h += 1122 I2F_PTERM equ 1122h += 1123 I2F_PPATH equ 1123h += 1124 I2F_CTLP_ERR equ 1124h += 1125 I2F_REDIR_5D equ 1125h += 1126 I2F_CTLP equ 1126h += + += include i:doshndl.def += ; File : $DOSHNDL.DEF$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 26 + + += ; += ; ENDLOG += += 0000 DCNTRL_DSADD equ dword ptr 0000h += 0000 DCNTRL_DSOFF equ word ptr 0000h += 0002 DCNTRL_DSSEG equ word ptr 0002h += 0004 DCNTRL_COUNT equ word ptr 0004h += 0006 DCNTRL_LEN equ 6 += += 0000 DHNDL_COUNT equ word ptr 00h ; 00 - Usage Count += 0002 DHNDL_MODE equ word ptr 02h ; 02 - File Mode += += 8000 DHM_FCB equ 8000h ; marks as FCB += 4000 DHM_COMMIT equ 4000h ; auto-commit file += 2000 DHM_NOCRIT equ 2000h ; no critical errors += 0080 DHM_LOCAL equ 10000000b ; file is not inherited += 0070 DHM_SHAREMSK equ 01110000b ; sharing bits += 0000 DHM_COMPAT equ 00000000b += 0010 DHM_DENY_ALL equ 00010000b ; exclusive - deny all += 0020 DHM_DENY_WRITE equ 00100000b += 0030 DHM_DENY_READ equ 00110000b += 0040 DHM_DENY_NONE equ 01000000b += 000F DHM_RWMSK equ 00001111b ; read write bits += 0002 DHM_RW equ 00000010b ; file opened read/write += 0001 DHM_WO equ 00000001b ; file opened write only += 0000 DHM_RO equ 00000000b ; file opened read only += += ; += ; 01h to 03h To be Determined += ; += 0004 DHNDL_DATRB equ byte ptr 04h ; Disk attribute byte += 0005 DHNDL_ATTR equ byte ptr 05h ; Attribute Byte += 0005 DHNDL_WATTR equ word ptr 05h ; Attribute Word += += 8000 DHAT_REMOTE equ 8000h ; set if file remote += 4000 DHAT_TIMEOK equ 4000h ; set if timestamp up to date += 1000 DHAT_LOCAL equ 1000h ; file is not inherited += 0800 DHAT_NETPRN equ 0800h ; device is networked printer += 0080 DHAT_DEV equ 0080h ; device/file bit += 0040 DHAT_READY equ 0040h ; ready/not ready bit += 0040 DHAT_CLEAN equ 0040h ; this bit CLEAR if dirty += 0020 DHAT_BIN equ 0020h ; raw/cooked bit += 001F DHAT_DRVMSK equ 001Fh ; drive in bottom bits += 0008 DHAT_CLK equ 0008h ; -reserved- += 0004 DHAT_NUL equ 0004h ; handle is null device += 0002 DHAT_COT equ 0002h ; handle is console output device += 0001 DHAT_CIN equ 0001h ; handle is console input device += += 0007 DHNDL_DEVPTR equ dword ptr 07h ; 07 - pointer to device += 0007 DHNDL_DEVOFF equ word ptr 07h ; 07 - offset of device += 0009 DHNDL_DEVSEG equ word ptr 09h ; 09 - segment of device += 000B DHNDL_BLK1 equ word ptr 0Bh ; 0B - first cluster in file + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 27 + + += 000D DHNDL_TIME equ word ptr 0Dh ; 0D - file time stamp += 000F DHNDL_DATE equ word ptr 0Fh ; 0F - file date stamp += 0011 DHNDL_SIZE equ dword ptr 11h ; 11 - file length += 0011 DHNDL_SIZELO equ word ptr 11h += 0013 DHNDL_SIZEHI equ word ptr 13h += 0015 DHNDL_POS equ dword ptr 15h ; 15 - current file position += 0015 DHNDL_POSLO equ word ptr 15h += 0017 DHNDL_POSHI equ word ptr 17h += 0019 DHNDL_IDX equ word ptr 19h ; 19 - relative cluster within file of last + read += 001B DHNDL_DBLK equ word ptr 1Bh ; 1B - cluster # of dir entry += 001E DHNDL_DCNTHI equ byte ptr 1Eh ; 1E - dir offset # within cluster += 001F DHNDL_DCNTLO equ byte ptr 1Fh ; 1F - dir offset # within cluster += 0020 DHNDL_NAME equ byte ptr 20h ; 20 - File/Device Name += 0028 DHNDL_EXT equ byte ptr 28h ; 28 - File extension += 002B DHNDL_SFT equ dword ptr 2Bh ; 2B - pointer to previous SFT += 002F DHNDL_UID equ word ptr 2Fh ; 2F - Owning Machine ID += 0031 DHNDL_PSP equ word ptr 31h ; 31 - Owning PSP += 0033 DHNDL_SHARE equ word ptr 33h ; 33 - Offset of sharing record += 0035 DHNDL_BLK equ word ptr 35h ; 35 - absolute cluster of last read += ; 37 - dword reserved for IFS += 003B DHNDL_LEN equ 3Bh += += ; With DOS 3 structures _DBLK is a 16 bit += += += ; Logical Drive Table format += 0000 LDT_NAME equ byte ptr 00h ; 00 - Ascii Name field += 0043 LDT_FLAGS equ word ptr 43h ; 43 - Flag field += 0045 LDT_PDT equ dword ptr 45h ; 45 - PDT for this drive += 0049 LDT_BLK equ word ptr 49h ; 49 - directory sector += 004B LDT_ROOT equ word ptr 4bh ; 4B - virtual block root += 004D LDT_DRV equ byte ptr 4dh ; 4D - physical drive += 004F LDT_ROOTLEN equ word ptr 4fh ; 4F - Length of root portion += 0058 LDT_LEN equ 58h += += 8000 LFLG_NETWRKD equ 8000h += 4000 LFLG_PHYSICAL equ 4000h += 2000 LFLG_JOINED equ 2000h += 1000 LFLG_SUBST equ 1000h + + + 0001 CIO_CTLP equ 0000$0001b ; Printer Echo State + 0002 CIO_HANDLE equ 0000$0010b ; use handle rather than Int 29 + 0004 CIO_RAW equ 0000$0100b ; no "cooked_status" checks + + 0050 CHECK_EVERY equ 80 ; check keyboard every "n" characters + + PCM_CODE CSEG BYTE + extrn char_error:near + extrn device_driver:near + extrn dos_entry:near + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 28 + + + extrn get_dseg:near + extrn ifn2dhndl:near + extrn int21_entry:near + extrn int21_func:near + extrn read_line:near + extrn ReadTimeAndDate:near + extrn reload_registers:near + + ; ***************************** + ; *** DOS Function 01 *** + ; *** Keybd Input W/Echo *** + ; ***************************** + ; + Public func01 + func01: + ; + ; Entry: + ; AH == 01h + ; Exit: + ; AL == char + ; + 0000 E85E00 0061 call func08 ; Read 1 character from Standard Input + ; and check for Control-C + 0003 92 xchg ax,dx ; echo using common code + + ; ***************************** + ; *** DOS Function 02 *** + ; *** Display Output *** + ; ***************************** + ; + Public func02 + func02: + ; + ; Entry: + ; AH == 02h + ; DL == char to display + ; + 0004 52 push dx ; char on stack + 0005 1607 push ss ! pop es + 0007 8BF4 mov si,sp ; ES:DX -> character + 0009 B90100 mov cx,1 + 000C E8C801 01D7 call stdout_cooked_write ; write character + 000F 58 pop ax ; recover char + 0010 C3 ret + + ; ***************************** + ; *** DOS Function 03 *** + ; *** Auxiliary Input *** + ; ***************************** + ; + Public func03 + func03: + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 29 + + + ; + ; Entry: + ; AH == 03h + ; Exit: + ; AL == Char + ; + 0011 BB0300 mov bx,STDAUX ; Read 1 character from Standard AUX + f03_10: + 0014 E99301 01AA jmp raw_read + + ; ***************************** + ; *** DOS Function 04 *** + ; *** Auxiliary Output *** + ; ***************************** + ; + Public func04 + func04: + ; + ; Entry: + ; AH == 04h + ; DL == Character to output + ; + 0017 BB0300 mov bx,STDAUX ; write the character passed in DL + 001A EB03 001F jmps f456common ; to the STDAUX Handle + + ; ***************************** + ; *** DOS Function 05 *** + ; *** Printer Output *** + ; ***************************** + ; + Public func05 + func05: + ; + ; Entry: + ; AH == 05h + ; DL == character to output to printer + ; + 001C BB0400 mov bx,STDPRN ; write the character passed in DL + ; jmp f456common ; to the STDPRN Handle + + f456common: + 001F 92 xchg ax,dx ; character in AL + ; jmp hndl_write + + hndl_write: + ;---------- + ; On Entry: + ; AL = character to write + ; BX = handle + ; On Exit: + ; AL preserved + ; + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 30 + + + 0020 E8B203 03D5 call is_device ; Does this handle refer to a device + 0023 720B 0030 jc hndl_w10 + 0025 26F744041000 test es:DH_ATTRIB[si],DA_SPECIAL + 002B 7403 0030 jz hndl_w10 ; Fast Console Output Using Int 29? + 002D CD29 int 29h ; This device supports FAST console + 002F C3 ret ; output so write this using Int29 + + hndl_w10: + 0030 50 push ax ; character on stack + 0031 8BD4 mov dx,sp ; SS:DX -> char + 0033 B90100 mov cx,1 ; do a single character + 0036 7205 003D jc hndl_w20 ; was it a file ? + 0038 E8AF02 02EA call device_write ; send to device driver + 003B EB07 0044 jmps hndl_w30 + hndl_w20: + 003D 1607 push ss ! pop es ; ES:DX -> character + 003F B440 mov ah,MS_X_WRITE ; otherwise call the FDOS to do all + 0041 E80000 E call dos_entry ; the hard work + hndl_w30: + 0044 58 pop ax + 0045 C3 ret + + + ; ***************************** + ; *** DOS Function 06 *** + ; *** Direct Console I/O *** + ; ***************************** + ; + Public func06 + func06: + ; + ; Entry: + ; AH == 06h + ; DL == 0FFh or Output char + ; Exit: + ; AL == Input char, if DL was 0FFh on input + ; + 0046 BB0100 mov bx,STDOUT ; Assume output DL to console + 0049 80FAFF cmp dl,0FFH ; or is it input ? + 004C 75D1 001F jne f456common + 004E 4B dec bx + ; mov bx,STDIN ; is there a character ready + 004F E8D302 0325 call char_check ; to be input + 0052 7405 0059 jz func07 + 0054 B80004 mov ax,RHS_IC ; set AL=0 and also set ZF on + 0057 EB0E 0067 jmps funcICexit ; exit as incomplete char + + + ; ***************************** + ; *** DOS Function 07 *** + ; *** Raw Input w/o echo *** + ; ***************************** + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 31 + + + ; + Public func07 + func07: + ; + ; Entry: + ; AH == 07h + ; Exit: + ; AL == character + ; + 0059 BB0000 mov bx,STDIN + 005C E84B01 01AA call raw_read ; extra status call made + 005F EB06 0067 jmps funcICexit ; set incomplete char + + ; ***************************** + ; *** DOS Function 08 *** + ; *** Input w/o echo *** + ; ***************************** + ; + Public func08 + func08: + ; + ; Entry: + ; AH == 08h + ; Exit: + ; AL == character + ; + 0061 BB0000 mov bx,STDIN ; Read 1 character from Standard Input + 0064 E84D01 01B4 call cooked_read + funcICexit: + ; exit point for incomplete character support + ; On Entry: + ; AL = character + ; AH = request header status (RHS_IC as on return from device driver) + ; On Exit: + ; AL = character + ; dos_FLAGS ZF set if incomplete character + ; + 0067 C43E0000 E les di,int21regs_ptr ; point to callers registers + 006B 26816516BFFF and es:reg_FLAGS[di],not ZERO_FLAG ; clear ZF + 0071 F6C404 test ah,RHS_IC/256 ; is it an incomplete char ? + 0074 7406 007C jz funcIC10 ; no - exit + 0076 26814D164000 or es:reg_FLAGS[di],ZERO_FLAG ; yes - set ZF + funcIC10: + 007C C3 ret + + ; ***************************** + ; *** DOS Function 09 *** + ; *** Print String *** + ; ***************************** + ; + Public func09 + func09: + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 32 + + + ; + ; Entry: + ; AH == 09h + ; DS:DX == address of character string + ; + + 007D B024 mov al,'$' ; it's terminated with a '$' + 007F 8BFA mov di,dx ; locate the end of the string + 0081 B9FFFF mov cx,0FFFFh ; and calculate its length + 0084 F2AE repnz scasb + 0086 F7D1 not cx + 0088 49 dec cx ; CX is the character count + 0089 8BF2 mov si,dx + 008B E84901 01D7 call stdout_cooked_write ; ES:SI -> character buffer + 008E B024 mov al,'$' + 0090 C3 ret + + + ; ***************************** + ; *** DOS Function 0A *** + ; *** Read String *** + ; ***************************** + ; + Public func0A + func0A: + ; + ; Entry: + ; AH == 0Ah + ; DS:DX == pointer to input buffer + ; + 0091 BB0000 mov bx,STDIN ; Read the editted line from STDIN + 0094 B90100 mov cx,STDOUT ; and display the results on STDOUT + 0097 E90000 E jmp read_line ; Read the Line + + ; ***************************** + ; *** DOS Function 0B *** + ; *** Console Status *** + ; ***************************** + ; + Public func0B + func0B: + ; + ; Entry: + ; AH == 0Bh + ; Exit: + ; AL == 0FFh if char available + ; == 00h otherwise + ; + 009A BB0000 mov bx,STDIN + 009D E8AD00 014D call cooked_status ; Get the current handle status + 00A0 B0FF mov al,0FFh ; Assume that the handle is ready + 00A2 7402 00A6 jz f0B_exit ; and return 0FFh in AL + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 33 + + + 00A4 B000 mov al,00 ; Not Ready + f0B_exit: + 00A6 EBBF 0067 jmps funcICexit ; exit thru incomplete char support + + + + ; ***************************** + ; *** DOS Function 0C *** + ; *** Flush and Execute *** + ; ***************************** + ; + Public func0C + func0C: + ; + ; Entry: + ; AH == 0Ch + ; AL == function to execute: 1,6,7,8 or A + ; Exit: + ; AL = 0 if function in AL is invalid + ; + 00A8 50 push ax ; save sub-function + 00A9 BB0000 mov bx,STDIN ; Is this Standard Input Handle a + 00AC E82603 03D5 call is_device ; file or device. Do not flush the + 00AF 720A 00BB jc f0C_20 ; buffer contents for a FILE + f0C_10: + 00B1 E8DB02 038F call hndl_instat ; check if any characters are left + 00B4 7505 00BB jnz f0C_20 ; and quit when buffer empty + 00B6 E8F100 01AA call raw_read ; read the character + 00B9 EBF6 00B1 jmps f0C_10 ; loop till the buffer is empty + + f0C_20: + 00BB 58 pop ax + 00BC 3C01740C 00CC cmp al,01h ! je al_ok ; is legal for this command + 00C0 3C0A7408 00CC cmp al,0ah ! je al_ok + 00C4 3C06720C 00D4 cmp al,06h ! jb al_nogo + 00C8 3C087708 00D4 cmp al,08h ! ja al_nogo + + al_ok: ; Valid function so now execute + 00CC E80000 E call reload_registers ; all register reloaded as per entry + 00CF 8AE0 mov ah,al ; Get the requested sub-function in AH + 00D1 E90000 E jmp int21_func ; execute the function + + al_nogo: ; Illegal command to execute + 00D4 33C0 xor ax,ax ; from this function so return error + 00D6 C3 ret + + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 34 + + + eject + ; + ; BREAK_CHECK checks for a CNTRL-C and is called by functions 01h to + ; 0Ch. Or by the entry code if the break flag is non zero. + ; + Public break_check + break_check: + 00D7 803E000001 E cmp indos_flag,01 ; Skip the check if we are + 00DC 7513 00F1 jnz break_c15 ; already in the emulator + 00DE 50 push ax + 00DF 06 push es + 00E0 56 push si + 00E1 C4360000 E les si,con_device + 00E5 E8B502 039D call device_instat ; get the input status + 00E8 5E pop si + 00E9 07 pop es + 00EA 7504 00F0 jnz break_c10 ; No Character Ready + 00EC 3C03 cmp al,CTLC ; Is the character a Control-C + 00EE 7402 00F2 jz break_c20 ; Yes + break_c10: + 00F0 58 pop ax + break_c15: + 00F1 C3 ret + + break_c20: ; The User has Typed Control-C so flush + 00F2 BBFFFF mov bx,0FFFFh ; input buffer (FFFF=con_device) + 00F5 E8C400 01BC call char_get + go_int23: + 00F8 0E07 push cs ! pop es ; ES:DX -> Character Buffer + 00FA BE0000 R mov si,offset cntrl_c_msg ; Message Offset + 00FD B90400 mov cx,length cntrl_c_msg ; Message Length + 0100 E8D400 01D7 call stdout_cooked_write ; write the ^C String to console + ; + ; Prepare to execute an Interrupt 23 (Break Check) and process + ; the return values. If the called routine returns with an IRET + ; or with a RETF and the carry flag reset continue the function + ; otherwise Abort. + ; + 0103 8E060000 E mov es,current_psp ; Get the Entry SS and SP + 0107 26A12E00 mov ax,PSP_USERSP ; Get the Users Stack Pointer + 010B 051000 add ax,18 - 2 ; Compensate for the User Registers + 010E A30000 E mov break_sp,ax ; and save for RETF check + 0111 FA cli + 0112 FE0E0000 E dec indos_flag ; Exit the PCDOS emulator + 0116 268E163000 mov ss,PSP_USERSS ; Switch to the Users Stack + 011B 268B262E00 mov sp,PSP_USERSP ; and Restore the registers + + 0120 585B595A5E5F POP$DOS ; Update the registers then + 5D1F07 + ; set the flags and return + ; to the user + 0129 F8 clc ; Default to continue function + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 35 + + + 012A CD23 int 23h ; Call the Break Handler + 012C FA cli ; Check the Flag State + 012D 730D 013C jnc do23_10 ; If CARRY then Abort this process + 012F E80000 E call get_dseg ; Get our data segment + 0132 C606000001 E mov exit_type,TERM_BREAK ; Force EXIT_TYPE to TERM_BREAK + 0137 B8004C mov ax,4C00h ; "Good-Bye Cruel World" + 013A EB0B 0147 jmps do23_20 + do23_10: + 013C 1E push ds ; Otherwise restart the aborted func + 013D E80000 E call get_dseg + 0140 3B260000 E cmp sp,break_sp + 0144 1F pop ds ; Restore the the USER DS correct + 0145 7403 014A jz do23_30 ; Did we Use a RETF or Not + do23_20: + 0147 83C402 add sp,2 ; Yes so correct the stack pointer + do23_30: ; and restart the aborted function + 014A E90000 E jmp int21_entry ; re-start the function call + + + + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 36 + + + eject + ; + ; cooked_status is called on input or output and looks for live keys ^C,^P,^S. + ; If any of these are found they are dealt with. + ; If ^P is encountered it is swallowed. + ; If ^C is encountered we always do an Int23. + ; If ^S is pressed we swallow it, and the next character (checking for ^C, but + ; not for ^P), then say a character is ready. + ; Note that this can lead to status calls (func0B) hanging inside the OS, + ; or the return of ^S characters from input calls (func01), but this is + ; intentional. + ; + + cooked_status: + ;------------- + ; check input + ; On Entry: + ; BX = handle to check + ; On Exit: + ; ZF set if character available + ; AL = character + ; AH = RHS_IC + ; + 014D E887FF 00D7 call break_check ; check for a ^C on console + 0150 E8D201 0325 call char_check ; is there a character ready + 0153 7542 0197 jnz cooked_s50 ; no so keep scanning + + 0155 803E000000 E cmp last_key_ext,0 ; was last char an zero ? + 015A C606000000 E mov last_key_ext,0 ; (clear flag for next time) + 015F 752B 018C jne cooked_s40 ; skip ^P,^S,^C checks if so + + 0161 3C10 cmp al,CTLP ; has the user typed ^P + 0163 750F 0174 jne cooked_s10 ; flush the buffer and + 0165 8036000001 E xor cio_state,CIO_CTLP ; toggle ^P flag + 016A E84F00 01BC call char_get ; flush the character from buffer + 016D E8A302 0413 call open_or_close_prn ; open/close printer device + 0170 85C0 test ax,ax ; ZF clear, ie. no char available + 0172 EB23 0197 jmps cooked_s50 + + cooked_s10: + 0174 3C03 cmp al,CTLC + 0176 7506 017E jnz cooked_s30 ; has the user typed ^C + 0178 E84100 01BC call char_get ; so get the RAW character + cooked_s20: + 017B E97AFF 00F8 jmp go_int23 ; and terminate the function + + cooked_s30: + 017E 3C13 cmp al,CTLS ; pause if the user has typed + 0180 750A 018C jnz cooked_s40 ; a ^S + 0182 E83700 01BC call char_get ; remove ^S and resume when + 0185 E81F00 01A7 call raw_read_wait ; the next character is typed + 0188 3C03 cmp al,CTLC + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 37 + + + 018A 74EF 017B je cooked_s20 ; has the user typed ^C + cooked_s40: + 018C 3C00 cmp al,0 + 018E 7505 0195 jne cooked_s45 + 0190 C606000001 E mov last_key_ext,1 + cooked_s45: + 0195 3BC0 cmp ax,ax ; ZF set, ie. char available + cooked_s50: + 0197 C3 ret + + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 38 + + + eject + ; + ; The COOKED, CMDLINE and RAW Read functions are basically the same + ; except in their treatment of 'live' characters ^C,^P, and ^S. + ; COOKED will look for and act upon all three live characters. + ; CMDLINE will look for and act upon ^C and ^P, but ^S will be returned + ; so we can use it as a line editing key. + ; RAW will not check for any live keys. + ; + public cmdline_read, raw_read ; for CMDLINE.PCM + + cmdline_read_wait: ; Waiting for a device to become + 0198 E81701 02B2 call idle_dev ; ready. So call IDLE routines to + ; put the processor to sleep. + cmdline_read: + 019B E839FF 00D7 call break_check ; check for a ^C on console + 019E E88401 0325 call char_check ; is there a character ready + 01A1 75F5 0198 jnz cmdline_read_wait ; no so keep scanning + 01A3 3C13 cmp al,CTLS ; if the user has typed ^S + 01A5 750D 01B4 jne cooked_read ; we have to do a raw read + ; jmps raw_read ; else we do a cooked read + + raw_read_wait: ; Waiting for a device to become + 01A7 E80801 02B2 call idle_dev ; ready. So call IDLE routines to + ; put the processor to sleep. + raw_read: + 01AA E87801 0325 call char_check ; Is there a character Ready + 01AD 75F8 01A7 jnz raw_read_wait ; loop until character available + 01AF EB0B 01BC jmps char_get + + cooked_read_wait: ; Waiting for a device to become + 01B1 E8FE00 02B2 call idle_dev ; ready. So call IDLE routines to + ; put the processor to sleep. + cooked_read: + 01B4 E820FF 00D7 call break_check ; check for a ^C on console + 01B7 E893FF 014D call cooked_status ; check for a ^S,^P,^C on handle BX + 01BA 75F5 01B1 jnz cooked_read_wait ; wait until char is available + ; jmps char_get ; else get the character + + char_get: + 01BC 0650 push es ! push ax ; Input one character and + 01BE 8BD4 mov dx,sp ; return it in AL + 01C0 E81202 03D5 call is_device ; Does this handle refer to a device + 01C3 B90100 mov cx,1 + 01C6 7206 01CE jc char_get30 ; if it's a device then + 01C8 E81B01 02E6 call device_read ; use device_read + char_get20: + 01CB 5807 pop ax ! pop es + 01CD C3 ret + + char_get30: + ; We are redirected, so call to the FDOS to get a character + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 39 + + + 01CE 1607 push ss ! pop es ; EX:DX -> character to read + 01D0 B43F mov ah,MS_X_READ ; call the FDOS to do all + 01D2 E80000 E call dos_entry ; the hard work + 01D5 EBF4 01CB jmps char_get20 + + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 40 + + + eject + + stdout_cooked_write: + 01D7 BB0100 mov bx,STDOUT ; output to the console device + ; jmp cooked_write + + ; + ; The COOKED_WRITE routine will expand TABS etc in the string + ; passed passed by the calling routine. + ; + ; On Entry: + ; ES:SI Buffer Address + ; CX Character Count + ; BX Output Handle + ; On Exit: + ; AL = last char written + ; + Public cooked_write + cooked_write: + 01DA 06 push es + 01DB 53 push bx + 01DC 8A260000 E mov ah,cio_state ; get CIO_CTLP status + 01E0 80CC06 or ah,CIO_RAW+CIO_HANDLE ; assume we will want raw handle output + 01E3 8AC3 mov al,bl + 01E5 F606010080 E test byte ptr remote_call+1,DHM_FCB/100h + 01EA 7513 01FF jnz cook_w03 + 01EC 8E060000 E mov es,current_psp ; get our PSP + 01F0 263B1E3200 cmp bx,PSP_XFNMAX ; range check our handle + 01F5 7333 022A jae cook_w05 + 01F7 26C43E3400 les di,PSP_XFTPTR + 01FC 268A01 mov al,es:byte ptr [bx+di] ; AL = Internal File Handle + cook_w03: + 01FF E80000 E call ifn2dhndl ; ES:BX -> DHNDL_ + 0202 7226 022A jc cook_w05 ; skip if bad handle + 0204 268B5705 mov dx,es:DHNDL_WATTR[bx] ; get handle attributes + 0208 81E2A380 and dx,DHAT_DEV+DHAT_CIN+DHAT_COT+DHAT_BIN+DHAT_REMOTE + 020C 81FAA300 cmp dx,DHAT_DEV+DHAT_CIN+DHAT_COT+DHAT_BIN + 0210 7409 021B je cook_w04 ; accept binary console device + 0212 81FA8300 cmp dx,DHAT_DEV+DHAT_CIN+DHAT_COT + 0216 7512 022A jne cook_w05 ; skip if not cooked console device + 0218 80E4FB and ah,not CIO_RAW ; we want cooked output + cook_w04: + 021B 26C45F07 les bx,es:DHNDL_DEVPTR[bx] ; its the console - but is it FAST ? + 021F 26F747041000 test es:DH_ATTRIB[bx],DA_SPECIAL + 0225 7403 022A jz cook_w05 ; skip if not + 0227 80E4FD and ah,not CIO_HANDLE ; don't use handle functions + cook_w05: + 022A 5B pop bx + 022B 07 pop es + 022C E34F 027D jcxz cook_w80 + cook_w10: + 022E 26AC lods es:al ; Read the next character + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 41 + + + 0230 3C7F7444 0278 cmp al,DEL ! je cook_w60 ; DEL is a NON Printing Character + 0234 3C20733C 0274 cmp al,' ' ! jae cook_w50 ; Space and Above are Normal + 0238 3C0A743C 0278 cmp al,LF ! je cook_w60 ; Just print LineFeeds + 023C 3C1B7438 0278 cmp al,ESC ! je cook_w60 ; Just print Escape + 0240 3C077434 0278 cmp al,BELL! je cook_w60 ; Just ring the Bell + 0244 3C0D750C 0254 cmp al,CR ! jne cook_w20 ; CR zeros the column number + 0248 C606000000 E mov column,0 + 024D C606000001 E mov char_count,1 ; check for ^S etc NOW + 0252 EB24 0278 jmps cook_w60 + cook_w20: + 0254 3C087506 025E cmp al,CTLH ! jne cook_w30 ; BackSpace decrements the + 0258 FE0E0000 E dec column ; column count by one + 025C EB1A 0278 jmps cook_w60 + cook_w30: + 025E 3C097516 0278 cmp al,TAB ! jne cook_w60 ; is it a TAB ? + cook_w40: + 0262 B020 mov al,' ' ; spaces + 0264 E81700 027E call cooked_out ; output a space char + 0267 FE060000 E inc column + 026B F606000007 E test column,7 ; are we at a TAB stop yet ? + 0270 75F0 0262 jnz cook_w40 + 0272 EB07 027B jmps cook_w70 + cook_w50: + 0274 FE060000 E inc column ; Update the column count and + cook_w60: + 0278 E80300 027E call cooked_out ; output the character + cook_w70: + 027B E2B1 022E loop cook_w10 ; onto the next character + cook_w80: + 027D C3 ret + + cooked_out: + ; On Entry: + ; AH = handle status + ; AL = character + ; BX = handle + ; On Exit: + ; AX, BX, CX, ES:SI preserved + ; + 027E FE0E0000 E dec char_count ; time to check keyboard input ? + 0282 7408 028C jz cooked_o10 ; no, skip status check + 0284 F6C403 test ah,CIO_HANDLE+CIO_CTLP ; is it complicated ? + 0287 7503 028C jnz cooked_o10 + 0289 CD29 int 29h ; This device supports FAST console + 028B C3 ret + + cooked_o10: + 028C 06 push es + 028D 50 push ax + 028E 51 push cx + 028F 56 push si + 0290 E88DFD 0020 call hndl_write ; display the character + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 42 + + + 0293 F6C401 test ah,CIO_CTLP ; Check for Printer Echo + 0296 7408 02A0 jz cooked_o20 ; Off so No Echo + 0298 53 push bx ; Save Output Handle + 0299 BB0400 mov bx,STDPRN ; and output the same data to the + 029C E881FD 0020 call hndl_write ; to the Printer Handle + 029F 5B pop bx + cooked_o20: + 02A0 F6C404 test ah,CIO_RAW ; is it a cooked console ? + 02A3 7508 02AD jnz cooked_o30 ; skip check if not + 02A5 E8A5FE 014D call cooked_status ; look for keyboard input + 02A8 C606000050 E mov char_count,CHECK_EVERY ; look again in a while + cooked_o30: + 02AD 5E pop si + 02AE 59 pop cx + 02AF 58 pop ax + 02B0 07 pop es + 02B1 C3 ret + + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 43 + + + eject + ; IDLE_DEV is called when the PCMODE is waiting for a character. + ; This routine must determine if the request is for a device or not + ; and call the IDLE interface for device requests to the system can be + ; put to sleep until a character is ready. + ; + ; On Entry:- BX Handle Number + ; + idle_dev: + 02B2 53 push bx ; preserve handle + 02B3 B80084 mov ax,8400h + 02B6 CD2A int 2ah ; Server hook for idle + 02B8 FE0E0000 R dec clock_count + 02BC 7503 02C1 jnz idle_dev10 ; Zero if NO skip delay and execute + 02BE E80000 E call ReadTimeAndDate ; for PC BIOS's who must read every day + idle_dev10: + if IDLE_DETECT + 02C1 F706000000C0 E test idle_flags,IDLE_DISABLE ; Has Idle Checking been enabled + 02C7 751B 02E4 jnz idle_dev40 ; Skip if NO + 02C9 0656 push es ! push si + 02CB E80701 03D5 call is_device ; The requested handle a file or device + 02CE 7212 02E2 jc idle_dev30 ; File Access skip IDLE + 02D0 B80300 mov ax,PROC_KEYIN ; Assume this is the REAL Console + 02D3 26F744040100 test es:DH_ATTRIB[si],DA_ISCIN; Test Attribute Bits + 02D9 7503 02DE jnz idle_dev20 ; Yes this is Default Console Device + 02DB B80400 mov ax,PROC_DEVIN ; Input from Another Device + idle_dev20: + 02DE FF1E0000 E callf idle_vec ; Call the IDLE Handler + idle_dev30: + 02E2 5E07 pop si ! pop es + idle_dev40: + endif + 02E4 5B pop bx ; recover handle + 02E5 C3 ret + + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 44 + + + eject + ; The following routine reads CX bytes from the device whose address + ; is held in the DWORD pointer passed by DS:SI. A Request Header + ; is built on the stack and the command is executed. + ; + ; On Entry: + ; ES:SI DWORD Pointer to Device Header + ; SS:DX Buffer Address + ; CX Character Count + ; + ; On Exit: + ; AX Request Header Status + ; Zero No Error + ; + Public device_read + device_read: + 02E6 B004 mov al,CMD_INPUT ; we want input + 02E8 EB02 02EC jmps device_common ; now use common code + + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 45 + + + eject + ; The following routine writes CX bytes to the device whose address + ; is held in the DWORD pointer passed by DS:SI. A Request Header + ; is built on the stack and the command is executed. + ; + ; On Entry: + ; ES:SI DWORD Pointer to Device Header + ; SS:DX Buffer Address + ; CX Character Count + ; + ; On Exit: + ; AX Request Header Status + ; Zero No Error + ; + Public device_write + device_write: + 02EA B008 mov al,CMD_OUTPUT ; we want output + device_common: + 02EC 53 push bx + 02ED 83EC1E sub sp,RH4_LEN ; reserve space on the stack + 02F0 8BDC mov bx,sp ; request header offset + 02F2 36C6071E mov ss:RH_LEN,RH4_LEN ; request header length + 02F6 3689570E mov ss:RH4_BUFOFF,dx ; buffer offset + 02FA 368C5710 mov ss:RH4_BUFSEG,ss ; buffer segment + device_common10: + 02FE 36894F12 mov ss:RH4_COUNT,cx ; character count + 0302 E8B300 03B8 call device_req ; execute command + 0305 7916 031D jns device_common20 ; if no errors return to the caller + 0307 362B4F12 sub cx,ss:RH4_COUNT ; CX = chars remaining + 030B 50 push ax ; save the error code + 030C E80000 E call char_error ; ask int 24 what to do + 030F 3C01 cmp al,ERR_RETRY ; should we retry the operation ? + 0311 58 pop ax ; recover the error code + 0312 7709 031D ja device_common20 ; Fail/Abort return error + 0314 368A4702 mov al,ss:RH_CMD ; reload the command + 0318 74E4 02FE je device_common10 ; Retry, re-issue the device request + 031A B80001 mov ax,RHS_DONE ; Ignore, pretend no errors + device_common20: + 031D 83C41E add sp,RH4_LEN ; restore the stack to its normal + 0320 A90080 test ax,RHS_ERROR ; state and return the status. + 0323 5B pop bx + 0324 C3 ret + + + char_check: + ; On Entry: + ; BX = handle to check + ; On Exit: + ; ZF set if character ready + ; AL = character (if device handle) + ; AH = RIC status + ; + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 46 + + + 0325 53 push bx ; Save the current handle status + if IDLE_DETECT + 0326 F706000000C0 E test idle_flags,IDLE_DISABLE ; Has Idle Checking been enabled + 032C 7513 0341 jnz char_check10 ; Skip if NO + 032E FF0E0000 E dec int28_delay ; Has the INT28 Loop count reached + 0332 750D 0341 jnz char_check10 ; Zero if NO skip delay and execute + 0334 A10000 E mov ax,int28_reload ; INT28. Otherwise DELAY/DISPATCH + 0337 A30000 E mov int28_delay,ax + 033A B80200 mov ax,PROC_INT28 ; Process is IDLE + 033D FF1E0000 E callf idle_vec ; Call the IDLE Handler + char_check10: + endif + 0341 803E000001 E cmp indos_flag,1 ; Only execute an INT 28 + 0346 7546 038E jnz char_check20 ; when the INDOS flag is 1 + 0348 803E0000FF E cmp int28_flag,TRUE ; Only generate INT 28s for the + 034D 753F 038E jnz char_check20 ; selected functions + + 034F FF360000 E push remote_call + 0353 FF360000 E push machine_id + 0357 8E060000 E mov es,current_psp ; Get the PSP + 035B 26FF362E00 push PSP_USERSP ; Save the SS:SP pointer to + 0360 26FF363000 push PSP_USERSS ; the register image + + if IDLE_DETECT ; Set IDLE_INT28 so $IDLE$ knows + 0365 810E00000400 E or idle_flags,IDLE_INT28 ; that we are nolonger inside DOS + endif + 036B CD28 int 28h ; Execute an INT 28 for SideKick and + ; the PRINT utility. INDOS flag is 1 + + if IDLE_DETECT ; Reset IDLE_INT28 so $IDLE$ knows + 036D 81260000FBFF E and idle_flags,not IDLE_INT28; that we are back DOS + endif + 0373 C6060000FF E mov int28_flag,TRUE ; Restore INT28_FLAG + 0378 8E060000 E mov es,current_psp ; Get the PSP + 037C 268F063000 pop PSP_USERSS ; Restore the SS:SP pointer to + 0381 268F062E00 pop PSP_USERSP ; the register image + 0386 8F060000 E pop machine_id + 038A 8F060000 E pop remote_call + char_check20: + 038E 5B pop bx + ; jmp hndl_instat ; Check Input Status. ZERO == Ready + + ; + ; + hndl_instat: + 038F E84300 03D5 call is_device ; Does this handle refer to a device + 0392 7309 039D jnc device_instat + 0394 B80644 mov ax,(MS_X_IOCTL shl 8)+6 ; Get the file status + 0397 E80000 E call dos_entry ; for the specified handle + 039A 3CFF cmp al,0FFh ; and return ZERO until the EOF + 039C C3 ret + + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 47 + + + ; The following routine executes the Non Destructive Input + ; command to the device whose address passed in ES:SI. + ; + ; On Entry: + ; ES:SI DWORD Pointer to Device Header + ; + ; On Exit: + ; Zero Character Ready + ; AH Top Byte Request Header Status + ; AL Next Character if ZERO + ; + + device_instat: + 039D 53 push bx + 039E 83EC0E sub sp,RH5_LEN ; Reserve Space on the Stack + 03A1 8BDC mov bx,sp ; Request Header Offset + 03A3 36C6070E mov ss:RH_LEN,RH5_LEN ; Set Request Header Length + 03A7 B005 mov al,CMD_INPUT_NOWAIT ; Command Number + 03A9 E80C00 03B8 call device_req ; Execute the Command + 03AC 368A470D mov al,ss:RH5_CHAR ; Assume a character is ready + 03B0 83C40E add sp,RH5_LEN ; Restore the Stack to its normal + 03B3 A90002 test ax,RHS_BUSY ; state and return the status. + 03B6 5B pop bx ; Zero if a Character is ready + 03B7 C3 ret + + ; The following routine handles the low level device interface to + ; the character device drivers. All the generic Request Header + ; initialization is carried out here. + ; + ; On Entry: + ; AL Command + ; ES:SI Device Header + ; SS:BX Current Request Header + ; + ; On Exit: + ; AX Request Header Status + ; + + device_req: + ;---------- + 03B8 36884702 mov ss:RH_CMD,al ; save the command + 03BC 1E push ds + 03BD 06 push es + 03BE 061F push es ! pop ds ; DS:SI -> device driver + 03C0 368E060000 E mov es,ss:current_psp ; es = current PSP + 03C5 26A03C00 mov al,es:PSP_RIC ; al = Return Interim Character flag + 03C9 3688470D mov ss:RH4_RIC,al ; Return Interim Char flag + 03CD 1607 push ss ! pop es ; ES:BX -> RH_ + 03CF E80000 E call device_driver + 03D2 07 pop es + 03D3 1F pop ds + 03D4 C3 ret + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 48 + + + + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 49 + + + eject + ; + ; IS_DEVICE checks the internal handle structures to determine + ; if the handle referenced in BX is a file or device. Invalid + ; handles all map to the default console device. + ; + ; On Entry: + ; BX Handle Number + ; + ; On Exit: + ; CY set if handle is for a file + ; CY clear if handle is for device at ES:SI + ; + is_device: + 03D5 50 push ax + 03D6 53 push bx ; Convert the Standard Handle number + 03D7 8BC3 mov ax,bx ; get XFN in AL + ; mov cx,current_psp ; into an internal handle number + ; jcxz is_dev10 ; no PSP, we have IFN already + ; mov es,cx + 03D9 F606010080 E test byte ptr remote_call+1,DHM_FCB/100h; if FCB initiated access + 03DE 7513 03F3 jnz is_dev10 ; we have IFN already + 03E0 8E060000 E mov es,current_psp + 03E4 263B1E3200 cmp bx,es:PSP_XFNMAX ; Check if the handle is in range for + 03E9 7322 040D jae is_dev_bad ; this PSP. + 03EB 26C4363400 les si,es:PSP_XFTPTR + 03F0 268A00 mov al,es:byte ptr [bx+si] ; AL = Internal File Handle + is_dev10: + 03F3 E80000 E call ifn2dhndl ; ES:BX -> DHNDL_ + 03F6 7215 040D jc is_dev_bad + 03F8 268B4705 mov ax,es:DHNDL_WATTR[bx] ; get file attributes + 03FC 258080 and ax,DHAT_REMOTE+DHAT_DEV + 03FF 3D8000 cmp ax,DHAT_DEV ; is it a local device ? + 0402 F9 stc ; assume it's a file + 0403 7505 040A jne is_dev30 + 0405 26C47707 les si,es:DHNDL_DEVPTR[bx] ; its a device + is_dev20: + 0409 F8 clc + is_dev30: + 040A 5B pop bx + 040B 58 pop ax + 040C C3 ret + + is_dev_bad: + 040D C4360000 E les si,con_device ; bad handles map to console + 0411 EBF6 0409 jmps is_dev20 + + open_or_close_prn: + ;----------------- + ; called when CIO_CTLP toggled - call prn device with Open or Close as appropri + ; + 0413 1E5053 push ds ! push ax ! push bx + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 50 + + + 0416 B81000 mov ax,CTLP + 0419 50 push ax ; ^P on stack + 041A 8B0E0000 E mov cx,current_psp ; look in PSP + 041E E36C 048C jcxz oc_prn30 ; no PSP, forget it + 0420 8EC1 mov es,cx + 0422 263B1E3200 cmp bx,PSP_XFNMAX ; Check if the handle is in range for + 0427 7363 048C jae oc_prn30 ; this PSP. + 0429 26C4363400 les si,es:PSP_XFTPTR ; for the internal handle number + 042E 268A4404 mov al,es:byte ptr STDPRN[si] + 0432 3CFF cmp al,0FFh ; AL = Internal File Handle + 0434 7456 048C je oc_prn30 ; skip if invalid Handle Number + 0436 E80000 E call ifn2dhndl ; ES:BX -> doshndl + 0439 7251 048C jc oc_prn30 + 043B 26F747050008 test es:DHNDL_WATTR[bx],DHAT_NETPRN + 0441 7413 0456 jz oc_prn10 + 0443 B82611 mov ax,I2F_CTLP ; turn on the network printer + 0446 CD2F int 2fh ; with a magic INT 2F call + 0448 730C 0456 jnc oc_prn10 + 044A 80260000FE E and cio_state,not CIO_CTLP ; make sure Printer Echo is off + 044F B82411 mov ax,I2F_CTLP_ERR + 0452 CD2F int 2fh + 0454 EB36 048C jmps oc_prn30 + oc_prn10: + 0456 268B4705 mov ax,es:DHNDL_WATTR[bx] ; get file attributes + 045A 258080 and ax,DHAT_REMOTE+DHAT_DEV + 045D 3D8000 cmp ax,DHAT_DEV ; is it a local device ? + 0460 752A 048C jne oc_prn30 + 0462 B00D mov al,CMD_DEVICE_OPEN ; assume we've just opened + 0464 F606000001 E test cio_state,CIO_CTLP ; Check for Printer Echo + 0469 7502 046D jnz oc_prn20 ; yes, skip next bit + 046B B00E mov al,CMD_DEVICE_CLOSE ; no, we must close + oc_prn20: + 046D 26C47707 les si,es:DHNDL_DEVPTR[bx] ; get the device driver address + 0471 26F744040008 test es:DH_ATTRIB[si],DA_REMOVE + 0477 7413 048C jz oc_prn30 ; no, skip call if not supported + 0479 83EC0D sub sp,RH13_LEN ; Reserve Space on the Stack + 047C 8BDC mov bx,sp ; and point to it + 047E 36C6070D mov ss:RH_LEN,RH13_LEN ; Set Request Header Length + 0482 36884702 mov ss:RH_CMD,al ; Command Number + 0486 E80000 E call device_driver ; issue the command + 0489 83C40D add sp,RH13_LEN ; Restore the Stack to its normal + oc_prn30: + 048C 58 pop ax ; discard ^P from stack + 048D 5B581F pop bx ! pop ax ! pop ds + 0490 C3 ret + + + PCM_RODATA CSEG WORD + + 0000 5E430D0A cntrl_c_msg db '^C', CR, LF ; Control-Break Message + + GLOBAL_DATA dseg + PC-DOS RASM-86 1.4a Source: CIO.A86 Page 51 + + + + 0000 00 clock_count db 0 + + PCMODE_DATA DSEG WORD + + extrn break_sp:word ; For Control-Break handler + extrn char_count:byte + extrn cio_state:byte ; Character I/O State + extrn column:byte ; Console Cursor Location + extrn con_device:dword ; Current Console Device + extrn current_psp:word ; Current PSP Address + extrn exit_type:byte + extrn last_key_ext:byte + extrn indos_flag:byte ; INDOS Count + extrn int21regs_ptr:dword ; pointer to callers registers + extrn machine_id:word + extrn remote_call:word + if IDLE_DETECT + extrn idle_flags:word ; IDLE State Flags + extrn idle_vec:dword ; IDLE routine Vector + extrn int28_delay:word + extrn int28_reload:word + extrn int28_flag:byte + endif + + end + + +End of assembly. Number of errors: 0. Use factor: 37% + if IDLE_DETECT + extrn idle_flags:word ; IDLE Sta \ No newline at end of file diff --git a/IBMDOS/BIN/CIO.OBJ b/IBMDOS/BIN/CIO.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..95941b43a8878f84be793ea79b9f87bcf9d4c434 GIT binary patch literal 2688 zcmc&#`)?dq6+U-nc4qeJSGE&y{h;D{}5=41PGxdz=VyURIL+S;^Ev~ zoBj#>a6R8W_dLFH&v(~lAMlA(?u93N0lm5rW?WWbZ#u3Zn`$j>^!SQlBuGu+5bzDY$8)15AM{&)C}7bDYK9>rg!WtTtYi5 z-OOj?7-S}P`jE(T* zZ|synn~(4CVPw=!rsLy8Oytt1 zGFj4Y=;>Ts!_4ET4&5+Gn0XE3-n8=tgZP=8^lZVHZp9DV>^g~@($czZ=?UW3i>ZQL zn9l1YyiHp(QkHIzKqj7;V6;;jk;nA{s$U-`!4?ZmPsgW;pLJ-n-iX|~4l|E+SZ+qs zB%zjfizW7!%i66XB$zm57)Z>{H$$?FXR|ebDw!S8CbC+Z`0?%9_#O*7X=9ZNsf-@a zYAAEP#bbE8HDR?39Dq9u&l*vw`rc~<++UGm{Sps1o+J3T!Cw;KS@$RWd{DWi3GGng z*YBz4t8b#`ywCkH*N~#p&+c~tFo-~T({rv&y1(U0z8VOP$R*4@Ng5*iW(Yk2pe%ki z`ntD4g_5W&W}^2)Y{d_iv811V&XO-NI$weM+WzY1Yo7P+k8WK_Ro`_}WNm*PQ((;- z04&!JVa+RXYtVQ-&$bFbA8`M`IX?Ga(AX%dq!dyEC0P~cL#ljMMs~}8#>m5$>t&=s zoUXiR(HI8)oST&#LFG#v()T=z-|*bu5NC{$Yx;q6P;GbG%1Dv8IdCs>Ph5U`Wf&-5Xro~(N_(tM zy3gvVj3(QtYK1CE{C>*nteDBY)V2ir8C;*YdS@8vdD6H`cE1E!&cS3rBPKX9Z|zhh_%$Z@Wy^sc0@Lt#vax0MArt~9_YszQ_hN3b|rVy zSxcl3T7*7oi7zl_4{=)dJV`D?Ry!@Gj(&DQ6b0;82dT;6Yq3=sMU`uG{&?Fn0CHfsgC>Z zE|))9hJQOgg`Sme&lKzIho!O6mp5zekgsB&*B&|dOQosw2e+d&LG?-&OK}o4?E|^g zRZ}|FKfVwu<9%$^_9Je@SoSAYdVvZ^DT-1Zwz}yF#M6i$wR)Y^ 65535 sector per drive += 0002 DA_ISCOT equ 0002h ; device is standard output device += 0001 DA_ISCIN equ 0001h ; device is standard input device += += 0029 FASTCON_INT equ 29h ; fast console output interrupt += + + + + PCM_CODE CSEG BYTE + public read_line, edit_size + + extrn dbcs_lead:near + extrn cmdline_read:near + extrn raw_read:near + extrn cooked_write:near + extrn get_dseg:near + extrn device_driver:near + + ; WARNING - the following routines are to support history buffers + ; As these are optional we muset NEVER call these routines unless + ; the HISTORY_ON bit is set in @hist_flag. + + extrn init_history:near + extrn save_history:near + extrn prev_cmd:near + extrn next_cmd:near + extrn match_cmd:near + extrn search_cmd:near + extrn match_word:near + extrn del_cur_history_buffer:near + extrn del_history_buffers:near + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 16 + + + extrn goto_eol:near + extrn next_word:near + extrn prev_word:near + extrn del_bol:near + extrn deln_word:near + + ; The following are public for HISTORY.PCM + public next_char, save_line + public space_out, bs_out, put_string + public goto_bol + public del_eol, del_line + public char_info + public prev_w20 + public deln_w10 + + + ; READ_LINE will read an editted line from the handle passed in BX + ; into a buffer with the following format:- + ; + ; BYTE Maximum String Length + ; BYTE Current String Length + ; BYTE(s) String Buffer + ; + ; On Entry:- + ; BX Input Handle + ; CX Output Handle + ; ES:DX Buffer Address + ; + ; On Exit:- + ; String input by user + ; + ; The following conventions apply for the READ_LINE function + ; + ; ES Buffer segment + ; SI Current cursor location in buffer (Index) + ; DX Last Character in Buffer (Index) + ; + 0080 DISABLE equ 80h ; Disable when advanced editing is off. + 8000 DISABLE_MASK equ 8000h + 0001 ESC_CODE equ 01h ; Scan code must be preceeded by escape byte. + 0000 NESC_CODE equ 00h ; No lead zero needed. + + read_line: + 0000 55 push bp ; Save the Stack Frame Pointer + 0001 8BEC mov bp,sp ; Intialise it to the top of the + 0003 83EC1C sub sp,RL_LENGTH ; READ_LINE control block and reserve + ; control block + 0006 895EFE mov RL_INPUT,bx ; Initialize the INPUT Handle + 0009 894EFC mov RL_OUTPUT,cx ; the OUTPUT Handle + 000C 4242 inc dx ! inc dx ; Skip max and Returned Length + 000E 8956F8 mov RL_BUFOFF,dx ; and save the buffer offset + 0011 8C46FA mov RL_BUFSEG,es ; and segment + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 17 + + + 0014 33C0 xor ax,ax ; now we zero + 0016 8946EC mov RL_SAVPOS,ax ; both position in it + 0019 8946EE mov RL_SAVMAX,ax ; and it's size + 001C A00000 E mov al,column + 001F 8946F6 mov RL_INICOL,ax ; save initial column + 0022 A10000 E mov ax,cle_state ; use to set initial editing state + 0025 25C7FF and ax,not (RLF_MATCH+RLF_DIRTY+RLF_RECALLED) + 0028 8946F4 mov RL_FLAGS,ax ; save in flags + 002B A90100 test ax,RLF_ENHANCED + 002E 7405 0035 jz read_line10 + 0030 E80000 E call init_history ; setup the history buffers + 0033 EB05 003A jmps read_line20 + read_line10: + 0035 8166F4FDFF and RL_FLAGS,not RLF_INS ; clear insert mode + read_line20: + 003A 8BFA mov di,dx ; di -> buffer + 003C 33DB xor bx,bx + 003E 260A5DFE or bl,es:byte ptr -2[di] ; Get the Maximum number of chars + 0042 895EF2 mov RL_MAXLEN,bx ; and save for later + 0045 7528 006F jnz read_line30 ; make sure some chars are requested + 0047 EB22 006B jmps ret_string10 ; if no chars just return + + ret_string: + 0049 58 pop ax ; Remove local return address + 004A 8B46F4 mov ax,RL_FLAGS ; get command line editor state + 004D A30000 E mov cle_state,ax ; save state for next time + 0050 8B7EF8 mov di,RL_BUFOFF ; Get the buffer Offset + 0053 268855FF mov es:byte ptr -1[di],dl ; Return the number of characters + 0057 52 push dx ; Save length of entry + 0058 03FA add di,dx ; Point to the end of the buffer + 005A B00D mov al,CR + 005C AA stosb ; Save CR + 005D E87C04 04DC call write_char ; Print a CR and return to the user + 0060 5A pop dx + 0061 F746F40100 test RL_FLAGS,RLF_ENHANCED ; Do not add to history if in + 0066 7403 006B jz ret_string10 ; compatibility mode + 0068 E80000 E call save_history ; Save state of history buffer + ret_string10: + 006B 8BE5 mov sp,bp ; Remove READ_LINE control Block + 006D 5D pop bp ; Restore BP and return to the caller + 006E C3 ret + + + read_line30: + 006F 33F6 xor si,si ; Currently at start of buffer + 0071 8BD6 mov dx,si ; with an empty buffer. + + 0073 33DB xor bx,bx + 0075 260A5DFF or bl,es:byte ptr -1[di] ; Check if the buffer contains any + 0079 7408 0083 jz read_line40 ; data which is terminated by a CR + 007B 2680390D cmp es:byte ptr [bx+di],CR + 007F 7502 0083 jnz read_line40 + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 18 + + + 0081 8BD3 mov dx,bx + read_line40: + 0083 E84803 03CE call save_line ; Update Save Buffer variables + 0086 8BD6 mov dx,si + ; + ; This is out main command loop - we get a character and try to match it + ; with a command in our edit_table. If History is on we look at commands + ; with the DISABLED bit set ie. enhanced commands. + ; It a match isn't found we insert the character in the buffer, and optionally + ; try to match with previous lines in the history buffer. + ; + read_line_loop: + 0088 8166F4BFFF and RL_FLAGS,not RLF_KANJI ; initial flags + 008D E86604 04F6 call get_char ; read the first character (AH Esc Flg) + + 0090 2E8B0E0100 R mov cx,edit_size ; now scan the control table looking + 0095 BB0300 R mov bx,offset edit_table ; for a match + read_ll_next_cmd: + 0098 25FF7F and ax,not DISABLE_MASK ; assume normal function + 009B F746F40100 test RL_FLAGS,RLF_ENHANCED ; compatibilty required? then it + 00A0 740A 00AC jz read_ll10 ; has to be a normal function + 00A2 2EF7070080 test EDIT_CNTRL,DISABLE_MASK ; history enabled, so we make + 00A7 7403 00AC jz read_ll10 ; our code match DISABLE mask + 00A9 0D0080 or ax,DISABLE_MASK ; of table entry + read_ll10: + 00AC 2E3B07 cmp ax,EDIT_CNTRL ; check for a match (Escape Flag + 00AF 7430 00E1 je read_ll_found_cmd ; and the character) + 00B1 83C304 add bx,EDIT_LEN ; Add the entry length + 00B4 E2E2 0098 loop read_ll_next_cmd ; and scan the whole table + + ; We have failed to find a command so insert char in buffer + + 00B6 F6C401 test ah,ESC_CODE ; Ignore non-matched escaped keys + 00B9 75CD 0088 jnz read_line_loop + + 00BB E82C00 00EA call save_char ; not an command so save the character + 00BE 814EF42000 or RL_FLAGS,RLF_DIRTY ; and remember we have something new + + ; Are we in search mode ? + + 00C3 F746F40100 test RL_FLAGS,RLF_ENHANCED ; Compatibilty required? + 00C8 74BE 0088 jz read_line_loop + 00CA F746F40C00 test RL_FLAGS,RLF_SEARCH+RLF_MATCH + 00CF 74B7 0088 jz read_line_loop ; is searching/matching on ? + 00D1 56 push si ; save current offset + 00D2 E80000 E call search_cmd + 00D5 58 pop ax ; this is our target offset + read_ll20: + 00D6 3BC6 cmp ax,si ; are we there yet ? + 00D8 73AE 0088 jae read_line_loop + 00DA 50 push ax ; no, keep rewinding cursor + 00DB E83B01 0219 call prev_char ; until we reach position + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 19 + + + 00DE 58 pop ax ; before we tried to match + 00DF EBF5 00D6 jmps read_ll20 + + read_ll_found_cmd: ; get the address of the corresponding + 00E1 2E8B4F02 mov cx,EDIT_FUNC ; function from the table + 00E5 FFD1 call cx ; execute the correct function + 00E7 EB9F 0088 jmps read_line_loop ; and go back for next character + + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 20 + + + eject + ; + ; the SAVE_CHAR routine will write the character in AL into + ; the buffer in memory and then update the screen image. The + ; RLF_INS flag is used to determine if INSERT is active. + ; + save_c10: + 00E9 C3 ret + + save_char: + 00EA 80FCFF cmp ah,TRUE ; Ignore any un-matched escape + 00ED 74FA 00E9 jz save_c10 ; sequences + 00EF E8BB00 01AD call save_kanji ; Test if AL is a Kanji Character + ; and setup up the parameter blocks + ; for the INTSAVE_CHAR routine + ; + ; INTSAVE_CHAR is the internal entry point to the Character Save + ; routine. It assumes the following:- + ; + ; On Entry:- AX(AL) Contains the character + ; CX the new character length in bytes + ; RLF_KANJI Flag is set for a Kanji Character + ; RL_KANJI Contains the kanji charater + ; + intsave_char: + 00F2 8BD9 mov bx,cx + 00F4 F746F40200 test RL_FLAGS,RLF_INS ; Overwrite the character in the + 00F9 7561 015C jnz save_c50 ; buffer currently + 00FB 03DE add bx,si ; Add the current index to the character + 00FD 3B5EF2 cmp bx,RL_MAXLEN ; size and compare against the buffer len + 0100 7355 0157 jae bell_char ; Full ? Yes Ring dat Bell ! + + 0102 3BD6 cmp dx,si ; Are we at the end of the line + 0104 7509 010F jnz intsave_c10 ; No so check character types + 0106 5051 push ax ! push cx + 0108 E8CD01 02D8 call skip_one_char ; Skip the coresponding character in + 010B 5958 pop cx ! pop ax ; the save buffer + 010D EB19 0128 jmps simple_save + + intsave_c10: + 010F 50 push ax ; Save the Input Character + 0110 E8FC02 040F call char_type ; Get the character type + 0113 8BD8 mov bx,ax ; and save in BX + 0115 268A05 mov al,es:[di] ; get the byte to be replaced + 0118 E8F402 040F call char_type ; and get its type + 011B 80E48E and ah,CHAR_SIZE ; Mask the Character SIZE attributes + 011E 80E78E and bh,CHAR_SIZE ; and check both storage and display + ; sizes are the same for old and new + 0121 3AE7 cmp ah,bh ; and do simple save if the character + 0123 58 pop ax ; Restore the input character to AX(AL) + 0124 7518 013E jnz save_c30 ; type match + 0126 2BD1 sub dx,cx ; Character overwritten so prevent + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 21 + + + ; Max Index being incremented + + simple_save: + 0128 03F1 add si,cx ; Assume at the EOL + 012A 03D1 add dx,cx + 012C AA stosb ; Save the character typed + 012D F746F44000 test RL_FLAGS,RLF_KANJI ; is this a Kanji character + 0132 7407 013B jz simple_s10 ; No so just output 1 character + 0134 E88C03 04C3 call put_char ; and echo it to the user + 0137 8A46F1 mov al,byte ptr RL_KANJI+1 ; Get the high byte of the Kanji + 013A AA stosb ; character save and then display it. + simple_s10: + 013B E98503 04C3 jmp put_char + ; ret + + ; + ; The SAVE_C30 function supports the Complex overwrite conditions + ; where the size of the character in memory or on the display do not + ; match with those of the present incumbent. eg a SPACE character + ; overwriting a TAB or a KANJI character overwriting a SPACE. + ; + ; To minimize the complexity of the code the character to be + ; overwritten is deleted and the new character then inserted. + ; This is not an optimal solution but drastically reduces the + ; amount of code required. + ; + save_c30: + 013E 5051 push ax ! push cx + 0140 E82201 0265 call deln_char + 0143 5958 pop cx ! pop ax + 0145 3BD6 cmp dx,si + 0147 74DF 0128 jz simple_save + 0149 814EF40200 or RL_FLAGS,RLF_INS + 014E E80B00 015C call save_c50 + 0151 8166F4FDFF and RL_FLAGS,not RLF_INS + 0156 C3 ret + + bell_char: + 0157 B007 mov al,BELL + 0159 E98003 04DC jmp write_char + ; + ; This code is called when INSERT mode is active and a + ; character (possibly Kanji) is to be inserted in the buffer + ; + ; On Entry:- CX the new character length in bytes + ; + save_c50: + 015C 8BD9 mov bx,cx ; Save new character length + 015E 03CA add cx,dx ; Add the current max to the character + 0160 3B4EF2 cmp cx,RL_MAXLEN ; size and compare against the buffer len + 0163 73F2 0157 jae bell_char ; Full ? Yes Ring dat Bell ! + 0165 8BCB mov cx,bx ; Restore Character Length + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 22 + + + 0167 3BD6 cmp dx,si ; If we are at the end of the line + 0169 74BD 0128 je simple_save ; Use the simple save code + ; + ; Create space in the current buffer for the new character + ; + 016B 1E push ds + 016C 5657 push si ! push di + 016E 8BCA2BCE mov cx,dx ! sub cx,si ; CX -> Number of bytes to move + 0172 8BFA037EF8 mov di,dx ! add di,RL_BUFOFF ; DI -> End of Destination Offset + 0177 03FB4F add di,bx ! dec di ; -> + Insert Char len - 1 + 017A 8BF72BF3 mov si,di ! sub si,bx ; SI -> DI - Insert Char Len + 017E 061F push es ! pop ds ; DS == ES + 0180 FD std ; Make the right amount of space in + 0181 F3A4 rep movsb ; the buffer + 0183 FC cld + 0184 5F5E pop di ! pop si + 0186 1F pop ds + + 0187 03D3 add dx,bx ; Update the Buffer Length + 0189 AA stosb ; Save the New character + 018A F746F44000 test RL_FLAGS,RLF_KANJI ; Check if this was a Kanji Character + 018F 7403 0194 jz save_c60 ; No + 0191 86C4AA xchg al,ah ! stosb ; Yes Save high byte + + save_c60: + 0194 8BCA2BCE mov cx,dx ! sub cx,si ; Display the updated string + 0198 03F356 add si,bx ! push si ; Save the Updated Index + 019B 8BF72BF3 mov si,di ! sub si,bx ; Get the offset of the new char + 019F E81103 04B3 call put_string ; in the buffer and display all + 01A2 5E pop si ; Restore the new index + 01A3 87FA xchg di,dx ; and calculate the number of BS + 01A5 E8D602 047E call calc_chars ; characters required to get back + 01A8 87FA xchg di,dx + 01AA E9FA02 04A7 jmp bs_out + ; + ; On Entry: AL First byte of Character + ; + ; On Exit: AX Complete Character Code + ; CX Character Size Bytes + ; RL_KANJI and RLF_KANJI set correctly + ; + save_kanji: + 01AD 8166F4BFFF and RL_FLAGS,not RLF_KANJI + 01B2 8946F0 mov RL_KANJI,ax ; Save the Character + 01B5 E85702 040F call char_type ; Is this the first byte of a + 01B8 F6C408 test ah,CHAR_KANJI ; two byte Kanji character + 01BB B90100 mov cx,1 ; Character size in bytes + 01BE 7411 01D1 jz save_k10 ; No + 01C0 814EF44000 or RL_FLAGS,RLF_KANJI ; Set internal Flag + 01C5 E82E03 04F6 call get_char ; Get the high byte and save + 01C8 8846F1 mov byte ptr RL_KANJI+1,al ; in the local variable + 01CB 8B46F0 mov ax,RL_KANJI ; Get the complete character + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 23 + + + 01CE B90200 mov cx,2 ; Character size in bytes + save_k10: + 01D1 C3 ret + + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 24 + + + eject + ; + ; The following group of functions modify the flags which control + ; the command line editor. + ; + toggle_ins: + 01D2 8176F40200 xor RL_FLAGS,RLF_INS ; Toggle the OverWrite/Insert + 01D7 C3 ret ; Flag + + toggle_search: + 01D8 8166F4F7FF and RL_FLAGS,not RLF_MATCH ; clear match bit + 01DD 8176F40400 xor RL_FLAGS,RLF_SEARCH ; Toggle the Search on/off flag + 01E2 C3 ret + + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 25 + + + eject + ; + ; This group of functions moves the cursor along the display + ; as well as updating the local variables. + ; + goto_bol: + 01E3 85F6 test si,si ; Move the cursor to the begining of + 01E5 740F 01F6 jz goto_b10 ; the displayed line + 01E7 8BFE mov di,si ; Set the buffer index to the + 01E9 33F6 xor si,si ; start of the line and the current + 01EB E89002 047E call calc_chars ; location + 01EE E8B602 04A7 call bs_out + 01F1 33F6 xor si,si + 01F3 8B7EF8 mov di,RL_BUFOFF + goto_b10: + 01F6 C3 ret + + next_char: + 01F7 3BF2 cmp si,dx + 01F9 7503 01FE jnz next_c05 ; Treat this as "F1" when we at the + 01FB E92501 0323 jmp copy_char ; end of the line + + next_c05: + 01FE 268A05 mov al,es:[di] ; Get the Offset of the next character + 0201 B90100 mov cx,1 ; the character itself and assume + 0204 E80802 040F call char_type ; it is 1 byte long + 0207 F6C4087401 020D test ah,CHAR_KANJI ! jz next_c10 + 020C 41 inc cx + next_c10: + 020D 87F7 xchg si,di ; Get the string offset in SI + 020F E8A102 04B3 call put_string ; display the character and + 0212 87F7 xchg si,di ; restore the register contents + 0214 03F1 add si,cx + 0216 03F9 add di,cx + 0218 C3 ret + + prev_char: + 0219 85F6 test si,si ; begining of line ? + 021B 742B 0248 jz prev_w30 + 021D 525657 push dx ! push si ! push di + 0220 8B76F8 mov si,RL_BUFOFF ; Scan from the begining of the buffer + 0223 8BD6 mov dx,si ; keeping the last match in DX + prev_c10: + 0225 E82B02 0453 call char_info ; Get the character information + 0228 3BF7 cmp si,di ; Stop when we get to the current + 022A 7404 0230 je prev_w20 ; character location + 022C 8BD6 mov dx,si ; Save current location + 022E EBF5 0225 jmps prev_c10 ; and repeat + + prev_w20: + 0230 2BF2 sub si,dx ; Calculate character length + 0232 56 push si ; save for update + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 26 + + + + 0233 2B7EF8 sub di,RL_BUFOFF ; Convert Offset to Index + 0236 F7DE03F7 neg si ! add si,di ; Set the buffer index to the current + 023A E84102 047E call calc_chars ; location and the previous character + 023D E86702 04A7 call bs_out ; BackSpace over character + 0240 59 pop cx ; Restore the character size + 0241 5F5E5A pop di ! pop si ! pop dx + 0244 2BF1 sub si,cx ; Update the Index and Pointer + 0246 2BF9 sub di,cx ; variables. + prev_w30: + 0248 C3 ret + + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 27 + + + eject + ; + ; This group of functions deletes characters or groups of characters + ; from the buffer. + ; + + delf_char: + 0249 3BF2 cmp si,dx ; any chars to our right ? + 024B 7218 0265 jb deln_char ; yes, delete them first + 024D E98800 02D8 jmp skip_one_char + ; ret ; discard next saved char + + del_eol: + 0250 8BCA2BCE mov cx,dx ! sub cx,si ; Calculate the number of bytes to + 0254 E304 025A jcxz del_eol10 ; delete and jump to DELN_WORD if + 0256 03CF add cx,di ; non zero. Convert to an offset + 0258 EB1E 0278 jmps deln_w10 ; and jmp to common code. + del_eol10: + 025A C3 ret + + delp_char: + 025B 0BF674FB 025A or si,si ! jz del_eol10 ; Ignore if the user is at the start + 025F E89900 02FB call back_one_char ; of the line otherwise move back one + 0262 E8B4FF 0219 call prev_char ; character in the line buffer + + + deln_char: + 0265 3BD674F1 025A cmp dx,si ! jz del_eol10 + 0269 268A05 mov al,es:[di] ; Get the Offset of the next character + 026C 8D4D01 lea cx,1[di] ; the character itself and assume + 026F E89D01 040F call char_type ; it is 1 byte long + 0272 F6C4087401 0278 test ah,CHAR_KANJI ! jz deln_w10 + 0277 41 inc cx + ; jmps deln_w10 + + ; + ; The 3 delete functions come together at this point with the standard + ; register format Plus CX is the offset of the first character not to + ; be deleted. + ; + deln_w10: + 0278 51 push cx ; Save Delete Offset + 0279 87FA xchg di,dx ; Determine the no of characters + 027B E80002 047E call calc_chars ; displayed to the end of the line + 027E 87FA xchg di,dx + 0280 8BD9 mov bx,cx ; Save the Column count + 0282 58 pop ax ; restore the delete offset + + 0283 5353 push bx ! push bx ; Save the count twice + + 0285 5657 push si ! push di + 0287 8BCA2BCE mov cx,dx ! sub cx,si ; No of chars from old EOL + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 28 + + + 028B 8BF0 mov si,ax ; Get the Source Offset + 028D 2BC7 sub ax,di ; calculate its length. + 028F 2BD0 sub dx,ax ; Update the string length + + 0291 2BC8 sub cx,ax ; Number of chars to copy + 0293 1E push ds ; Move the contents of the + 0294 061F push es ! pop ds ; string down in memory and + 0296 F3A4 rep movsb ; then update the screen image + 0298 1F pop ds + 0299 5E5F pop si ! pop di ; Get the current buffer offset + ; Restore SWAPPED SI <-> DI + + 029B 8BCA mov cx,dx ; Calculate the length of the + 029D 2BCF sub cx,di ; string and print it alll + 029F E81102 04B3 call put_string + 02A2 87F7 xchg si,di ; Restore SI and DI + + 02A4 E307 02AD jcxz deln_w20 + 02A6 87FA xchg di,dx ; Calculate the number of columns + 02A8 E8D301 047E call calc_chars ; displayed + 02AB 87FA xchg di,dx + + deln_w20: + 02AD 5B pop bx ; Restore the original line length + 02AE 2BD9 sub bx,cx ; and calculate the number of spaces + 02B0 8BCB mov cx,bx ; required to overwrite the data + 02B2 E8EE01 04A3 call space_out + + 02B5 59 pop cx ; Finally move the cursor back to + 02B6 E9EE01 04A7 jmp bs_out ; its correct place + + + + + ; + ; Delete the contents of the complete line + ; + del_line: + 02B9 C746EC0000 mov RL_SAVPOS,0 ; Reset the buffer index + 02BE 85D2 test dx,dx + 02C0 7415 02D7 jz del_l10 + 02C2 E81EFF 01E3 call goto_bol ; Jump to the begining of the line + 02C5 8BFA mov di,dx ; calculate the number of display + 02C7 E8B401 047E call calc_chars ; columns it currently takes up + 02CA E8D601 04A3 call space_out ; Overwrite with spaces + 02CD E8D701 04A7 call bs_out ; Move back to the start of the line + 02D0 33F6 xor si,si ; and update all the initial variables + 02D2 8BD6 mov dx,si + 02D4 8B7EF8 mov di,RL_BUFOFF + del_l10: + 02D7 C3 ret + + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 29 + + + eject + ; + ; The following routines manipulate the SAVE Buffer data. Which + ; is initialised on entry to this function. + ; + ; SKIP_ONE_CHAR increments the Save Buffer control variables and + ; returns the number of bytes skipped in CX. + ; + ; On Entry: Standard Registers + ; + ; On Exit: AX Next Character in Buffer + ; CX Character Size (Bytes) + ; + skip_one_char: + 02D8 33C9 xor cx,cx + 02DA 8B5EEC mov bx,RL_SAVPOS ; Update the Save Buffer variables + 02DD 3B5EEE cmp bx,RL_SAVMAX ; Check the current save buffer is + 02E0 7315 02F7 jae soc_20 ; valid and has not been exhausted. + ; Otherwise increment the RL_SAVPOS + 02E2 BB0000 E mov bx,offset savbuf ; pointer by one character. This + 02E5 035EEC add bx,RL_SAVPOS ; means that the RL_SAVPOS can be + 02E8 8A07 mov al,ds:[bx] ; incremented by 1 or 2 depending on + 02EA E82201 040F call char_type ; the contents of the buffer + 02ED F6C408 test ah,CHAR_KANJI + 02F0 7404 02F6 jz soc_10 + 02F2 8A6701 mov ah,ds:1[bx] + 02F5 41 inc cx + soc_10: + 02F6 41 inc cx + soc_20: + 02F7 014EEC add RL_SAVPOS,cx + 02FA C3 ret + ; + ; + ; BACK_ONE_CHAR decrements the Save Buffer control variables and + ; returns the number of bytes skipped in CX. + ; + ; On Entry: Standard Registers + ; + ; On Exit: RL_SAVPOS points to previous buffer char + ; AX,BX,CX,DX Unknown + ; + back_one_char: + 02FB 52 push dx + 02FC BB0000 E mov bx,offset savbuf ; Get the Buffer address + 02FF 8BCB034EEC mov cx,bx ! add cx,RL_SAVPOS ; CX is the Current location + 0304 8BD3 mov dx,bx ; DX is last matching character + boc_10: + 0306 3BD9 cmp bx,cx ; Have we reached the current Char + 0308 7410 031A jz boc_20 ; Yes exit and update buffer + 030A 8BD3 mov dx,bx ; Update last character location + 030C 8A07 mov al,ds:[bx] ; incremented by 1 or 2 depending on + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 30 + + + 030E E8FE00 040F call char_type ; the contents of the buffer + 0311 43 inc bx + 0312 F6C408 test ah,CHAR_KANJI ; Increment pointer by 2 for a Kanji + 0315 74EF 0306 jz boc_10 ; character + 0317 43 inc bx + 0318 EBEC 0306 jmps boc_10 + + boc_20: + 031A 81EA0000 E sub dx,offset savbuf ; Calculate the character Index + 031E 8956EC mov RL_SAVPOS,dx ; and save in RL_SAVPOS + 0321 5A pop dx + 0322 C3 ret + + copy_char: + 0323 3BD6 cmp dx,si ; If at end of line copy characters + 0325 7406 032D jz copy_c5 + 0327 E8CDFE 01F7 call next_char ; Otherwise just move by 1 + 032A E90A00 0337 jmp copy_c10 + copy_c5: + 032D E8A8FF 02D8 call skip_one_char ; Calculate Bytes to copy + 0330 E305 0337 jcxz copy_c10 ; Skip Update in no characters skipped + 0332 294EEC sub RL_SAVPOS,cx ; Restore the Buffer Position + 0335 EB23 035A jmps copy_a10 ; and copy the data + copy_c10: + 0337 C3 ret + + copy_till_char: + 0338 3BD6 cmp dx,si ; Copy out if at end of line + 033A 7508 0344 jnz move_till_char + 033C E84B00 038A call skip_till_char ; Returns index to the next char + 033F 294EEC sub RL_SAVPOS,cx + 0342 EB16 035A jmps copy_a10 + move_till_char: + 0344 8976EC mov RL_SAVPOS,si ; Start search from the current + 0347 E84000 038A call skip_till_char ; position + 034A E307 0353 jcxz no_move ; CX=0 - dont move + move_along: + 034C 51 push cx + 034D E8A7FE 01F7 call next_char ; Shuttle along the line until + 0350 59 pop cx ; we reach the character + 0351 E2F9 034C loop move_along + no_move: + 0353 C3 ret + + copy_all: + 0354 8B4EEE mov cx,RL_SAVMAX ; Calculate the number of bytes to + 0357 2B4EEC sub cx,RL_SAVPOS ; copy from the buffer. + copy_a10: + 035A 83F900 cmp cx,0 ; do we have nothing to copy + 035D 7E2A 0389 jle copy_a30 ; (or less than nothing..) + + 035F FF76F4 push RL_FLAGS ; Save State flags and prevent + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 31 + + + 0362 814EF40200 or RL_FLAGS,RLF_INS ; SAVPOS being modified + copy_a20: + 0367 51 push cx + 0368 8166F4BFFF and RL_FLAGS,not RLF_KANJI + 036D E868FF 02D8 call skip_one_char ; Return the next character and its + 0370 83F901 cmp cx,1 + 0373 740B 0380 jz copy_a25 ; size in bytes + 0375 8946F0 mov RL_KANJI,ax ; Save the Kanji Character and + 0378 814EF44000 or RL_FLAGS,RLF_KANJI ; set the control flag + 037D 5B pop bx + 037E 4B dec bx + 037F 53 push bx ; Decrement the Loop Count + + copy_a25: + 0380 E86FFD 00F2 call intsave_char ; Save the character + 0383 59 pop cx ; and repeat till all bytes have + 0384 E2E1 0367 loop copy_a20 ; been copied + 0386 8F46F4 pop RL_FLAGS ; Restore State Flags + copy_a30: + 0389 C3 ret + + skip_till_char: + 038A E86901 04F6 call get_char ; Get the first character + 038D E81DFE 01AD call save_kanji ; Setup RL_KANJI etc. + 0390 52 push dx + 0391 E844FF 02D8 call skip_one_char ; don't match on 1st char + 0394 8BD1 mov dx,cx ; remember we've skipped 1st char + 0396 E32F 03C7 jcxz stc_40 ; buffer exhausted + stc_10: + 0398 E83DFF 02D8 call skip_one_char ; Get the Next Character + 039B E32A 03C7 jcxz stc_40 ; Buffer exhausted + 039D 03D1 add dx,cx ; Update the Total Byte Count + 039F 83F902740E 03B2 cmp cx,2 ! jz stc_20 ; Was this a Kanji Character + 03A4 F746F44000 test RL_FLAGS,RLF_KANJI ; No but are we looking for one ? + 03A9 75ED 0398 jnz stc_10 ; Yes so get the next character + 03AB 3A46F0 cmp al,byte ptr RL_KANJI ; Have we got a matching character ? + 03AE 75E8 0398 jnz stc_10 ; No so look again + 03B0 EB0C 03BE jmps stc_30 ; Return Sucess + + stc_20: ; Kanji Character in Buffer + 03B2 F746F44000 test RL_FLAGS,RLF_KANJI ; Are we looking for a Kanji Char + 03B7 74DF 0398 jz stc_10 ; No so try again + 03B9 3B46F0 cmp ax,RL_KANJI ; Check the character and repeat + 03BC 75DA 0398 jnz stc_10 ; if they donot match + + stc_30: ; Character Match + 03BE 2BD1 sub dx,cx ; Correct the Total Byte Count + 03C0 294EEC sub RL_SAVPOS,cx ; point to the matching char + 03C3 87CA xchg cx,dx ; and return the Match Count + 03C5 5A pop dx + 03C6 C3 ret + + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 32 + + + stc_40: ; No Match + 03C7 2956EC sub RL_SAVPOS,dx ; Restore RL_SAVPOS to orginal value + 03CA 33C9 xor cx,cx ; and return 0000 characters skipped + 03CC 5A pop dx + 03CD C3 ret + + ; + ; Update the Save buffer with the contents of the users + ; line buffer. + ; + ; On Entry: ES:DI -> Current location in Buffer + ; DX No. of bytes in buffer + ; + ; On Exit: Update RL_SAVMAX, RL_SAVPOS, RL_SAVBUF + ; + save_line: + 03CE 33C0 xor ax,ax + 03D0 8946EC mov RL_SAVPOS,ax + 03D3 8946EE mov RL_SAVMAX,ax + 03D6 8BCA mov cx,dx ; Current Line Length + 03D8 E31E 03F8 jcxz save_l10 + 03DA 81F98000 cmp cx,savbuf_size ; clip the amount saved + 03DE 7203 03E3 jb save_l5 ; to be a maximum of + 03E0 B98000 mov cx,savbuf_size ; the save buffer size + save_l5: + 03E3 894EEE mov RL_SAVMAX,cx ; Set the Save Data Length + 03E6 1E06 push ds ! push es + 03E8 5657 push si ! push di + + 03EA 1E07 push ds ! pop es + 03EC C576F8 lds si,RL_BUFPTR + 03EF BF0000 E mov di,offset savbuf + 03F2 F3A4 rep movsb ; save the data + 03F4 5F5E pop di ! pop si + 03F6 071F pop es ! pop ds + save_l10: + ; ret + + ignore_char: + 03F8 C3 ret + + mem_line: ;; JFL save from beginning of line + 03F9 E8D2FF 03CE call save_line + 03FC E9E4FD 01E3 jmp goto_bol + ; ret + + + eof_char: ;; JFL make F6 return a CTL Z + 03FF B01A mov al,01Ah + 0401 B90100 mov cx,1 + 0404 E9EBFC 00F2 jmp intsave_char + ; ret + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 33 + + + + ctlat_char: ;; JFL make F7 return a CTL @ + 0407 B000 mov al,0h + 0409 B90100 mov cx,1 + 040C E9E3FC 00F2 jmp intsave_char + ; ret + + + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 34 + + + eject + ; + ; CHAR_TYPE get the next character from the buffer ES:SI and returns + ; its type in AH using the equates CHAR_????. The character is returned + ; in AL. + ; + ; + ; + char_type: + 040F B481 mov ah,CHAR_SPACE or CHAR_STD ; WhiteSpace + 0411 3C20743D 0452 cmp al,' ' ! jz char_t100 + 0415 B402 mov ah,CHAR_TAB ; Tab Character + 0417 3C097437 0452 cmp al,TAB ! jz char_t100 + 041B B490 mov ah,CHAR_ALPHAN or CHAR_STD + 041D 3C157431 0452 cmp al,CTLU ! jz char_t100 ; Control-U and Control-T are treated + 0421 3C14742D 0452 cmp al,CTLT ! jz char_t100 ; as normal characters + 0425 B404 mov ah,CHAR_CTL ; Control Character + 0427 3C207227 0452 cmp al,' ' ! jb char_t100 + + 042B B490 mov ah,CHAR_ALPHAN or CHAR_STD + 042D 3C30721F 0450 cmp al,'0' ! jb char_t90 ; Return SYMBOL + 0431 3C39761D 0452 cmp al,'9' ! jbe char_t100 ; Return AlphaNumeric + 0435 3C417217 0450 cmp al,'A' ! jb char_t90 ; Return Symbol + 0439 3C5A7615 0452 cmp al,'Z' ! jbe char_t100 ; Return AlphaNumeric + 043D 3C61720F 0450 cmp al,'a' ! jb char_t90 ; Return Symbol + 0441 3C7A760D 0452 cmp al,'z' ! jbe char_t100 ; Return AlphaNumeric + 0445 3C807207 0450 cmp al,80h ! jb char_t90 ; Return Symbol + + 0449 B408 mov ah, CHAR_KANJI ; assume character is 16 bits + 044B E80000 E call dbcs_lead ; is byte a DBCS lead? + 044E 7402 0452 je char_t100 ; yes - done + char_t90: + 0450 B4A0 mov ah,CHAR_OTHER or CHAR_STD ; no - Normal Character Symbol + + char_t100: + 0452 C3 ret + + + + + + ; + ; CHAR_INFO will return various information about the character + ; at ES:SI + ; + ; On Entry: ES:SI Character Pointer + ; BX Current Column No. + ; CX Byte Scan Count + ; + ; On Exit: ES:SI Points to the next Character + ; BX Updates Column No. + ; CX Updates Byte Scan Count + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 35 + + + ; AH Character type Flags + ; AL First byte of Character + char_info: + 0453 26AC lods es:al + 0455 E8B7FF 040F call char_type ; Test the character type and assume + 0458 43 inc bx ; it will take 1 Screen location + 0459 F6C431 test ah,CHAR_ONECOL + 045C 751F 047D jnz char_i20 + + 045E 43 inc bx ; Now check for the Control Characters + 045F F6C404 test ah,CHAR_CTL ; which take up 2 cols + 0462 7519 047D jnz char_i20 + + 0464 F6C408 test ah,CHAR_KANJI ; If this was the first byte of a + 0467 7404 046D jz char_i10 ; KANJI character then skip the + 0469 4649 inc si ! dec cx ; next byte + 046B EB10 047D jmps char_i20 + + char_i10: + 046D 50 push ax ; Save AX and calculate the number + 046E 4B4B dec bx ! dec bx ; of screen locations that this TAB + 0470 8BC3 mov ax,bx ; character will use based on the fact + 0472 250700 and ax,7 ; BX contains the current column + 0475 F7D8050800 neg ax ! add ax,8 + 047A 03D8 add bx,ax + 047C 58 pop ax + + char_i20: + 047D C3 ret + + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 36 + + + eject + ; + ; CALC_CHARS calculates the number of character locations used + ; on the screen to display a particular sub-string of the current + ; buffer. This routine takes account of the Kanji, Control and TAB + ; characters. + ; + ; On Entry: SI Start Buffer Index + ; DI End Buffer Index + ; + ; On Exit: CX Count + ; + calc_chars: + 047E 53 push bx + 047F 5657 push si ! push di + 0481 8B5EF6 mov bx,RL_INICOL ; Get the initial Column + 0484 2BFE sub di,si ; DI = Sub-string length bytes + 0486 8BCE mov cx,si ; Use the Start Index for the + 0488 8B76F8 mov si,RL_BUFOFF ; initial count and scan from the + 048B E305 0492 jcxz calc_c20 ; start of the buffer + + calc_c10: + 048D E8C3FF 0453 call char_info + 0490 E2FB 048D loop calc_c10 + + calc_c20: + 0492 8BCF mov cx,di ; Sub-String Length + 0494 8BFB mov di,bx ; Current Column position + + calc_c30: + 0496 E8BAFF 0453 call char_info + 0499 E2FB 0496 loop calc_c30 + + 049B 2BDF sub bx,di + 049D 8BCB mov cx,bx + 049F 5F5E pop di ! pop si + 04A1 5B pop bx + 04A2 C3 ret + + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 37 + + + eject + ; + ; The following functions are purely Low level character output + ; functions. + ; + space_out: ; Write CX Space characters to the + 04A3 B020 mov al,' ' ; Output handle + 04A5 EB02 04A9 jmps block_out + + bs_out: + 04A7 B008 mov al,CTLH ; Write CX BackSpace characters to + ;; jmps block_out ; Output Handle + + block_out: + 04A9 E307 04B2 jcxz block_o20 + 04AB 51 push cx + block_o10: + 04AC E82D00 04DC call write_char ; output this character + 04AF E2FB 04AC loop block_o10 + 04B1 59 pop cx + block_o20: + 04B2 C3 ret + + ; + ; Display CX characters from the string at ES:SI + ; + put_string: + 04B3 E30D 04C2 jcxz puts_s20 + 04B5 5156 push cx ! push si + put_s10: + 04B7 51 push cx + 04B8 26AC lods es:al + 04BA E80600 04C3 call put_char + 04BD 59 pop cx + 04BE E2F7 04B7 loop put_s10 + 04C0 5E59 pop si ! pop cx + puts_s20: + 04C2 C3 ret + + ; + ; Display the character in AL + ; + put_char: + 04C3 3C207315 04DC cmp al,' ' ! jae write_char ; skip if it's printable + 04C7 3C147411 04DC cmp al,CTLT! je write_char ; Control-T and Control-U are treated + 04CB 3C15740D 04DC cmp al,CTLU! je write_char ; like normal Characters. + 04CF 3C097409 04DC cmp al,TAB ! je write_char ; skip if it's TAB + 04D3 0C40 or al,040h ; Convert Character to Uppercase + 04D5 50 push ax ; save it + 04D6 B05E mov al,'^' ; display the character + 04D8 E80100 04DC call write_char ; in ^X format + 04DB 58 pop ax + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 38 + + + write_char: + 04DC 06 push es + 04DD 52 push dx + 04DE 51 push cx + 04DF 56 push si + 04E0 57 push di + 04E1 50 push ax ; char on stack + 04E2 8B5EFC mov bx,RL_OUTPUT ; Output AL to the OUTPUT Handle + 04E5 1607 push ss ! pop es ; ES:DX -> Character Buffer + 04E7 8BF4 mov si,sp ; buffer offset + 04E9 B90100 mov cx,1 ; character count + 04EC E80000 E call cooked_write ; Write Character + 04EF 58 pop ax + 04F0 5F pop di + 04F1 5E pop si + 04F2 59 pop cx + 04F3 5A pop dx + 04F4 07 pop es + 04F5 C3 ret + ; + ; Read 1 a character from RL_INPUT saving all the vital registers + ; from corruption. If the first character is the ESCAPE character + ; set AH to TRUE and read the next byte. Otherwise AH is FALSE + ; + get_char: + 04F6 1E push ds + 04F7 06 push es + 04F8 52 push dx + 04F9 56 push si + 04FA 57 push di + + 04FB E80000 E call get_dseg ; point at pcmode data + 04FE C5360000 E lds si,con_device ; DS:SI -> current console device + 0502 F744040040 test ds:DH_ATTRIB[si],DA_IOCTL ; test bit 14: IOCTL bit + 0507 7427 0530 jz get_c05 ; error if IOCTL not supported + 0509 83EC1E sub sp,RH_SIZE ; reserve this many words on the stack + 050C 8BDC mov bx,sp ; SS:BX -> request packet + 050E 1607 push ss ! pop es ; ES:BX -> request packet + 0510 8D56F4 lea dx,RL_FLAGS ; point at flags + 0513 26C647020C mov es:RH_CMD[bx],CMD_OUTPUT_IOCTL + 0518 26C6071E mov es:RH_LEN[bx],RH4_LEN + 051C 2689570E mov es:RH4_BUFOFF[bx],dx ; set up for a normal + 0520 268C5710 mov es:RH4_BUFSEG[bx],ss ; IOCTL read/write + 0524 26C747120200 mov es:RH4_COUNT[bx],WORD + 052A E80000 E call device_driver ; execute the command + 052D 83C41E add sp,RH_SIZE ; reclaim the stack + get_c05: + + 0530 E80000 E call get_dseg ; point at pcmode data + 0533 8B5EFE mov bx,RL_INPUT ; BX = input stream + 0536 E80000 E call cmdline_read ; get a character + + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 39 + + + 0539 B400 mov ah,FALSE ; Assume this is NOT the Escape + 053B 2E3A060000 R cmp al,esc_char ; character and set high byte of the + 0540 7505 0547 jnz get_c10 ; match word to FALSE + + 0542 E80000 E call raw_read ; read the second byte of the escape + 0545 B401 mov ah,ESC_CODE ; sequence, setting high byte to ESC + get_c10: + 0547 5F pop di + 0548 5E pop si + 0549 5A pop dx + 054A 07 pop es + 054B 1F pop ds + 054C C3 ret + + PCM_RODATA CSEG WORD + + 0000 EDIT_CNTRL equ cs:word ptr 0[bx] ; Character and Esc Flag + 0002 EDIT_FUNC equ cs:word ptr 2[bx] ; Edit Function Address + 0004 EDIT_LEN equ 4 ; Edit Table Entry Size + + 0000 00 esc_char db 0 ; Command Line Editor Escape Character + 0001 2D00 edit_size dw (offset edit_end - edit_table)/EDIT_LEN + + 0003 0D004900 R edit_table db CR ! db NESC_CODE ! dw ret_string + 0007 0A00F803 R db LF ! db NESC_CODE ! dw ignore_char + 000B 08005B02 R db CTLH ! db NESC_CODE ! dw delp_char + 000F 7F004902 R db DEL ! db NESC_CODE ! dw delf_char + + 0013 1B00B902 R db ESC ! db NESC_CODE ! dw del_line + 0017 3B012303 R db ';' ! db ESC_CODE ! dw copy_char ; Function 1 + 001B 3C013803 R db '<' ! db ESC_CODE ! dw copy_till_char ; Function 2 + 001F 3D015403 R db '=' ! db ESC_CODE ! dw copy_all ; Function 3 + 0023 3E018A03 R db '>' ! db ESC_CODE ! dw skip_till_char ; Function 4 + 0027 3F01F903 R db '?' ! db ESC_CODE ! dw mem_line ; Function 5 + + 002B 4001FF03 R db '@' ! db ESC_CODE ! dw eof_char ; Function 6 + 002F 41010704 R db 'A' ! db ESC_CODE ! dw ctlat_char ; Function 7 + 0033 42810000 E db 'B' ! db ESC_CODE or DISABLE ! dw match_cmd ; Function 8 + + 0037 5201D201 R db 'R' ! db ESC_CODE ! dw toggle_ins ; Insert + 003B 53014902 R db 'S' ! db ESC_CODE ! dw delf_char ; Delete + 003F 4B811902 R db 'K' ! db ESC_CODE or DISABLE ! dw prev_char ; Left Arrow + 0043 4D81F701 R db 'M' ! db ESC_CODE or DISABLE ! dw next_char ; Right Arrow + ; When advanced editing is disabled the match for Left/Right arrows will fall + ; through to here + 0047 4B015B02 R db 'K' ! db ESC_CODE ! dw delp_char ; Left Arrow - compat + 004B 4D012303 R db 'M' ! db ESC_CODE ! dw copy_char ; Right Arrow - compat + ; + ; Extended functions from here on + ; + 004F 43810000 E db 'C' ! db ESC_CODE or DISABLE ! dw del_cur_history_buffer ; Func 9 + 0053 44810000 E db 'D' ! db ESC_CODE or DISABLE ! dw del_history_buffers ; Func 10 + PC-DOS RASM-86 1.4a Source: CMDLINE.A86 Page 40 + + + 0057 4781E301 R db 'G' ! db ESC_CODE or DISABLE ! dw goto_bol ; Home + 005B 4F810000 E db 'O' ! db ESC_CODE or DISABLE ! dw goto_eol ; End + 005F 74810000 E db 't' ! db ESC_CODE or DISABLE ! dw next_word ; Control Right Arrow + 0063 73810000 E db 's' ! db ESC_CODE or DISABLE ! dw prev_word ; Control Left Arrow + + + 0067 1680D201 R db CTLV ! db NESC_CODE or DISABLE ! dw toggle_ins + 006B 1180E301 R db CTLQ ! db NESC_CODE or DISABLE ! dw goto_bol + 006F 17800000 E db CTLW ! db NESC_CODE or DISABLE ! dw goto_eol + 0073 12800000 E db CTLR ! db NESC_CODE or DISABLE ! dw match_cmd + 0077 0480F701 R db CTLD ! db NESC_CODE or DISABLE ! dw next_char + 007B 13801902 R db CTLS ! db NESC_CODE or DISABLE ! dw prev_char + 007F 06800000 E db CTLF ! db NESC_CODE or DISABLE ! dw next_word + 0083 01800000 E db CTLA ! db NESC_CODE or DISABLE ! dw prev_word + 0087 07806502 R db CTLG ! db NESC_CODE or DISABLE ! dw deln_char + 008B 14800000 E db CTLT ! db NESC_CODE or DISABLE ! dw deln_word + 008F 1980B902 R db CTLY ! db NESC_CODE or DISABLE ! dw del_line + 0093 02800000 E db CTLB ! db NESC_CODE or DISABLE ! dw del_bol + 0097 0B805002 R db CTLK ! db NESC_CODE or DISABLE ! dw del_eol + + 009B 4981F803 R db 'I' ! db ESC_CODE or DISABLE ! dw ignore_char ; PageUP + 009F 5181F803 R db 'Q' ! db ESC_CODE or DISABLE ! dw ignore_char ; PageDown + 00A3 48810000 E db 'H' ! db ESC_CODE or DISABLE ! dw prev_cmd ; Up Arrow + 00A7 50810000 E db 'P' ! db ESC_CODE or DISABLE ! dw next_cmd ; Down Arrow + 00AB 05800000 E db CTLE ! db NESC_CODE or DISABLE ! dw prev_cmd + 00AF 18800000 E db CTLX ! db NESC_CODE or DISABLE ! dw next_cmd + 00B3 1F80D801 R db CTLUB ! db NESC_CODE or DISABLE ! dw toggle_search ; Default search mode + 00B7 edit_end rb 0 + + + PCMODE_DATA DSEG WORD + + extrn con_device:dword ; Current Console Device + extrn column:byte ; Console Cursor Location + + 0080 savbuf_size equ 128 + + extrn savbuf:byte ; fixed location in DOS data area + + extrn cle_state:word ; command line editing state + + end + + +End of assembly. Number of errors: 0. Use factor: 23% +n_device:dword ; Current Console Device diff --git a/IBMDOS/BIN/CMDLINE.OBJ b/IBMDOS/BIN/CMDLINE.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..bab5a1be7f7d55d0befa0461a50140d3535d0a04 GIT binary patch literal 2944 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 literal 0 HcmV?d00001 diff --git a/IBMDOS/BIN/DOSMEM.LST b/IBMDOS/BIN/DOSMEM.LST new file mode 100644 index 0000000..fe275c2 --- /dev/null +++ b/IBMDOS/BIN/DOSMEM.LST @@ -0,0 +1,1024 @@ + PC-DOS RASM-86 1.4a Source: DOSMEM.A86 Page 1 + + += 0001 __RASM__ EQU 1 + + ; File : $DOSMEM.A86$ + ; + ; Description : + ; + ; Original Author : DIGITAL RESEARCH + ; + ; Last Edited By : $CALDERA$ + ; + ;-----------------------------------------------------------------------; + ; Copyright Work of Caldera, Inc. All Rights Reserved. + ; + ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, + ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. + ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES + ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF + ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO + ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE + ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE + ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, + ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, + ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, + ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF + ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT + ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND + ; CIVIL LIABILITY. + ;-----------------------------------------------------------------------; + ; + ; *** Current Edit History *** + ; *** End of Current Edit History *** + ; $Log$ + ; DOSMEM.A86 1.13 94/12/01 10:05:21 + ; now freeing UMBs also during program termination + ; DOSMEM.A86 1.12 93/07/20 22:46:25 + ; dmd_upper_root defaults to FFFF + ; DOSMEM.A86 1.10 93/06/18 21:00:11 + ; Remove historic CDOS comment + ; ENDLOG + ; += include pcmode.equ += ; File : $PCMODE.EQU$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; + PC-DOS RASM-86 1.4a Source: DOSMEM.A86 Page 2 + + += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += ; This file contains all the general purpose definitions += ; and equates used by the PCMODE Module. += ; += += FFFF TRUE equ 0FFFFh ; value of TRUE += 0000 FALSE equ 0 ; value of FALSE += += 0006 TRUE_VERSION equ 6 += += FFFF IDLE_DETECT equ TRUE ; Check for IDLE Process's += += if IDLE_DETECT += 0001 IDLE_COMMAND equ 0001h ; Command Processor Active += 0002 IDLE_DOSFUNC equ 0002h ; DOS Function Called += 0004 IDLE_INT28 equ 0004h ; INT 28 Called += += 4000 IDLE_ON equ 4000h ; ReSet when Idle Checking Enabled += 8000 IDLE_INIT equ 8000h ; ReSet when $IDLE$ Loaded and Active += C000 IDLE_DISABLE equ IDLE_INIT + IDLE_ON += += 0001 PROC_IDLE equ 0001 ; Process is IDLE += 0002 PROC_INT28 equ 0002 ; INT28 Polling Loop += 0003 PROC_KEYIN equ 0003 ; Keyboard Input += 0004 PROC_DEVIN equ 0004 ; Device Input Routine += endif += += += 00C0 STACK_SIZE equ 192 ; Local Stack Size (Levels) += 0050 MAX_PATHLEN equ 80 ; Maximum Path length += 000D MAX_FILELEN equ 13 + PC-DOS RASM-86 1.4a Source: DOSMEM.A86 Page 3 + + += += ; += ; DOS process termination Codes += ; += 0000 TERM_NORMAL equ 0 ; Normal Termination += 0001 TERM_BREAK equ 1 ; Termination by Control Break += 0002 TERM_ERROR equ 2 ; Termination by Critical Error += 0003 TERM_RESIDENT equ 3 ; Terminate and Stay Resident += += ; += ; Critical Error responses from the default INT 24 handler and += ; the DO_INT24 routine. += ; += 0000 ERR_IGNORE equ 0 ; Ignore Error += 0001 ERR_RETRY equ 1 ; Retry the Operation += 0002 ERR_ABORT equ 2 ; Terminate the Process += 0003 ERR_FAIL equ 3 ; Fail Function += ; += 0008 OK_FAIL equ 0000$1000b ; Fail is a Valid Response += 0010 OK_RETRY equ 0001$0000b ; Retry is a Valid Response += 0020 OK_IGNORE equ 0010$0000b ; Ignore is a valid Response += 0038 OK_RIF equ 0011$1000b ; All Responsese are Valid += 0030 OK_RI equ 0011$0000b ; Retry and Ignore are Valid += 0018 OK_RF equ 0001$1000b ; Retry and Fail are Valid += ; += 0040 NO_CRIT_ERRORS equ 0100$0000b ; critical error shouldn't be generated += ; warning - must match FDOS.A86 += ; + PC-DOS RASM-86 1.4a Source: DOSMEM.A86 Page 4 + + += eject += ; The following equates define the format in which the users registers += ; are saved on the stack. This format is also seen by an application += ; when a critical error occurs. += ; += CodeMacro POP$DOS ; Pop User Registers a la MS-DOS += db 058h ! db 05Bh ; pop AX ! pop BX += db 059h ! db 05Ah ; pop BX ! pop CX += db 05Eh ! db 05Fh ; pop SI ! pop DI += db 05Dh ; pop BP += db 01Fh ! db 007h ; pop DS ! pop ES += EndM += += CodeMacro PUSH$DOS ; Push User Registers += db 006h ! db 01Eh ; push ES ! push DS += db 055h ; push BP += db 057h ! db 056h ; push DI ! push SI += db 052h ! db 051h ; push DX ! push CX += db 053h ! db 050h ; push BX ! push AX += EndM += += 0000 reg_AX equ word ptr .00 += 0000 reg_AL equ byte ptr .00 += 0001 reg_AH equ byte ptr .01 += += 0002 reg_BX equ word ptr .02 += 0002 reg_BL equ byte ptr .02 += 0003 reg_BH equ byte ptr .03 += += 0004 reg_CX equ word ptr .04 += 0004 reg_CL equ byte ptr .04 += 0005 reg_CH equ byte ptr .05 += += 0006 reg_DX equ word ptr .06 += 0006 reg_DL equ byte ptr .06 += 0007 reg_DH equ byte ptr .07 += += 0008 reg_SI equ word ptr .08 += 000A reg_DI equ word ptr .10 += 000C reg_BP equ word ptr .12 += += 000E reg_DS equ word ptr .14 += 0010 reg_ES equ word ptr .16 += += 0012 reg_IP equ word ptr .18 += 0014 reg_CS equ word ptr .20 += 0016 reg_FLAGS equ word ptr .22 += += ; Processor Flags += 0001 CARRY_FLAG equ 0001h ; Carry Flag += 0040 ZERO_FLAG equ 0040h ; Zero Flag += 0080 SIGN_FLAG equ 0080h ; Sign Flag + PC-DOS RASM-86 1.4a Source: DOSMEM.A86 Page 5 + + += 0200 INT_FLAG equ 0200h ; Interrupt Flag += 0400 DIR_FLAG equ 0400h ; Direction Flag += 0800 OFLW_FLAG equ 0800h ; OverFlow Flag += += 0000 DMD_ID equ es:byte ptr .0 ; id code ('M' or 'Z') += 0001 DMD_PSP equ es:word ptr .1 ; owner of memory block += 0003 DMD_LEN equ es:word ptr .3 ; length of memory block += 0006 DMD_IDLE_FLAGS equ es:word ptr .6 ; idle flags live here += 0008 DMD_NAME equ es:byte ptr .8 ; ASCIIZ name field += 0008 DMD_NAME_LEN equ 8 ; 8 Bytes long += 004D IDM equ 'M' ; not last id code += 005A IDZ equ 'Z' ; last id code += += PCMCODE GROUP PCM_HEADER, PCM_CODE, BDOS_CODE, PCM_RODATA += PCMCODE GROUP PCM_HISTORY, PCM_ICODE, PCM_CODEND += += PCM_HEADER CSEG PARA += PCM_CODE CSEG BYTE += PCM_RODATA CSEG WORD += BDOS_CODE CSEG WORD += PCM_HISTORY CSEG BYTE += PCM_ICODE CSEG BYTE += PCM_CODEND CSEG PARA += += += PCMDATA GROUP PCMODE_DATA, FDOS_DSEG, FIXED_DOS_DATA += PCMDATA GROUP PCMODE_CODE, GLOBAL_DATA, BDOS_DATA, PCMODE_DSIZE += += PCMODE_DATA DSEG WORD ; DOS Data += FDOS_DSEG DSEG WORD COMMON ; FDOS Parameter Block +=0000 fdos_data rw 7 += FIXED_DOS_DATA CSEG WORD 'DATA' ; Fixed DOS Data Area += PCMODE_CODE CSEG WORD 'DATA' ; DATA relative CODE += GLOBAL_DATA DSEG WORD ; GLOBAL DOS DATA (Process Independant) += BDOS_DATA DSEG WORD ; BDOS Data Area += PCMODE_DSIZE DSEG PARA ; End of DOS Data Area + += include i:msdos.equ += ; File : $MSDOS.EQU$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES + PC-DOS RASM-86 1.4a Source: DOSMEM.A86 Page 6 + + += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += += += 0000 MS_P_TERMCPM equ 00H += 0001 MS_C_READ equ 01H += 0002 MS_C_WRITE equ 02H += 0003 MS_A_READ equ 03H += 0004 MS_A_WRITE equ 04H += 0005 MS_L_WRITE equ 05H += 0006 MS_C_RAWIO equ 06H += 0007 MS_C_RAWIN equ 07H += 0008 MS_C_NOECHO equ 08H += 0009 MS_C_WRITESTR equ 09H += 000A MS_C_READSTR equ 0aH += 000B MS_C_STAT equ 0bH += 000C MS_C_FLUSH equ 0cH += 000D MS_DRV_ALLRESET equ 0dH += 000E MS_DRV_SET equ 0eH += 000F MS_F_OPEN equ 0fH += 0010 MS_F_CLOSE equ 10H += 0011 MS_F_SFIRST equ 11H += 0012 MS_F_SNEXT equ 12H += 0013 MS_F_DELETE equ 13H += 0014 MS_F_READ equ 14H += 0015 MS_F_WRITE equ 15H += 0016 MS_F_MAKE equ 16H += 0017 MS_F_RENAME equ 17H += 0019 MS_DRV_GET equ 19H += 001A MS_F_DMAOFF equ 1aH += 001B MS_DRV_ALLOC equ 1bH += 001C MS_DRV_ALLOCSPEC equ 1cH += 0021 MS_F_READRAND equ 21H += 0022 MS_F_WRITERAND equ 22H += 0023 MS_F_SIZE equ 23H + PC-DOS RASM-86 1.4a Source: DOSMEM.A86 Page 7 + + += 0024 MS_F_RANDREC equ 24H += 0025 MS_S_SETINT equ 25H += 0026 MS_P_MKPSP equ 26H += 0027 MS_F_READBLK equ 27H += 0028 MS_F_WRITEBLK equ 28H += 0029 MS_F_PARSE equ 29H += 002A MS_T_GETDATE equ 2aH += 002B MS_T_SETDATE equ 2bH += 002C MS_T_GETTIME equ 2cH += 002D MS_T_SETTIME equ 2dH += 002E MS_F_VERIFY equ 2eH += 002F MS_F_DMAGET equ 2fH += 0030 MS_S_BDOSVER equ 30H += 0031 MS_P_TERMKEEP equ 31H += 0033 MS_S_BREAK equ 33H += 0035 MS_S_GETINT equ 35H += 0036 MS_DRV_SPACE equ 36H += 0038 MS_S_COUNTRY equ 38H += 0039 MS_X_MKDIR equ 39H += 003A MS_X_RMDIR equ 3aH += 003B MS_X_CHDIR equ 3bH += 003C MS_X_CREAT equ 3cH += 003D MS_X_OPEN equ 3dH += 003E MS_X_CLOSE equ 3eH += 003F MS_X_READ equ 3fH += 0040 MS_X_WRITE equ 40H += 0041 MS_X_UNLINK equ 41H += 0042 MS_X_LSEEK equ 42H += 0043 MS_X_CHMOD equ 43H += 0044 MS_X_IOCTL equ 44H += 0045 MS_X_DUP equ 45H += 0046 MS_X_DUP2 equ 46H += 0047 MS_X_CURDIR equ 47H += 0048 MS_M_ALLOC equ 48H += 0049 MS_M_FREE equ 49H += 004A MS_M_SETBLOCK equ 4aH += 004B MS_X_EXEC equ 4bH += 004C MS_X_EXIT equ 4cH += 004D MS_X_WAIT equ 4dH += 004E MS_X_FIRST equ 4eH += 004F MS_X_NEXT equ 4fH += 0050 MS_P_SETPSP equ 50H += 0054 MS_F_GETVERIFY equ 54H += 0056 MS_X_RENAME equ 56H += 0057 MS_X_DATETIME equ 57H += 0058 MS_M_STRATEGY equ 58h += 0059 MS_F_ERROR equ 59H += 005A MS_X_MKTEMP equ 5aH += 005B MS_X_MKNEW equ 5bH += 005C MS_F_LOCK equ 5cH += 0060 MS_X_EXPAND equ 60H += 0062 MS_P_GETPSP equ 62H + PC-DOS RASM-86 1.4a Source: DOSMEM.A86 Page 8 + + += 6601 MS_X_GETCP equ 6601h += 6602 MS_X_SETCP equ 6602h += 0067 MS_X_SETHC equ 67h += 0068 MS_X_COMMIT equ 68h += += 0021 DOS_INT equ 21h ; DOS Entry Point += ; += 0000 STDIN equ 0 ; Standard Console Input Handle += 0001 STDOUT equ 1 ; Standard Console Output Handle += 0002 STDERR equ 2 ; Standard Error Output += 0003 STDAUX equ 3 ; Auxilary Device Handle += 0004 STDPRN equ 4 ; Printer Device Handle + += include i:mserror.equ += ; File : $MSERROR.EQU$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += += FFFF ED_FUNCTION equ -01 ; invalid function number += FFFE ED_FILE equ -02 ; file not found += FFFD ED_PATH equ -03 ; path not found += FFFC ED_HANDLE equ -04 ; too many open files + PC-DOS RASM-86 1.4a Source: DOSMEM.A86 Page 9 + + += FFFB ED_ACCESS equ -05 ; file access denied += FFFA ED_H_MATCH equ -06 ; invalid handle number += FFF9 ED_DMD equ -07 ; memory descriptor destroyed += FFF8 ED_MEMORY equ -08 ; insufficient memory += FFF7 ED_BLOCK equ -09 ; invalid memory block addr += FFF6 ED_ENVIRON equ -10 ; invalid environment += FFF5 ED_FORMAT equ -11 ; invalid format += FFF4 ED_ACC_CODE equ -12 ; invalid access code += FFF3 ED_DATA equ -13 ; invalid data += FFF1 ED_DRIVE equ -15 ; invalid drive specified += FFF0 ED_DIR equ -16 ; can't remove current dir += FFEF ED_DEVICE equ -17 ; not same device += FFEE ED_ROOM equ -18 ; no more files += += FFED ED_PROTECT equ -19 ; disk write protected += FFEC ED_BADUNIT equ -20 ; invalid drive specified += FFEB ED_NOTREADY equ -21 ; drive doesn't respond += FFEA ED_BADCMD equ -22 ; invalid command to driver += FFE9 ED_BADDATA equ -23 ; data CRC error += FFE8 ED_BADRHLEN equ -24 ; (shouldn't happen) += FFE7 ED_BADSEEK equ -25 ; can't seek to track += FFE6 ED_BADMEDIA equ -26 ; unrecognizable medium += FFE5 ED_RNF equ -27 ; record/sector not found += FFE4 ED_NOPAPER equ -28 ; printer error += FFE3 ED_WRFAIL equ -29 ; write failed += FFE2 ED_RDFAIL equ -30 ; read failed += FFE1 ED_GENFAIL equ -31 ; anything failed += FFE0 ED_SHAREFAIL equ -32 ; sharing conflict += FFDF ED_LOCKFAIL equ -33 ; locking conflict += FFDE ED_DISKCHG equ -34 ; invalid disk change += FFDD ED_NOFCBS equ -35 ; FCB table exhausted += FFDC ED_NOLOCKS equ -36 ; lock list items exhausted += FFCE ED_NET equ -50 ; Network Request Not Supported += += FFBF ED_NETACCESS equ -65 ; file access denied += += FFB7 ED_NETPWD equ -73 ; Server Password Error += FFB6 ED_NETVER equ -74 ; Incorrect Server version += FFB5 ED_NETREQ equ -75 ; No Local Network Resources += FFB4 ED_NETTIME equ -76 ; Network Time Out Error += FFB3 ED_NETCOMM equ -77 ; Network Communications Error += FFB2 ED_NETSRVR equ -78 ; No Server Network Resources += FFB1 ED_NETLOG equ -79 ; Server Not Logged In += += FFB0 ED_EXISTS equ -80 ; file already exists += FFAE ED_MAKE equ -82 ; Cannot Make (Files ??) += FFAD ED_FAIL equ -83 ; FAIL code returned from INT 24 += FFAC ED_STRUCT equ -84 ; Out of Structures += FFAB ED_ASSIGN equ -85 ; Already Assigned += FFAA ED_PASSWORD equ -86 ; Invalid Password += FFA9 ED_PARAM equ -87 ; Invalid Parameter += FFA8 ED_NETWRITE equ -88 ; Network write fault + PC-DOS RASM-86 1.4a Source: DOSMEM.A86 Page 10 + + += FFA7 ED_NETFUNC equ -89 ; Function not supported on network += FFA6 ED_COMPONENT equ -90 ; system component not installed += FFA6 ED_LASTERROR equ -90 ; Last Error Number Used += += += 0001 CLASS_RESOURCE equ 1 ; Out of Resource += 0002 CLASS_TEMP equ 2 ; Temporary Situation += 0003 CLASS_AUTHOR equ 3 ; Authorization Error += 0004 CLASS_INTERNAL equ 4 ; Internal System Software Error += 0005 CLASS_HARDWARE equ 5 ; Hardware Failure += 0006 CLASS_SYSTEM equ 6 ; Serious System Failure += 0007 CLASS_APPLIC equ 7 ; Application Program Error += 0008 CLASS_LOST equ 8 ; File/Item Not Found += 0009 CLASS_FORMAT equ 9 ; File/Item Illegal Format += 000A CLASS_LOCKED equ 10 ; File/Item Locked += 000B CLASS_MEDIA equ 11 ; Media Failure += 000C CLASS_EXISTS equ 12 ; Item Already Exists += 000D CLASS_UNKNOWN equ 13 ; Unknown Classification += += 0001 ACT_RETRY equ 1 ; Retry a few times then prompt user += 0002 ACT_DELAY equ 2 ; Delay then as ACT_RETRY += 0003 ACT_USER equ 3 ; Prompt user to re-enter data += 0004 ACT_ABORT equ 4 ; Clean Up then ABORT the process += 0005 ACT_TERM equ 5 ; Terminate immeadiately NO CLEAN UP += 0006 ACT_IGNORE equ 6 ; Ignore the Error += 0007 ACT_URETRY equ 7 ; Retry the error after user intervention += += 0001 LOC_UNKNOWN equ 1 ; Unknown error location += 0002 LOC_BLOCK equ 2 ; Block Device Failure += 0003 LOC_NET equ 3 ; Network Failure += 0004 LOC_CHAR equ 4 ; Related to Serial/Character devices += 0005 LOC_MEMORY equ 5 ; Failure related to Memory + + + 0001 BEST_FIT equ 01h ; allocate BEST match memory block + 0002 LAST_FIT equ 02h ; allocate LAST matching memory block + 0080 UPPER_FIT equ 80h ; preferably allocate from upper memory + 0040 UPPER_ONLY_FIT equ 40h ; only allocate from upper memory + + 0004 FIRST_FIT equ 04h ; we use this internally... + + PCM_CODE CSEG BYTE + extrn error_exit:near ; Standard Error Handler + extrn return_AX_CLC:near + extrn return_BX:near + extrn reload_ES:near + extrn toupper:near + + ; ***************************** + ; *** DOS Function 48 *** + ; *** Allocate Memory Block *** + ; ***************************** + PC-DOS RASM-86 1.4a Source: DOSMEM.A86 Page 11 + + + ; + Public func48 + func48: ; bx = request size + 0000 FF1E0000 E callf lock_tables ; lock global tables + 0004 E85201 0159 call search_mem ; look for block bx or bigger + 0007 724F 0058 jc memory_avbl_error ; skip on error + 0009 F606000002 E test mem_strategy,LAST_FIT ; is it last fit ? + 000E 740E 001E jz f48_10 ; no, use from begining + 0010 8BC1 mov ax,cx ; work out how much we have + 0012 2BC3 sub ax,bx ; to leave free + 0014 7408 001E je f48_10 + 0016 48 dec ax + 0017 8BD8 mov bx,ax + 0019 E8FF01 021B call make_dmd ; allocate this DMD as free + 001C 8BD9 mov bx,cx ; real block is the next one + f48_10: + 001E A10000 E mov ax,current_psp ; Change the Owner + 0021 26A30100 mov DMD_PSP,ax ; we now own this block + + 0025 06 push es + 0026 E8F201 021B call make_dmd ; make new DMD for allocated mem + 0029 58 pop ax + 002A 40 inc ax ; return starting segment + 002B EB24 0051 jmps memory_exit ; unlock global tables + + + ; ***************************** + ; *** DOS Function 49 *** + ; *** Free Memory Block *** + ; ***************************** + ; + Public func49 + func49: + 002D FF1E0000 E callf lock_tables ; lock global tables + 0031 E81302 0247 call get_dmd ; es -> dmd + 0034 7227 005D jc memory_error ; skip if block invalid + 0036 26A10100 mov ax,DMD_PSP ; get owner field + 003A 3B060000 E cmp ax,dmd_owner + 003E 8CC0 mov ax,es ; return DMD address in AX + 0040 7208 004A jb func49_10 + 0042 8B160000 E mov dx,dmd_address ; nothing below this block get's freed + 0046 3BC2 cmp ax,dx ; should we free it ? + 0048 7202 004C jb func49_20 ; no, give it a new owner + func49_10: + 004A 33D2 xor dx,dx ; yes, owner = 0 means free block + func49_20: + 004C 2689160100 mov DMD_PSP,dx ; free/set new owner + ; jmps memory_exit + + ; centralised exit point to unlock system tables + + memory_exit: + PC-DOS RASM-86 1.4a Source: DOSMEM.A86 Page 12 + + + ;----------- + ; On Entry: + ; AX = return value + ; On Exit + ; None + ; + 0051 FF1E0000 E callf unlock_tables ; unlock global tables + 0055 E90000 E jmp return_AX_CLC ; return DMD address + + memory_avbl_error: + 0058 8BD9 mov bx,cx + 005A E80000 E call return_BX ; return biggest block available + memory_error: + 005D FF1E0000 E callf unlock_tables ; unlock global tables + 0061 C606000005 E mov locus,LOC_MEMORY + 0066 E90000 E jmp error_exit ; Jump to error handler + + + ; ***************************** + ; *** DOS Function 4A *** + ; *** Alter Memory Block *** + ; ***************************** + ; + Public func4A + func4A: + 0069 FF1E0000 E callf lock_tables ; lock global tables + 006D E8D701 0247 call get_dmd ; es -> dmd + 0070 72EB 005D jc memory_error ; skip if block invalid + + 0072 26FF360300 push DMD_LEN ; save the current DMD length + 0077 E87301 01ED call merge_mem ; pick up unallocated blocks + 007A 58 pop ax ; return original DMD length + 007B 72E0 005D jc memory_error ; if dmd's destroyed + + 007D B8F8FF mov ax,ED_MEMORY ; assume insufficient mem + 0080 268B0E0300 mov cx,DMD_LEN ; cx = available size + 0085 3BCB cmp cx,bx ; if avail < req, then + 0087 72CF 0058 jb memory_avbl_error ; return maximum possible + + 0089 A10000 E mov ax,current_psp ; Force this block to be owned by the + 008C 26A30100 mov DMD_PSP,ax ; current PSP. MACE Utilities + + 0090 E88801 021B call make_dmd ; new block on top + 0093 E80000 E call reload_ES + 0096 8CC0 mov ax,es + 0098 EBB7 0051 jmps memory_exit + + ; ***************************** + ; *** DOS Function 58 *** + ; *** Get/Set Alloc Strategy*** + ; ***************************** + ; + PC-DOS RASM-86 1.4a Source: DOSMEM.A86 Page 13 + + + ; On Entry:- AL == 0 Get Allocation Strategy + ; AL == 1 Set Allocation Strategy + ; AL == 2 Get Upper Memory Link + ; AL == 3 Set Upper Memory Link + Public func58 + + func58: + 009A FF1E0000 E callf lock_tables ; lock global tables + 009E 3C03 cmp al,3 + 00A0 770E 00B0 ja f58_error ; Range Check Sub-Function + 00A2 98 cbw ; AH = 0 + 00A3 8BF0 mov si,ax + 00A5 03F6 add si,si ; SI = word offset of sub-function + 00A7 2EFF94B500 R call cs:f58_tbl[si] ; execute the sub-function + 00AC 73A3 0051 jnc memory_exit ; return the result + 00AE EBAD 005D jmps memory_error ; or the error + + + f58_error: + 00B0 B8FFFF mov ax,ED_FUNCTION + 00B3 EBA8 005D jmps memory_error + + 00B5 BD00 R f58_tbl dw f58_get_strategy + 00B7 C100 R dw f58_set_strategy + 00B9 C800 R dw f58_get_link + 00BB CE00 R dw f58_set_link + + f58_get_strategy: + ; mov ah,0 ; AX = subfunction = 0-3 + 00BD A00000 E mov al,mem_strategy + ; clc + 00C0 C3 ret + + f58_set_strategy: + 00C1 B458 mov ah,MS_M_STRATEGY + 00C3 881E0000 E mov mem_strategy,bl + ; clc + 00C7 C3 ret + + f58_get_link: + 00C8 B458 mov ah,MS_M_STRATEGY + 00CA A00000 E mov al,dmd_upper_link + ; clc + 00CD C3 ret + + f58_set_link: + 00CE B8FFFF mov ax,ED_FUNCTION ; return function not implemented + 00D1 8B0E0000 E mov cx,dmd_upper_root ; if no upper memory chain + 00D5 41 inc cx ; CX = FFFF + 00D6 F9 stc + 00D7 E328 0101 jcxz f58_set_link20 + 00D9 49 dec cx + PC-DOS RASM-86 1.4a Source: DOSMEM.A86 Page 14 + + + 00DA 881E0000 E mov dmd_upper_link,bl ; set link field + 00DE A10000 E mov ax,dmd_root ; now find dmd before upper memory root + 00E1 B24D mov dl,IDM ; assume we want to link + 00E3 84DB test bl,bl ; do we want to link/unlink UMBs? + 00E5 7502 00E9 jnz f58_set_link10 + 00E7 B25A mov dl,IDZ ; no, we want to unlink + f58_set_link10: + 00E9 8EC0 mov es,ax ; point to DMD + 00EB E86101 024F call check_dmd_id ; stop if id is invalid + 00EE 7211 0101 jc f58_set_link20 ; and return an error + 00F0 06 push es + 00F1 E8EE00 01E2 call next_dmd ; does the next DMD match our + 00F4 07 pop es + 00F5 3BC1 cmp ax,cx ; upper memory chain ? + 00F7 75F0 00E9 jne f58_set_link10 + 00F9 2688160000 mov DMD_ID,dl ; set appropriate link type + 00FE B80358 mov ax,(MS_M_STRATEGY*256)+3; return AX unchanged + ; clc + f58_set_link20: + 0101 C3 ret + + + + + PC-DOS RASM-86 1.4a Source: DOSMEM.A86 Page 15 + + + eject + ;**************************************** + ;* * + ;* Memory Function Subroutines * + ;* * + ;**************************************** + ; + ; FREE_ALL takes the PSP passed in the BX register and free's all + ; memory associated with that PSP. + ; + ; entry: bx = requested PSP + ; + ; exit: + ; + Public free_all + free_all: + 0102 8E060000 E mov es,dmd_root ; es -> first dmd + + free_all_loop: + 0106 E84601 024F call check_dmd_id ; if block is invalid + 0109 722C 0137 jc free_all_fail ; then quit now + + 010B 8AD0 mov dl,al ; dl = id code + 010D 26391E0100 cmp DMD_PSP,bx ; if block is owned by another + 0112 7507 011B jnz free_all_next ; then check next + + 0114 268126010000 and DMD_PSP,0 ; Free this partition + 00 + + free_all_next: + 011B 06 push es + 011C E8C300 01E2 call next_dmd ; es -> next block up + 011F 58 pop ax + 0120 80FA4D cmp dl,IDM ; if previous block wasn't last + 0123 74E1 0106 jz free_all_loop ; then keep going + 0125 39060000 E cmp dmd_upper_root,ax + 0129 760A 0135 jbe free_all_end + 012B A10000 E mov ax,dmd_upper_root ; free UMBs as well + 012E 3DFFFF cmp ax,-1 ; if UMB head is valid + 0131 8EC0 mov es,ax + 0133 75D1 0106 jne free_all_loop + free_all_end: + 0135 33C0 xor ax,ax ; Otherwise Stop + + free_all_fail: + 0137 C3 ret + + ; + ; SET_OWNER allows the OWNING PSP to specify the new owner of + ; the partition. An error is returned if an incorrect partition address + ; is given or the partition is not owned by the current PSP. + ; + PC-DOS RASM-86 1.4a Source: DOSMEM.A86 Page 16 + + + ; Entry:- AX == New PSP + ; BX == Partition Start + ; + ; Exit:- + ; no carry AX == Unknown + ; carry AX == Error Code + ; + Public set_owner + set_owner: + 0138 06 push es + 0139 4B dec bx + 013A 8EC3 mov es,bx ; ES points at DMD (We Hope) + 013C 93 xchg ax,bx ; Save the New PSP address in BX + 013D E80F01 024F call check_dmd_id ; Check for a valid DMD + 0140 7215 0157 jc s_o20 + 0142 A10000 E mov ax,current_psp + 0145 263B060100 cmp ax,DMD_PSP ; Check the Current PSP owns the memory + 014A 7507 0153 jnz s_o10 + 014C 26891E0100 mov DMD_PSP,bx ; Set the new owner and return + 0151 EB04 0157 jmps s_o20 + + s_o10: + 0153 B8F7FF mov ax,ED_BLOCK + 0156 F9 stc + s_o20: + 0157 07 pop es + 0158 C3 ret + + ; + ; Search for a free memory block at least as big as bx + ; entry: bx = requested size + ; success exit: cf clear, es -> dmd + ; cx = block size + ; failure exit: cf set, ax = error code + ; cx = biggest block available + + search_mem: + 0159 B8F9FF mov ax,ED_DMD ; assume bad DMD chain + 015C 8B0E0000 E mov cx,dmd_root ; start at the bottom + 0160 E366 01C8 jcxz search_mem_exit + 0162 8EC1 mov es,cx ; lets clean up memory list + 0164 800E000004 E or mem_strategy,FIRST_FIT ; grab 1st block we come to + search_mem_init: + 0169 33F6 xor si,si ; si = max mem available + 016B BFFFFF mov di,0FFFFh ; di = size of candiate (FFFF=none) + ; dx = dmd of candidate + search_mem_loop: + 016E E8DE00 024F call check_dmd_id ; if block is invalid + 0171 7255 01C8 jc search_mem_exit ; then quit now + + 0173 26833E010000 cmp DMD_PSP,0 ; if block is owned + 0179 752F 01AA jnz search_mem_next ; then check another + PC-DOS RASM-86 1.4a Source: DOSMEM.A86 Page 17 + + + + 017B E86F00 01ED call merge_mem ; group with unallocated blocks + + 017E 8CC0 mov ax,es ; AX = current DMD + 0180 268B0E0300 mov cx,DMD_LEN ; cx = block length + + 0185 3BCE cmp cx,si ; is it the biggest block we + 0187 7202 018B jb search_mem40 ; have found so far ? + 0189 8BF1 mov si,cx ; if so then save the new size + search_mem40: + + 018B 3BCB cmp cx,bx ; if it's not long enough + 018D 721B 01AA jb search_mem_next ; then try the next block + + 018F F606000006 E test mem_strategy,FIRST_FIT+LAST_FIT + 0194 750B 01A1 jnz search_mem50 ; grab this block ? + + 0196 F606000001 E test mem_strategy,BEST_FIT ; if BEST FIT then we only save this + 019B 740D 01AA jz search_mem_next ; candidate if the previous + 019D 3BCF cmp cx,di ; candidate was bigger + 019F 7309 01AA jae search_mem_next + search_mem50: + 01A1 8CC2 mov dx,es ; save this DMD candidate + 01A3 8BF9 mov di,cx ; along with it's length + 01A5 80260000FB E and mem_strategy,not FIRST_FIT + search_mem_next: + 01AA E82D00 01DA call search_next_dmd ; try for another DMD + 01AD B8F8FF mov ax,ED_MEMORY ; assume insufficient mem + 01B0 7216 01C8 jc search_mem_exit ; stop if it's true + + 01B2 8CC0 mov ax,es + 01B4 3B060000 E cmp ax,dmd_upper_root ; if we reach the dmd upper root + 01B8 75B4 016E jne search_mem_loop ; then we have a special case + 01BA 800E000004 E or mem_strategy,FIRST_FIT ; grab 1st high memory block we find + 01BF F606000040 E test mem_strategy,UPPER_ONLY_FIT + 01C4 75A3 0169 jnz search_mem_init ; upper only is another special case + 01C6 EBA6 016E jmps search_mem_loop + + search_mem_exit: + 01C8 80260000FB E and mem_strategy,not FIRST_FIT + 01CD 8BCF mov cx,di ; DX&DI contain our best candidate + 01CF 47 inc di ; if DI=FFFF then we don't have one + 01D0 7404 01D6 je search_mem_bad ; else we return with CX = size + 01D2 8EC2 mov es,dx ; and ES = DMD + 01D4 F8 clc ; clear the error flag + 01D5 C3 ret + + search_mem_bad: + 01D6 8BCE mov cx,si ; no allocation made, so return + search_mem_error: ; biggest block and flag the error + 01D8 F9 stc + 01D9 C3 ret + PC-DOS RASM-86 1.4a Source: DOSMEM.A86 Page 18 + + + + search_next_dmd: + ; On Entry: + ; ES = current DMD + ; On Exit: + ; ES = AX = next DMD + ; DX/DI preserved + ; + 01DA 26803E00004D cmp DMD_ID,IDM ; do we have any more blocks ? + 01E0 75F6 01D8 jne search_mem_error ; no, return CY set + ; jmp next_dmd ; else try next DMD + + ; Point to next DOS Memory Descriptor (dmd) in the chain + ; entry: es -> current dmd + ; exit: es -> next dmd + + next_dmd: + 01E2 8CC0 mov ax,es + 01E4 2603060300 add ax,DMD_LEN + 01E9 40 inc ax ; allow for dmd itself + 01EA 8EC0 mov es,ax + 01EC C3 ret + + ; Increase the size of the current mem block + ; by gobbling all adjacent unallocated blocks + ; entry: es -> dmd + ; exit: cf = 1, al = 7 if chain is broken + ; ES,SI,DI,DX,BX preserved + + merge_mem: + 01ED 06 push es + 01EE 26803E00004D cmp DMD_ID,IDM ; if no more dmd's + 01F4 7522 0218 jnz merge_mem_done ; then just quit + + 01F6 E8E9FF 01E2 call next_dmd + 01F9 E85300 024F call check_dmd_id ; if id is invalid + 01FC 721B 0219 jc merge_mem_quit ; then return an error + + 01FE 26833E010000 cmp DMD_PSP,0 ; if next dmd is owned + 0204 7512 0218 jnz merge_mem_done ; then done + + 0206 268B0E0300 mov cx,DMD_LEN ; if free, grab its length + 020B 07 pop es ; restore base dmd + + 020C 26A20000 mov DMD_ID,al ; use next's id (in case of last) + 0210 41 inc cx + 0211 26010E0300 add DMD_LEN,cx ; add new memory to base + 0216 EBD5 01ED jmps merge_mem ; and try again + + merge_mem_done: + 0218 F8 clc ; clear error flag + merge_mem_quit: + PC-DOS RASM-86 1.4a Source: DOSMEM.A86 Page 19 + + + 0219 07 pop es ; restore base dmd + 021A C3 ret ; with cf and error flag + + + ; If needed, create a new dmd on top of allocated memory + ; entry: es -> current block + ; bx = requested block size + ; cx = current block size + + make_dmd: + 021B 3BD9 cmp bx,cx ; if request and size match + 021D 7427 0246 jz make_dmd_done ; then that's all we need + + 021F 268A160000 mov dl,DMD_ID ; get current block id + 0224 26891E0300 mov DMD_LEN,bx ; else shrink this block + 0229 26C60600004D mov DMD_ID,IDM ; not the last now + 022F E8B0FF 01E2 call next_dmd + 0232 2688160000 mov DMD_ID,dl ; our old id for the new dmd + 0237 26C706010000 mov DMD_PSP,0 ; new block is free + 00 + 023E 2BCB sub cx,bx + 0240 49 dec cx + 0241 26890E0300 mov DMD_LEN,cx ; length is whatever is left + + make_dmd_done: + 0246 C3 ret + + ; Get passed value of memory block + ; exit: es -> dmd + ; al = DMD_ID, cf cleared if valid + ; al = 7, cf set if invalid + + get_dmd: + 0247 E80000 E call reload_ES + 024A 8CC0 mov ax,es + 024C 48 dec ax ; back up to dmd + 024D 8EC0 mov es,ax + ; jmps check_dmd_id ; fall through + + ; Check first byte in the dmd for a valid id code + ; entry: es -> dmd + ; exit: al = DMD_ID, cf cleared if valid + ; al = 7, cf set if invalid + + Public check_dmd_id + + check_dmd_id: + 024F 26A00000 mov al,DMD_ID + 0253 3C4D cmp al,IDM ; if not last + 0255 7408 025F jz check_dmd_done ; then good + 0257 3C5A cmp al,IDZ ; if last + 0259 7404 025F jz check_dmd_done ; also good + PC-DOS RASM-86 1.4a Source: DOSMEM.A86 Page 20 + + + + 025B B8F7FF mov ax,ED_BLOCK ; Invalid DMD + check_dmd_error: + 025E F9 stc ; flag the error + check_dmd_done: + 025F C3 ret + + + PCMODE_DATA DSEG + + extrn lock_tables:dword + extrn unlock_tables:dword + + extrn dmd_address:word ; don't free DMD's with segment under this value + extrn dmd_owner:word ; don't free DMD's with owner under this value + extrn dmd_upper_root:word + extrn dmd_upper_link:byte + extrn current_psp:word + extrn locus:byte + extrn mem_strategy:byte + extrn dmd_root:word + + end + + +End of assembly. Number of errors: 0. Use factor: 16% + ; don't free DMD's with owner under this value + extrn dm \ No newline at end of file diff --git a/IBMDOS/BIN/DOSMEM.OBJ b/IBMDOS/BIN/DOSMEM.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..7b747a57af4231c622c5637c21b2bbf5b439c16c GIT binary patch literal 1664 zcmcgr|7#m%7=NC-rNttO@B*vaKhOE>mk<9T?5cwRclXXqSqio5)y z5qJV18pbxE-iL&kh@W!=&?RCYp&URwjL{BCh#2d5lOpyKqS%y(KX<&{VGMP+RU-b> z;Z{qCgeoam6UK`jZfzKW5Y@Or#9KSux(NQ&K{tx{_pw#b!xAjcx>$-uS%_hrsGC@X z2`tRIS&~UCmS}|Ny(TWdYJnicOwDri`%9WJh$v;trOeJjfDYOvL07L043V%0w(ZNQVhpNynsx zv$WCu7|)aqLn~R%xH*ndUNp!V=SWdiLo-c`@k1~J+&y;~1OT=Pz&FsRG|B97;?b`$KTEX2aA4f=2z)aJP)_VZbi>@&6wLIN}LBdM_ z^$UI{`6na`6A{FIgKk@9yG8I1Vc+a7@B|yZxE=Ryu@l~Q!ozmAr`jpcw4;-DR-Akw z8}=MK>OEo$laFU3-qSV;yzv*H;{GsymC5y#2S+Cn zxU`ME{yrQ!(LOoPSo__NU;#dZvoHtHI$fC}A$|CPy!8}-vV5^O&uL0}syO*wO*nO+ z(ew|ZyIS%u!|~Z6@K)K0$qm_yBY+E)Y3mNeFAz2-T`1eq^o(SMHxPauCvvjgZmlb5GS-wGBe k*J#SL62rx6bof9um}u+m*)U8x*;xM(`r}kL{9o_?5BmZ6K>z>% literal 0 HcmV?d00001 diff --git a/IBMDOS/BIN/DOSMEM.SYM b/IBMDOS/BIN/DOSMEM.SYM new file mode 100644 index 0000000..113f60f --- /dev/null +++ b/IBMDOS/BIN/DOSMEM.SYM @@ -0,0 +1,101 @@ + 0000 VARIABLES +0000 CURRENT_PSP 0000 DMD_ADDRESS 0000 DMD_ID +0006 DMD_IDLE_FLAGS 0003 DMD_LEN 0008 DMD_NAME 0000 DMD_OWNER +0001 DMD_PSP 0000 DMD_ROOT 0000 DMD_UPPER_LINK +0000 DMD_UPPER_ROOT 00B5 F58_TBL 0000 FDOS_DATA +0000 LOCK_TABLES 0000 LOCUS 0000 MEM_STRATEGY +0001 REG_AH 0000 REG_AL 0000 REG_AX 0003 REG_BH 0002 REG_BL +000C REG_BP 0002 REG_BX 0005 REG_CH 0004 REG_CL 0014 REG_CS +0004 REG_CX 0007 REG_DH 000A REG_DI 0006 REG_DL 000E REG_DS +0006 REG_DX 0010 REG_ES 0016 REG_FLAGS 0012 REG_IP 0008 REG_SI +0000 UNLOCK_TABLES + +0000 NUMBERS +0004 ACT_ABORT 0002 ACT_DELAY 0006 ACT_IGNORE 0001 ACT_RETRY 0005 ACT_TERM +0007 ACT_URETRY 0003 ACT_USER 0001 BEST_FIT 0001 CARRY_FLAG +0007 CLASS_APPLIC 0003 CLASS_AUTHOR +000C CLASS_EXISTS 0009 CLASS_FORMAT +0005 CLASS_HARDWARE 0004 CLASS_INTERNAL +000A CLASS_LOCKED 0008 CLASS_LOST 000B CLASS_MEDIA +0001 CLASS_RESOURCE 0006 CLASS_SYSTEM 0002 CLASS_TEMP +000D CLASS_UNKNOWN 0400 DIR_FLAG 0008 DMD_NAME_LEN +0021 DOS_INT FFFB ED_ACCESS FFF4 ED_ACC_CODE FFAB ED_ASSIGN +FFEA ED_BADCMD FFE9 ED_BADDATA FFE6 ED_BADMEDIA +FFE8 ED_BADRHLEN FFE7 ED_BADSEEK FFEC ED_BADUNIT FFF7 ED_BLOCK +FFA6 ED_COMPONENT FFF3 ED_DATA FFEF ED_DEVICE FFF0 ED_DIR +FFDE ED_DISKCHG FFF9 ED_DMD FFF1 ED_DRIVE FFF6 ED_ENVIRON FFB0 ED_EXISTS +FFAD ED_FAIL FFFE ED_FILE FFF5 ED_FORMAT FFFF ED_FUNCTION +FFE1 ED_GENFAIL FFFC ED_HANDLE FFFA ED_H_MATCH FFA6 ED_LASTERROR +FFDF ED_LOCKFAIL FFAE ED_MAKE FFF8 ED_MEMORY FFCE ED_NET +FFBF ED_NETACCESS FFB3 ED_NETCOMM FFA7 ED_NETFUNC FFB1 ED_NETLOG +FFB7 ED_NETPWD FFB5 ED_NETREQ FFB2 ED_NETSRVR FFB4 ED_NETTIME FFB6 ED_NETVER +FFA8 ED_NETWRITE FFDD ED_NOFCBS FFDC ED_NOLOCKS FFE4 ED_NOPAPER +FFEB ED_NOTREADY FFA9 ED_PARAM FFAA ED_PASSWORD +FFFD ED_PATH FFED ED_PROTECT FFE2 ED_RDFAIL FFE5 ED_RNF FFEE ED_ROOM +FFE0 ED_SHAREFAIL FFAC ED_STRUCT FFE3 ED_WRFAIL 0002 ERR_ABORT +0003 ERR_FAIL 0000 ERR_IGNORE 0001 ERR_RETRY 0000 FALSE 0004 FIRST_FIT +0001 IDLE_COMMAND FFFF IDLE_DETECT +C000 IDLE_DISABLE 0002 IDLE_DOSFUNC 8000 IDLE_INIT +0004 IDLE_INT28 4000 IDLE_ON 004D IDM 005A IDZ 0200 INT_FLAG +0002 LAST_FIT 0002 LOC_BLOCK 0004 LOC_CHAR 0005 LOC_MEMORY 0003 LOC_NET +0001 LOC_UNKNOWN 000D MAX_FILELEN +0050 MAX_PATHLEN 0003 MS_A_READ 0004 MS_A_WRITE 000C MS_C_FLUSH +0008 MS_C_NOECHO 0007 MS_C_RAWIN 0006 MS_C_RAWIO 0001 MS_C_READ +000A MS_C_READSTR 000B MS_C_STAT 0002 MS_C_WRITE +0009 MS_C_WRITESTR 001B MS_DRV_ALLOC +001C MS_DRV_ALLOCSPEC 000D MS_DRV_ALLRESET 0019 MS_DRV_GET +000E MS_DRV_SET 0036 MS_DRV_SPACE 0010 MS_F_CLOSE +0013 MS_F_DELETE 002F MS_F_DMAGET +001A MS_F_DMAOFF 0059 MS_F_ERROR 0054 MS_F_GETVERIFY +005C MS_F_LOCK 0016 MS_F_MAKE 000F MS_F_OPEN 0029 MS_F_PARSE +0024 MS_F_RANDREC 0014 MS_F_READ 0027 MS_F_READBLK +0021 MS_F_READRAND 0017 MS_F_RENAME +0011 MS_F_SFIRST 0023 MS_F_SIZE 0012 MS_F_SNEXT +002E MS_F_VERIFY 0015 MS_F_WRITE 0028 MS_F_WRITEBLK +0022 MS_F_WRITERAND 0005 MS_L_WRITE 0048 MS_M_ALLOC 0049 MS_M_FREE +004A MS_M_SETBLOCK 0058 MS_M_STRATEGY +0062 MS_P_GETPSP 0026 MS_P_MKPSP 0050 MS_P_SETPSP +0000 MS_P_TERMCPM 0031 MS_P_TERMKEEP +0030 MS_S_BDOSVER 0033 MS_S_BREAK 0038 MS_S_COUNTRY +0035 MS_S_GETINT 0025 MS_S_SETINT +002A MS_T_GETDATE 002C MS_T_GETTIME +002B MS_T_SETDATE 002D MS_T_SETTIME 003B MS_X_CHDIR +0043 MS_X_CHMOD 003E MS_X_CLOSE 0068 MS_X_COMMIT 003C MS_X_CREAT +0047 MS_X_CURDIR 0057 MS_X_DATETIME 0045 MS_X_DUP +0046 MS_X_DUP2 004B MS_X_EXEC 004C MS_X_EXIT 0060 MS_X_EXPAND +004E MS_X_FIRST 6601 MS_X_GETCP 0044 MS_X_IOCTL 0042 MS_X_LSEEK 0039 MS_X_MKDIR +005B MS_X_MKNEW 005A MS_X_MKTEMP 004F MS_X_NEXT 003D MS_X_OPEN +003F MS_X_READ 0056 MS_X_RENAME 003A MS_X_RMDIR 6602 MS_X_SETCP +0067 MS_X_SETHC 0041 MS_X_UNLINK 004D MS_X_WAIT 0040 MS_X_WRITE +0040 NO_CRIT_ERRORS 0800 OFLW_FLAG 0008 OK_FAIL 0020 OK_IGNORE +0010 OK_RETRY 0018 OK_RF 0030 OK_RI 0038 OK_RIF 0004 PROC_DEVIN +0001 PROC_IDLE 0002 PROC_INT28 0003 PROC_KEYIN 0080 SIGN_FLAG 00C0 STACK_SIZE +0003 STDAUX 0002 STDERR 0000 STDIN 0001 STDOUT 0004 STDPRN +0001 TERM_BREAK 0002 TERM_ERROR 0000 TERM_NORMAL +0003 TERM_RESIDENT FFFF TRUE 0006 TRUE_VERSION +0080 UPPER_FIT 0040 UPPER_ONLY_FIT 0040 ZERO_FLAG 0001 __RASM__ + +0000 LABELS +025F CHECK_DMD_DONE 025E CHECK_DMD_ERROR +024F CHECK_DMD_ID 0000 ERROR_EXIT 001E F48_10 00B0 F58_ERROR +00C8 F58_GET_LINK 00BD F58_GET_STRATEGY +00CE F58_SET_LINK 00E9 F58_SET_LINK10 +0101 F58_SET_LINK20 00C1 F58_SET_STRATEGY 0102 FREE_ALL +0135 FREE_ALL_END 0137 FREE_ALL_FAIL +0106 FREE_ALL_LOOP 011B FREE_ALL_NEXT 0000 FUNC48 +002D FUNC49 004A FUNC49_10 004C FUNC49_20 0069 FUNC4A 009A FUNC58 +0247 GET_DMD 021B MAKE_DMD 0246 MAKE_DMD_DONE +0058 MEMORY_AVBL_ERROR 005D MEMORY_ERROR +0051 MEMORY_EXIT 01ED MERGE_MEM 0218 MERGE_MEM_DONE +0219 MERGE_MEM_QUIT 01E2 NEXT_DMD 0000 RELOAD_ES +0000 RETURN_AX_CLC 0000 RETURN_BX 0159 SEARCH_MEM +018B SEARCH_MEM40 01A1 SEARCH_MEM50 +01D6 SEARCH_MEM_BAD 01D8 SEARCH_MEM_ERROR +01C8 SEARCH_MEM_EXIT 0169 SEARCH_MEM_INIT +016E SEARCH_MEM_LOOP 01AA SEARCH_MEM_NEXT +01DA SEARCH_NEXT_DMD 0138 SET_OWNER 0153 S_O10 0157 S_O20 +0000 TOUPPER +C58 +0247 GET_DMD 021B MAKE_DMD 0246 MAKE_DMD_DONE +0058 MEMORY_AVBL_ERROR 005D MEMORY_ERROR +0051 MEMORY_ \ No newline at end of file diff --git a/IBMDOS/BIN/ERROR.LST b/IBMDOS/BIN/ERROR.LST new file mode 100644 index 0000000..efdb2e8 --- /dev/null +++ b/IBMDOS/BIN/ERROR.LST @@ -0,0 +1,1475 @@ + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 1 + + += 0001 __RASM__ EQU 1 + + ; File : $ERROR.A86$ + ; + ; Description : + ; + ; Original Author : DIGITAL RESEARCH + ; + ; Last Edited By : $CALDERA$ + ; + ;-----------------------------------------------------------------------; + ; Copyright Work of Caldera, Inc. All Rights Reserved. + ; + ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, + ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. + ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES + ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF + ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO + ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE + ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE + ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, + ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, + ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, + ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF + ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT + ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND + ; CIVIL LIABILITY. + ;-----------------------------------------------------------------------; + ; + ; *** Current Edit History *** + ; *** End of Current Edit History *** + ; $Log$ + ; ERROR.A86 1.17 94/12/02 11:01:03 + ; added logical error entry + ; ERROR.A86 1.16 93/11/26 15:51:29 + ; Update char_error so ES:SI -> device driver header itself + ; ERROR.A86 1.14 93/09/09 22:36:26 + ; Int 21/59 uses error stack (for benefit of Lantastic) + ; ERROR.A86 1.13 93/09/03 20:28:11 + ; Add "no critical errors" support (int 21/6C) + ; ENDLOG + ; + ; This file contains the Error handling routines for PCMODE + ; When a function encounters an error it jumps to the ERROR_EXIT + ; function which will process the error consistantly. FCB_ERROR_EXIT + ; is a special case of ERROR_EXIT where the error code is not returned + ; directly to the user but is still saved for func59 + ; + += include pcmode.equ += ; File : $PCMODE.EQU$ += ; + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 2 + + += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += ; This file contains all the general purpose definitions += ; and equates used by the PCMODE Module. += ; += += FFFF TRUE equ 0FFFFh ; value of TRUE += 0000 FALSE equ 0 ; value of FALSE += += 0006 TRUE_VERSION equ 6 += += FFFF IDLE_DETECT equ TRUE ; Check for IDLE Process's += += if IDLE_DETECT += 0001 IDLE_COMMAND equ 0001h ; Command Processor Active += 0002 IDLE_DOSFUNC equ 0002h ; DOS Function Called += 0004 IDLE_INT28 equ 0004h ; INT 28 Called += += 4000 IDLE_ON equ 4000h ; ReSet when Idle Checking Enabled += 8000 IDLE_INIT equ 8000h ; ReSet when $IDLE$ Loaded and Active += C000 IDLE_DISABLE equ IDLE_INIT + IDLE_ON += += 0001 PROC_IDLE equ 0001 ; Process is IDLE + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 3 + + += 0002 PROC_INT28 equ 0002 ; INT28 Polling Loop += 0003 PROC_KEYIN equ 0003 ; Keyboard Input += 0004 PROC_DEVIN equ 0004 ; Device Input Routine += endif += += += 00C0 STACK_SIZE equ 192 ; Local Stack Size (Levels) += 0050 MAX_PATHLEN equ 80 ; Maximum Path length += 000D MAX_FILELEN equ 13 += += ; += ; DOS process termination Codes += ; += 0000 TERM_NORMAL equ 0 ; Normal Termination += 0001 TERM_BREAK equ 1 ; Termination by Control Break += 0002 TERM_ERROR equ 2 ; Termination by Critical Error += 0003 TERM_RESIDENT equ 3 ; Terminate and Stay Resident += += ; += ; Critical Error responses from the default INT 24 handler and += ; the DO_INT24 routine. += ; += 0000 ERR_IGNORE equ 0 ; Ignore Error += 0001 ERR_RETRY equ 1 ; Retry the Operation += 0002 ERR_ABORT equ 2 ; Terminate the Process += 0003 ERR_FAIL equ 3 ; Fail Function += ; += 0008 OK_FAIL equ 0000$1000b ; Fail is a Valid Response += 0010 OK_RETRY equ 0001$0000b ; Retry is a Valid Response += 0020 OK_IGNORE equ 0010$0000b ; Ignore is a valid Response += 0038 OK_RIF equ 0011$1000b ; All Responsese are Valid += 0030 OK_RI equ 0011$0000b ; Retry and Ignore are Valid += 0018 OK_RF equ 0001$1000b ; Retry and Fail are Valid += ; += 0040 NO_CRIT_ERRORS equ 0100$0000b ; critical error shouldn't be generated += ; warning - must match FDOS.A86 += ; + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 4 + + += eject += ; The following equates define the format in which the users registers += ; are saved on the stack. This format is also seen by an application += ; when a critical error occurs. += ; += CodeMacro POP$DOS ; Pop User Registers a la MS-DOS += db 058h ! db 05Bh ; pop AX ! pop BX += db 059h ! db 05Ah ; pop BX ! pop CX += db 05Eh ! db 05Fh ; pop SI ! pop DI += db 05Dh ; pop BP += db 01Fh ! db 007h ; pop DS ! pop ES += EndM += += CodeMacro PUSH$DOS ; Push User Registers += db 006h ! db 01Eh ; push ES ! push DS += db 055h ; push BP += db 057h ! db 056h ; push DI ! push SI += db 052h ! db 051h ; push DX ! push CX += db 053h ! db 050h ; push BX ! push AX += EndM += += 0000 reg_AX equ word ptr .00 += 0000 reg_AL equ byte ptr .00 += 0001 reg_AH equ byte ptr .01 += += 0002 reg_BX equ word ptr .02 += 0002 reg_BL equ byte ptr .02 += 0003 reg_BH equ byte ptr .03 += += 0004 reg_CX equ word ptr .04 += 0004 reg_CL equ byte ptr .04 += 0005 reg_CH equ byte ptr .05 += += 0006 reg_DX equ word ptr .06 += 0006 reg_DL equ byte ptr .06 += 0007 reg_DH equ byte ptr .07 += += 0008 reg_SI equ word ptr .08 += 000A reg_DI equ word ptr .10 += 000C reg_BP equ word ptr .12 += += 000E reg_DS equ word ptr .14 += 0010 reg_ES equ word ptr .16 += += 0012 reg_IP equ word ptr .18 += 0014 reg_CS equ word ptr .20 += 0016 reg_FLAGS equ word ptr .22 += += ; Processor Flags += 0001 CARRY_FLAG equ 0001h ; Carry Flag += 0040 ZERO_FLAG equ 0040h ; Zero Flag += 0080 SIGN_FLAG equ 0080h ; Sign Flag + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 5 + + += 0200 INT_FLAG equ 0200h ; Interrupt Flag += 0400 DIR_FLAG equ 0400h ; Direction Flag += 0800 OFLW_FLAG equ 0800h ; OverFlow Flag += += 0000 DMD_ID equ es:byte ptr .0 ; id code ('M' or 'Z') += 0001 DMD_PSP equ es:word ptr .1 ; owner of memory block += 0003 DMD_LEN equ es:word ptr .3 ; length of memory block += 0006 DMD_IDLE_FLAGS equ es:word ptr .6 ; idle flags live here += 0008 DMD_NAME equ es:byte ptr .8 ; ASCIIZ name field += 0008 DMD_NAME_LEN equ 8 ; 8 Bytes long += 004D IDM equ 'M' ; not last id code += 005A IDZ equ 'Z' ; last id code += += PCMCODE GROUP PCM_HEADER, PCM_CODE, BDOS_CODE, PCM_RODATA += PCMCODE GROUP PCM_HISTORY, PCM_ICODE, PCM_CODEND += += PCM_HEADER CSEG PARA += PCM_CODE CSEG BYTE += PCM_RODATA CSEG WORD += BDOS_CODE CSEG WORD += PCM_HISTORY CSEG BYTE += PCM_ICODE CSEG BYTE += PCM_CODEND CSEG PARA += += += PCMDATA GROUP PCMODE_DATA, FDOS_DSEG, FIXED_DOS_DATA += PCMDATA GROUP PCMODE_CODE, GLOBAL_DATA, BDOS_DATA, PCMODE_DSIZE += += PCMODE_DATA DSEG WORD ; DOS Data += FDOS_DSEG DSEG WORD COMMON ; FDOS Parameter Block +=0000 fdos_data rw 7 += FIXED_DOS_DATA CSEG WORD 'DATA' ; Fixed DOS Data Area += PCMODE_CODE CSEG WORD 'DATA' ; DATA relative CODE += GLOBAL_DATA DSEG WORD ; GLOBAL DOS DATA (Process Independant) += BDOS_DATA DSEG WORD ; BDOS Data Area += PCMODE_DSIZE DSEG PARA ; End of DOS Data Area + += include fdos.def += ; File : $FDOS.DEF$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 6 + + += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += += 0048 FD_DISKINFO equ 48h += 0049 FD_FLUSH equ 49h += 004A FD_SELECT equ 4Ah += 004B FD_EXEC equ 4Bh += 004C FD_EXIT equ 4Ch += 004D FD_FCB equ 4Dh += 0050 FD_COMMIT equ 50H += 0051 FD_NEW equ 51h += 0052 FD_LOCK equ 52h += 0054 FD_DDIO equ 54h += 0055 FD_EXPAND equ 55h += 0058 FD_REOPEN equ 58h += += 0007 FDOS_MAXPARM equ 7 ; Maximum FDOS Parameter Length (WORDS) += += 0000 FD_FUNC equ fdos_data += += 0002 FD_DRIVE equ fdos_data + 2 += 0004 FD_DPB equ dword ptr fdos_data + 4 += 0004 FD_DPBOFF equ fdos_data + 4 += 0006 FD_DPBSEG equ fdos_data + 6 += 0008 FD_ADJUST equ fdos_data + 8 += += 0002 FD_NAME equ dword ptr fdos_data + 2 += 0002 FD_NAMEOFF equ fdos_data + 2 += 0004 FD_NAMESEG equ fdos_data + 4 += += 0006 FD_MODE equ fdos_data + 6 += += 0002 FD_HANDLE equ fdos_data + 2 += += 0004 FD_BUF equ dword ptr fdos_data + 4 + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 7 + + += 0004 FD_BUFOFF equ fdos_data + 4 += 0006 FD_BUFSEG equ fdos_data + 6 += += 0008 FD_COUNT equ fdos_data + 8 += += 0004 FD_OFFSET equ dword ptr fdos_data + 4 += += 0008 FD_METHOD equ fdos_data + 8 += += 0006 FD_FLAG equ fdos_data + 6 += += 0008 FD_ATTRIB equ fdos_data + 8 += += 0004 FD_PATH equ dword ptr fdos_data + 4 += 0004 FD_PATHOFF equ fdos_data + 4 += 0006 FD_PATHSEG equ fdos_data + 6 += += 0002 FD_ONAME equ dword ptr fdos_data + 2 += 0002 FD_ONAMEOFF equ fdos_data + 2 += 0004 FD_ONAMESEG equ fdos_data + 4 += += 000A FD_NNAME equ dword ptr fdos_data + 10 += 000A FD_NNAMEOFF equ fdos_data + 10 += 000C FD_NNAMESEG equ fdos_data + 12 += += 0004 FD_SFLAG equ fdos_data + 4 += 0006 FD_DATE equ fdos_data + 6 += 0008 FD_TIME equ fdos_data + 8 += += 0008 FD_LENGTH equ dword ptr fdos_data + 8 += 000C FD_LFLAG equ word ptr fdos_data + 12 += += 0004 FD_NEWHND equ fdos_data + 4 += += 0002 FD_FCBADR equ dword ptr fdos_data + 2 += 0002 FD_FCBOFF equ fdos_data + 2 += 0004 FD_FCBSEG equ fdos_data + 4 += += 0006 FD_FCBCNT equ fdos_data + 6 += 0008 FD_FCBFUNC equ fdos_data + 8 += += 0002 FD_PSPSEG equ fdos_data + 2 += += 0002 FD_BPBOFF equ fdos_data + 2 += 0004 FD_BPBSEG equ fdos_data + 4 += 0006 FD_DDSCOFF equ fdos_data + 6 += 0008 FD_DDSCSEG equ fdos_data + 8 += += 0004 FD_IOCTLFUNC equ fdos_data + 4 += 0006 FD_IOCTLSTAT equ fdos_data + 6 += += 0002 FD_NUMOPEN equ fdos_data + 2 + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 8 + + += += 0002 FD_DDIO_DRV_OP equ fdos_data + 2 += 0004 FD_DDIO_NSECTORS equ fdos_data + 4 += 0006 FD_DDIO_STARTLOW equ fdos_data + 6 += 0008 FD_DDIO_STARTHIGH equ fdos_data + 8 += 000A FD_DDIO_DMAOFF equ fdos_data + 10 += 000C FD_DDIO_DMASEG equ fdos_data + 12 += + += include i:msdos.equ += ; File : $MSDOS.EQU$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += += += 0000 MS_P_TERMCPM equ 00H += 0001 MS_C_READ equ 01H += 0002 MS_C_WRITE equ 02H += 0003 MS_A_READ equ 03H += 0004 MS_A_WRITE equ 04H += 0005 MS_L_WRITE equ 05H += 0006 MS_C_RAWIO equ 06H + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 9 + + += 0007 MS_C_RAWIN equ 07H += 0008 MS_C_NOECHO equ 08H += 0009 MS_C_WRITESTR equ 09H += 000A MS_C_READSTR equ 0aH += 000B MS_C_STAT equ 0bH += 000C MS_C_FLUSH equ 0cH += 000D MS_DRV_ALLRESET equ 0dH += 000E MS_DRV_SET equ 0eH += 000F MS_F_OPEN equ 0fH += 0010 MS_F_CLOSE equ 10H += 0011 MS_F_SFIRST equ 11H += 0012 MS_F_SNEXT equ 12H += 0013 MS_F_DELETE equ 13H += 0014 MS_F_READ equ 14H += 0015 MS_F_WRITE equ 15H += 0016 MS_F_MAKE equ 16H += 0017 MS_F_RENAME equ 17H += 0019 MS_DRV_GET equ 19H += 001A MS_F_DMAOFF equ 1aH += 001B MS_DRV_ALLOC equ 1bH += 001C MS_DRV_ALLOCSPEC equ 1cH += 0021 MS_F_READRAND equ 21H += 0022 MS_F_WRITERAND equ 22H += 0023 MS_F_SIZE equ 23H += 0024 MS_F_RANDREC equ 24H += 0025 MS_S_SETINT equ 25H += 0026 MS_P_MKPSP equ 26H += 0027 MS_F_READBLK equ 27H += 0028 MS_F_WRITEBLK equ 28H += 0029 MS_F_PARSE equ 29H += 002A MS_T_GETDATE equ 2aH += 002B MS_T_SETDATE equ 2bH += 002C MS_T_GETTIME equ 2cH += 002D MS_T_SETTIME equ 2dH += 002E MS_F_VERIFY equ 2eH += 002F MS_F_DMAGET equ 2fH += 0030 MS_S_BDOSVER equ 30H += 0031 MS_P_TERMKEEP equ 31H += 0033 MS_S_BREAK equ 33H += 0035 MS_S_GETINT equ 35H += 0036 MS_DRV_SPACE equ 36H += 0038 MS_S_COUNTRY equ 38H += 0039 MS_X_MKDIR equ 39H += 003A MS_X_RMDIR equ 3aH += 003B MS_X_CHDIR equ 3bH += 003C MS_X_CREAT equ 3cH += 003D MS_X_OPEN equ 3dH += 003E MS_X_CLOSE equ 3eH += 003F MS_X_READ equ 3fH += 0040 MS_X_WRITE equ 40H += 0041 MS_X_UNLINK equ 41H += 0042 MS_X_LSEEK equ 42H + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 10 + + += 0043 MS_X_CHMOD equ 43H += 0044 MS_X_IOCTL equ 44H += 0045 MS_X_DUP equ 45H += 0046 MS_X_DUP2 equ 46H += 0047 MS_X_CURDIR equ 47H += 0048 MS_M_ALLOC equ 48H += 0049 MS_M_FREE equ 49H += 004A MS_M_SETBLOCK equ 4aH += 004B MS_X_EXEC equ 4bH += 004C MS_X_EXIT equ 4cH += 004D MS_X_WAIT equ 4dH += 004E MS_X_FIRST equ 4eH += 004F MS_X_NEXT equ 4fH += 0050 MS_P_SETPSP equ 50H += 0054 MS_F_GETVERIFY equ 54H += 0056 MS_X_RENAME equ 56H += 0057 MS_X_DATETIME equ 57H += 0058 MS_M_STRATEGY equ 58h += 0059 MS_F_ERROR equ 59H += 005A MS_X_MKTEMP equ 5aH += 005B MS_X_MKNEW equ 5bH += 005C MS_F_LOCK equ 5cH += 0060 MS_X_EXPAND equ 60H += 0062 MS_P_GETPSP equ 62H += 6601 MS_X_GETCP equ 6601h += 6602 MS_X_SETCP equ 6602h += 0067 MS_X_SETHC equ 67h += 0068 MS_X_COMMIT equ 68h += += 0021 DOS_INT equ 21h ; DOS Entry Point += ; += 0000 STDIN equ 0 ; Standard Console Input Handle += 0001 STDOUT equ 1 ; Standard Console Output Handle += 0002 STDERR equ 2 ; Standard Error Output += 0003 STDAUX equ 3 ; Auxilary Device Handle += 0004 STDPRN equ 4 ; Printer Device Handle + += include i:mserror.equ += ; File : $MSERROR.EQU$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 11 + + += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += += FFFF ED_FUNCTION equ -01 ; invalid function number += FFFE ED_FILE equ -02 ; file not found += FFFD ED_PATH equ -03 ; path not found += FFFC ED_HANDLE equ -04 ; too many open files += FFFB ED_ACCESS equ -05 ; file access denied += FFFA ED_H_MATCH equ -06 ; invalid handle number += FFF9 ED_DMD equ -07 ; memory descriptor destroyed += FFF8 ED_MEMORY equ -08 ; insufficient memory += FFF7 ED_BLOCK equ -09 ; invalid memory block addr += FFF6 ED_ENVIRON equ -10 ; invalid environment += FFF5 ED_FORMAT equ -11 ; invalid format += FFF4 ED_ACC_CODE equ -12 ; invalid access code += FFF3 ED_DATA equ -13 ; invalid data += FFF1 ED_DRIVE equ -15 ; invalid drive specified += FFF0 ED_DIR equ -16 ; can't remove current dir += FFEF ED_DEVICE equ -17 ; not same device += FFEE ED_ROOM equ -18 ; no more files += += FFED ED_PROTECT equ -19 ; disk write protected += FFEC ED_BADUNIT equ -20 ; invalid drive specified += FFEB ED_NOTREADY equ -21 ; drive doesn't respond += FFEA ED_BADCMD equ -22 ; invalid command to driver += FFE9 ED_BADDATA equ -23 ; data CRC error += FFE8 ED_BADRHLEN equ -24 ; (shouldn't happen) += FFE7 ED_BADSEEK equ -25 ; can't seek to track += FFE6 ED_BADMEDIA equ -26 ; unrecognizable medium += FFE5 ED_RNF equ -27 ; record/sector not found += FFE4 ED_NOPAPER equ -28 ; printer error += FFE3 ED_WRFAIL equ -29 ; write failed += FFE2 ED_RDFAIL equ -30 ; read failed += FFE1 ED_GENFAIL equ -31 ; anything failed += FFE0 ED_SHAREFAIL equ -32 ; sharing conflict + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 12 + + += FFDF ED_LOCKFAIL equ -33 ; locking conflict += FFDE ED_DISKCHG equ -34 ; invalid disk change += FFDD ED_NOFCBS equ -35 ; FCB table exhausted += FFDC ED_NOLOCKS equ -36 ; lock list items exhausted += FFCE ED_NET equ -50 ; Network Request Not Supported += += FFBF ED_NETACCESS equ -65 ; file access denied += += FFB7 ED_NETPWD equ -73 ; Server Password Error += FFB6 ED_NETVER equ -74 ; Incorrect Server version += FFB5 ED_NETREQ equ -75 ; No Local Network Resources += FFB4 ED_NETTIME equ -76 ; Network Time Out Error += FFB3 ED_NETCOMM equ -77 ; Network Communications Error += FFB2 ED_NETSRVR equ -78 ; No Server Network Resources += FFB1 ED_NETLOG equ -79 ; Server Not Logged In += += FFB0 ED_EXISTS equ -80 ; file already exists += FFAE ED_MAKE equ -82 ; Cannot Make (Files ??) += FFAD ED_FAIL equ -83 ; FAIL code returned from INT 24 += FFAC ED_STRUCT equ -84 ; Out of Structures += FFAB ED_ASSIGN equ -85 ; Already Assigned += FFAA ED_PASSWORD equ -86 ; Invalid Password += FFA9 ED_PARAM equ -87 ; Invalid Parameter += FFA8 ED_NETWRITE equ -88 ; Network write fault += FFA7 ED_NETFUNC equ -89 ; Function not supported on network += FFA6 ED_COMPONENT equ -90 ; system component not installed += FFA6 ED_LASTERROR equ -90 ; Last Error Number Used += += += 0001 CLASS_RESOURCE equ 1 ; Out of Resource += 0002 CLASS_TEMP equ 2 ; Temporary Situation += 0003 CLASS_AUTHOR equ 3 ; Authorization Error += 0004 CLASS_INTERNAL equ 4 ; Internal System Software Error += 0005 CLASS_HARDWARE equ 5 ; Hardware Failure += 0006 CLASS_SYSTEM equ 6 ; Serious System Failure += 0007 CLASS_APPLIC equ 7 ; Application Program Error += 0008 CLASS_LOST equ 8 ; File/Item Not Found += 0009 CLASS_FORMAT equ 9 ; File/Item Illegal Format += 000A CLASS_LOCKED equ 10 ; File/Item Locked += 000B CLASS_MEDIA equ 11 ; Media Failure += 000C CLASS_EXISTS equ 12 ; Item Already Exists += 000D CLASS_UNKNOWN equ 13 ; Unknown Classification += += 0001 ACT_RETRY equ 1 ; Retry a few times then prompt user += 0002 ACT_DELAY equ 2 ; Delay then as ACT_RETRY += 0003 ACT_USER equ 3 ; Prompt user to re-enter data += 0004 ACT_ABORT equ 4 ; Clean Up then ABORT the process += 0005 ACT_TERM equ 5 ; Terminate immeadiately NO CLEAN UP += 0006 ACT_IGNORE equ 6 ; Ignore the Error += 0007 ACT_URETRY equ 7 ; Retry the error after user intervention += += 0001 LOC_UNKNOWN equ 1 ; Unknown error location + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 13 + + += 0002 LOC_BLOCK equ 2 ; Block Device Failure += 0003 LOC_NET equ 3 ; Network Failure += 0004 LOC_CHAR equ 4 ; Related to Serial/Character devices += 0005 LOC_MEMORY equ 5 ; Failure related to Memory + += include i:psp.def += ; File : $PSP.DEF$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += ; += ; Program Segment Prefix += ; ---------------------- += ; This structure holds vital information for DOS programs += ; += ;****************************************************************************** += ;* += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 00 | int 20 | memory | *** | jmpf|longjmp off| += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 08 |longjmp seg| int22 Off | int22 Seg | int22 Off | += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 10 | int22 Seg | int24 Off | int24 Seg | Parent | + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 14 + + += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 18 | Default Handle Table | += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 20 | XFT (20 entries) | += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 28 | XFT contd. | Environ | User SP | += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 30 | User SS | xfnmax | xftoff | xftseg | += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 38 | res1 | res2 | ric | *** | ********* | += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 40 | version | ********* | ********* | ********* | += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 48 | ********* | ********* | ********* | ********* | += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 50 | int 21 | retf| *** | ********* | ********* | += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += ;* 58 | ********* | ********* | PSP fcb 1 | += ;* +-----+-----+-----+-----+-----+-----+-----+-----+ += += 0000 PSP_INT20 equ es:word ptr .0000h += 0002 PSP_MEMORY equ es:word ptr .0002h += ;PSP_??? equ es:byte ptr .0004h += 0005 PSP_LONGCALL equ es:byte ptr .0005h += 0006 PSP_LONGOFF equ es:word ptr .0006h += 0008 PSP_LONGSEG equ es:word ptr .0008h += 000A PSP_TERM_IP equ es:word ptr .000Ah += 000C PSP_TERM_CS equ es:word ptr .000Ch += 000E PSP_BREAK_IP equ es:word ptr .000Eh += 0010 PSP_BREAK_CS equ es:word ptr .0010h += 0012 PSP_ERROR_IP equ es:word ptr .0012h += 0014 PSP_ERROR_CS equ es:word ptr .0014h += 0016 PSP_PARENT equ es:word ptr .0016h += 0018 PSP_XFT equ es:byte ptr .0018h += ; += ; The Default Handle Table is HERE !! += ; += 002C PSP_ENVIRON equ es:word ptr .002ch += 002E PSP_USERSP equ es:word ptr .002eh += 0030 PSP_USERSS equ es:word ptr .0030h += 0032 PSP_XFNMAX equ es:word ptr .0032h += 0034 PSP_XFTPTR equ es:dword ptr .0034h += 0034 PSP_XFTOFF equ es:word ptr .0034h += 0036 PSP_XFTSEG equ es:word ptr .0036h += 0038 PSP_RES1 equ es:word ptr .0038h ; DOS Reserved 0FFFFh += 003A PSP_RES2 equ es:word ptr .003Ah ; DOS Reserved 0FFFFh += 003C PSP_RIC equ es:byte ptr .003Ch ; Return Interim Character flag += 0040 PSP_VERSION equ es:word ptr .0040h ; DOS version number += += += 0050 PSP_DOSCALL equ es:word ptr .0050h += 0052 PSP_DOSRETF equ es:byte ptr .0052h + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 15 + + += += 005C PSP_FCB1 equ es:byte ptr .005Ch += 006C PSP_FCB2 equ es:byte ptr .006Ch += 0080 PSP_COMLEN equ es:byte ptr .0080h += 0081 PSP_COMLINE equ es:byte ptr .0081h += += 0014 XFNMAX equ 20 += += 0100 PSPLEN equ 100h += 0060 PSPILEN equ 60h + += include i:char.def += ; File : $CHAR.DEF$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += ;************************************************; += ;* *; += ;* Character Definitions *; += ;* *; += ;************************************************; += += 0001 CTLA equ 'A' - '@' + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 16 + + += 0002 CTLB equ 'B' - '@' += 0003 CTLC equ 'C' - '@' += 0004 CTLD equ 'D' - '@' += 0005 CTLE equ 'E' - '@' += 0006 CTLF equ 'F' - '@' += 0007 CTLG equ 'G' - '@' += 0007 BELL equ 'G' - '@' += 0008 CTLH equ 'H' - '@' += 0009 CTLI equ 'I' - '@' += 0009 TAB equ 'I' - '@' += 000A CTLJ equ 'J' - '@' += 000A LF equ 'J' - '@' += 000B CTLK equ 'K' - '@' += 000D CTLM equ 'M' - '@' += 000D CR equ 'M' - '@' += 0010 CTLP equ 'P' - '@' += 0011 CTLQ equ 'Q' - '@' += 0012 CTLR equ 'R' - '@' += 0013 CTLS equ 'S' - '@' += 0014 CTLT equ 'T' - '@' += 0015 CTLU equ 'U' - '@' += 0016 CTLV equ 'V' - '@' += 0017 CTLW equ 'W' - '@' += 0018 CTLX equ 'X' - '@' += 0019 CTLY equ 'Y' - '@' += 001A CTLZ equ 'Z' - '@' += 001B ESC equ '[' - '@' += 001C CTLBS equ '\' - '@' += 001F CTLUB equ '_' - '@' += 001E CTLUP equ '^' - '@' += 007F DEL equ 07Fh += 007F RUBOUT equ DEL += += 005E CTL equ '^' + += include i:reqhdr.equ += ; File : $REQHDR.EQU$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 17 + + += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += += 0000 CMD_INIT equ 0 ; Initialize the Device Driver += 0001 CMD_MEDIA_CHECK equ 1 ; Request Media Check += 0002 CMD_BUILD_BPB equ 2 ; Build Drive BPB += 0003 CMD_INPUT_IOCTL equ 3 ; IOCTL input += 0004 CMD_INPUT equ 4 ; Input += 0005 CMD_INPUT_NOWAIT equ 5 ; Non destructive input no wait += 0006 CMD_INPUT_STATUS equ 6 ; Input status += 0007 CMD_INPUT_FLUSH equ 7 ; Input flush += 0008 CMD_OUTPUT equ 8 ; Output += 0009 CMD_OUTPUT_VERIFY equ 9 ; Output with verify += 000A CMD_OUTPUT_STATUS equ 10 ; Output status += 000B CMD_OUTPUT_FLUSH equ 11 ; Output flush += 000C CMD_OUTPUT_IOCTL equ 12 ; IOCTL output += 000D CMD_DEVICE_OPEN equ 13 ; Device OPEN += 000E CMD_DEVICE_CLOSE equ 14 ; Device CLOSE += 000F CMD_FIXED_MEDIA equ 15 ; Removeable Media Check += 0013 CMD_GENERIC_IOCTL equ 19 ; Generic IOCTL += 0017 CMD_GET_DEVICE equ 23 ; Get the Logical Device += 0018 CMD_SET_DEVICE equ 24 ; Set the Logical Device += 0019 CMD_QUERY_IOCTL equ 25 ; query ioctl support += += ; Generic Request Header Format += += 0000 RH_LEN equ es:byte ptr 0[bx] += 0001 RH_UNIT equ es:byte ptr 1[bx] += 0002 RH_CMD equ es:byte ptr 2[bx] += 0003 RH_STATUS equ es:word ptr 3[bx] += 0100 RHS_DONE equ 0100h += 0200 RHS_BUSY equ 0200h += 0400 RHS_IC equ 0400h ; Interim Character += 0800 RHS_RM equ 0800h += 8000 RHS_ERROR equ 8000h += += ;****** + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 18 + + += ;* No longer safe to use - some device drivers trample on them.... += ;* += ;* RH_STRATEGY equ es:dword ptr 5[bx] ; Device Strategy Routine += ;* RH_STRATOFF equ es:word ptr 5[bx] ; Strategy Offset += ;* RH_STRATSEG equ es:word ptr 7[bx] ; Strategy Segment += ;* RH_INTERRUPT equ es:dword ptr 9[bx] ; Device Interrupt Routine += ;* RH_INTOFF equ es:word ptr 9[bx] ; Intterupt Offset += ;* RH_INTSEG equ es:word ptr 11[bx] ; Interrupt Segment += ;***** += += ; Request header for initialization += += 000D RH0_NUNITS equ es:byte ptr 13[bx] += 000E RH0_RESIDENT equ es:word ptr 14[bx] += 0012 RH0_BPBOFF equ es:word ptr 18[bx] += 0014 RH0_BPBSEG equ es:word ptr 20[bx] += 0016 RH0_DRIVE equ es:byte ptr 22[bx] += 0016 RH0_LEN equ 22 += += ; Request header for media check += += 000D RH1_MEDIA equ es:byte ptr 13[bx] ; BDOS: current media byte += 000E RH1_RETURN equ es:byte ptr 14[bx] ; driver: return code (00, 01, FF) += 000F RH1_VOLID equ es:dword ptr 15[bx] ; driver: volume label address += 000F RH1_LEN equ 15 += += ; Request header for "build BPB" += += 000D RH2_MEDIA equ es:byte ptr 13[bx] ; BDOS or driver? += 000E RH2_BUFFER equ es:dword ptr 14[bx] ; BDOS: scratch buffer for driver use += 0012 RH2_BPB equ es:dword ptr 18[bx] ; same as the following: += 0012 RH2_BPBOFF equ es:word ptr 18[bx] ; driver: address of new BPB += 0014 RH2_BPBSEG equ es:word ptr 20[bx] += 0018 RH2_LEN equ 24 += += ; Request header for input/output += += 000D RH4_MEDIA equ es:byte ptr 13[bx] ; BDOS: current media byte += 000D RH4_RIC equ es:byte ptr 13[bx] ; BDOS: Return Interim Char flg += 000E RH4_BUFFER equ es:dword ptr 14[bx] ; BDOS: disk transfer address += 000E RH4_BUFOFF equ es:word ptr 14[bx] ; BDOS: Buffer Offset += 0010 RH4_BUFSEG equ es:word ptr 16[bx] ; BDOS: Buffer Segment += 0012 RH4_COUNT equ es:word ptr 18[bx] ; BDOS: sector count += 0014 RH4_SECTOR equ es:word ptr 20[bx] ; BDOS: starting sector += 0016 RH4_VOLID equ es:dword ptr 22[bx] ; driver: volume if illegal disk change += 001A RH4_BIGSECTOR equ es:dword ptr 26[bx] += 001A RH4_BIGSECTORLO equ es:word ptr 26[bx] += 001C RH4_BIGSECTORHI equ es:word ptr 28[bx] += += 001E RH4_LEN equ 30 += += ; Request Header for Non-Destructive Input + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 19 + + += += 000D RH5_CHAR equ es:byte ptr 13[bx] ; Character Read from Device += 000D RH5_RIC equ es:byte ptr 13[bx] ; BDOS: Return Interim Char flg += 000E RH5_LEN equ 14 += += ; Request Header for Device Open += += 000D RH13_LEN equ 13 += += ; Request Header for Device Close += += 000D RH14_LEN equ 13 += += ; Request header for generic IOCTL += += 000D RH19_CATEGORY equ es:word ptr 13[bx] ; BDOS: major/minor function number += 000D RH19_MAJOR equ es:byte ptr 13[bx] ; BDOS: Major Function Number += 000E RH19_MINOR equ es:byte ptr 14[bx] ; BDOS: Minor Function Number += 000F RH19_SI equ es:word ptr 15[bx] ; BDOS: User SI += 0011 RH19_DI equ es:word ptr 17[bx] ; BDOS: User DI += 0013 RH19_GENPB equ es:dword ptr 19[bx] ; BDOS: extra parameters += 0017 RH19_LEN equ 23 += += 0040 RQ19_SET equ 40h ; set device parameters += 0060 RQ19_GET equ 60h ; get device parameters += 0041 RQ19_WRITE equ 41h ; write tracks += 0061 RQ19_READ equ 61h ; read tracks += 0042 RQ19_FORMAT equ 42h ; format tracks += 0062 RQ19_VERIFY equ 62h ; verify tracks += += 004C RQ19_PRP_START equ 4Ch ; start of codepage prepare += 004D RQ19_PRP_END equ 4Dh ; end of codepage prepare += 004A RQ19_SELECT equ 4Ah ; select code page += 006A RQ19_QRY_SEL equ 6Ah ; query selected code page += 006B RQ19_QRY_PRP equ 6Bh ; query prepared code page(s) += 005F RQ19_DSP_SET equ 5Fh ; set display information += 007F RQ19_DSP_GET equ 7Fh ; get display information += += ; Request header for get/set drive += += 000E RH24_CMD equ es:byte ptr 14[bx] ; BDOS: Command Code += 000F RH24_STATUS equ es:word ptr 15[bx] ; BDOS: Status += 0011 RH24_RESVD equ es:dword ptr 17[bx] ; BDOS: Reserved += 0015 RH24_LEN equ 21 += += 001E RH_SIZE equ 30 ; maximum size of request header + + + ; + 0000 ERR_TBL_CODE equ byte ptr 0 ; Error Code in Table + 0001 ERR_TBL_CLASS equ byte ptr 1 ; Error Class entry in Table + 0002 ERR_TBL_ACTION equ byte ptr 2 ; Error Action entry in Table + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 20 + + + 0003 ERR_TBL_LOCUS equ byte ptr 3 ; Locus entry in table + 0004 ERR_TBL_LEN equ 4 ; 4 bytes per entry + ; + PCM_CODE CSEG BYTE + extrn get_dseg:near + extrn do_int24:near + extrn reload_registers:near + extrn return_AX_CLC:near + ; + ; ***************************** + ; *** DOS Function 59 *** + ; *** Get Extended Error *** + ; ***************************** + ; + Public func59 + + func59: + 0000 C43E0000 E les di,error_dev ; Return device driver address + 0004 8A3E0000 E mov bh,error_class ; return the Error Class + 0008 8A1E0000 E mov bl,error_action ; the Action Code + 000C 8A2E0000 E mov ch,error_locus ; the Locus Code + 0010 A10000 E mov ax,error_code ; the Error Code + + 0013 C5360000 E lds si,int21regs_ptr ; point to user stack + 0017 8C4410 mov reg_ES[si],es + 001A 897C0A mov reg_DI[si],di + 001D 895C02 mov reg_BX[si],bx + 0020 894C04 mov reg_CX[si],cx + 0023 161F push ss ! pop ds + 0025 E90000 E jmp return_AX_CLC + + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 21 + + + eject + ; On Entry:- AX == Internal Error Number + ; + ; On Exit:- None + ; CY set if error should be returned + ; CY clear if it should be ignored + ; + Public error_exit + error_exit: + 0028 803E000000 E cmp internal_flag,0 ; If this is an internal + 002D 7506 0035 jnz error_ret ; do not generate a critical + 002F E86800 009A call disk_error ; error + 0032 7504 0038 jnz error_r10 ; No Error Occured or Ignored + 0034 C3 ret ; in critcal error handler + + ; + ; Return the error code to the user and DO NOT generate any + ; critical errors. + ; + ; On Entry:- AX == Internal Error Number + ; + ; On Exit:- None + ; + Public error_ret + error_ret: + 0035 E8D600 010E call set_error ; the internal error code + error_r10: ; otherwise negate + 0038 C43E0000 E les di,int21regs_ptr + 003C 26814D160100 or es:reg_FLAGS[di],CARRY_FLAG ; set the "users" carry Flag + 0042 F9 stc ; also set real one + if offset reg_AX EQ 0 + 0043 AB stosw ; save return code + else + mov es:reg_AX[di],ax + endif + 0044 C3 ret + + ; + ; On Entry:- AX == Internal Error Number + ; + ; On Exit:- None + ; + Public fcberror_exit + fcberror_exit: + 0045 E85200 009A call disk_error ; Process the error code generating + 0048 7402 004C jz fe_e10 ; a critical error is required + 004A B0FF mov al,0FFh ; on FCB error return AL = FF + fe_e10: + 004C C3 ret + + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 22 + + + eject + ; WARNING - may be called from FDOS with DS = SYSDAT + ; + ; CHAR_ERROR is called when any character device function generates + ; an error. First CHAR_ERROR sets the correct parameters for Get + ; Extended Error. Then it generates a Critical Error by calling + ; DO_INT24. + ; + ; Entry:- ES:SI -> device driver header + ; SS:BX -> RH_ + ; AX = RH_STATUS + ; + ; Exit AL Error Action + ; + Public char_error + char_error: + 004D 36F606000040 E test ss:valid_flg,NO_CRIT_ERRORS + 0053 7403 0058 jz char_e10 + 0055 B003 mov al,ERR_FAIL ; no critical errors allowed + 0057 C3 ret ; so just fail things + char_e10: + 0058 1E push ds + 0059 06 push es + 005A 53 push bx + 005B 51 push cx + 005C 52 push dx + 005D 56 push si + 005E 57 push di + 005F 161F push ss ! pop ds ; DS -> our data now + 0061 89360000 E mov word ptr error_dev+0,si ; save the device driver address + 0065 8C060200 E mov word ptr error_dev+2,es ; and then initialise the FUNC59 + 0069 06 push es ; data areas + 006A 257F00 and ax,007Fh ; Mask the Unused Bits + 006D 80CCB8 or ah,80h+OK_RIF ; Retry/Ignore/Abort/Fail allowable + 0070 36807F0208 cmp ss:RH_CMD,CMD_OUTPUT ; is this a read or write failure ? + 0075 7502 0079 jne char_e20 + 0077 FEC4 inc ah ; 01 is a Write Failure + char_e20: + 0079 88260000 E mov rwmode,ah ; + 007D 50 push ax ; save for int 24 + 007E 98 cbw ; zero AH again + 007F F7D8 neg ax ; convert to an internal error + 0081 05EDFF add ax,ED_PROTECT ; code for set_error + 0084 B104 mov cl,LOC_CHAR + 0086 E88500 010E call set_error + 0089 05EDFF add ax,ED_PROTECT ; convert to hardware error + 008C 97 xchg ax,di ; DI == hardware error + 008D 58 pop ax + 008E 07 pop es + 008F E80000 E call do_int24 ; execute INT 24 + 0092 5F pop di + 0093 5E pop si + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 23 + + + 0094 5A pop dx + 0095 59 pop cx + 0096 5B pop bx + 0097 07 pop es + 0098 1F pop ds + 0099 C3 ret + + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 24 + + + eject + ; + ; DISK_ERROR gains control after any DOS disk based function + ; has been executed which generates an error. First ERROR set the + ; correct parameters for Get Extended Error. Then it determines if + ; the current error should generate a Critical Error and calls + ; DO_INT24 if TRUE. + ; + ; + ; On Entry: + ; AX Internal Error Code + ; + ; On Exit: + ; AX 0 if no error to return (Ignore) + ; AX DOS Error Code + ; ZF reflects AX + ; + disk_error: + 009A B104 mov cl,LOC_CHAR ; assume character device + ; determine if the error is + 009C F606000080 E test rwmode,80h ; caused by a character or + 00A1 7502 00A5 jnz disk_e10 ; block device and set the + 00A3 B102 mov cl,LOC_BLOCK ; the critical error locus + disk_e10: + 00A5 E86600 010E call set_error ; record error information + 00A8 7461 010B jz disk_e50 ; just return a logical error. + + 00AA 05EDFF add ax,ED_PROTECT ; Convert to HardWare Error + 00AD 8BF8 mov di,ax ; DI == HardWare Error + ; Now get the information + 00AF 8A260000 E mov ah,rwmode ; about the error location + + 00B3 80E4C7 and ah,not OK_RIF ; mask the all responses + ; mov al,valid_flg ; valid flag contains no crit + ; and al,not NO_CRITICAL_ERRORS ; errors bit, but if that was + ; or ah,al ; set we wouldn't be here + 00B6 0A260000 E or ah,valid_flg ; or in valid responses + + 00BA 83FBE1 cmp bx,ED_GENFAIL ; if it's general failure + 00BD 7503 00C2 jne disk_e20 ; we cannot Ignore the error + 00BF 80E4DF and ah,not OK_IGNORE ; but must Abort/Fail/Retry + disk_e20: ; as appropriate + + 00C2 A00000 E mov al,err_drv ; get the failing drive + 00C5 A20000 E mov error_drive,al ; and save locally + + 00C8 C4360000 E les si,error_dev ; get device driver header + + ; are we are a character device + 00CC F6C480 test ah,80h ; as these have handled at a + 00CF 7529 00FA jnz disk_e40 ; lower level and just need + ; to be FAILed back to caller + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 25 + + + + 00D1 E80000 E call do_int24 ; Execute INT 24 + + 00D4 8AD8 mov bl,al ; Copy reponse into BL + + 00D6 33C0 xor ax,ax ; Assume Ignore Error + 00D8 80FB00742E 010B cmp bl,ERR_IGNORE ! jz disk_e50 ; Ignore the Error + + 00DD 80FB037418 00FA cmp bl,ERR_FAIL ! jz disk_e40 ; If not FAIL then RETRY + 00E2 E80000 E call reload_registers ; get back entry registers + 00E5 A30000 R mov FD_FUNC,ax ; save AX for a moment + 00E8 8AC4 mov al,ah ; set up function number + 00EA 32E4 xor ah,ah ; in AX + 00EC 87060000 R xchg ax,FD_FUNC ; save for use by FDOS + 00F0 32E4 xor ah,ah ; zero AH 'cause it's handy + 00F2 8B260000 E mov sp,retry_sp ; Must be RETRY so reset the + 00F6 FF260000 E jmp retry_off ; STACK and IP + + disk_e40: + ; + ; When a Critical Error is FAILED then we do the following + ; if (extended error_code <= ED_SHAREFAIL) then + ; ret = ED_ACCESS; + ; else + ; ret = ED_FAIL; + ; extended error_code = ED_FAIL; + ; return(ret); + ; + ; nb. above proto-code is at the request of ant + ; + 00FA B85300 mov ax,-(ED_FAIL) ; always return ED_FAIL in the + 00FD 87060000 E xchg ax,error_code ; extended error_code + 0101 3D2000 cmp ax,-(ED_SHAREFAIL) ; did we FAIL on sharing conflict ? + 0104 B80500 mov ax,-(ED_ACCESS) ; assume we did and prepare to return + 0107 7302 010B jae disk_e50 ; ED_ACCESS + 0109 B053 mov al,-(ED_FAIL) ; woops, return ED_FAIL after all + disk_e50: + 010B 0BC0 or ax,ax ; NZ if error return required + 010D C3 ret + + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 26 + + + eject + ; + ; On Entry:- AX Internal Error Code + ; CL Critical Error Locus + ; + ; On Exit:- AX DOS Error Code + ; BX Internal Error Code + ; ZF set on logical error + set_error: + 010E 8BD8 mov bx,ax ; by default we return the raw error + 0110 BF7400 R mov di,offset critical_error; Scan for critical Errors First + 0113 E88600 019C call scan_error_table ; look for a matching error + 0116 723B 0153 jc set_logical_error + 0118 880E0000 E mov locus,cl ; Save the critical error LOCUS + 011C 3DE0FF cmp ax,ED_SHAREFAIL ; watch out for SHAREFAIL - the action + 011F 7514 0135 jne set_e10 ; depends on the caller + ; + ; ED_SHAREFAIL will return ED_ACCESS if the result of an attempt to open + ; a file in shared mode, otherwise (FCB's and compatibility) it will + ; generate a critical error. + ; + 0121 BBE1FF mov bx,ED_GENFAIL ; assume we want a critical error + 0124 833E00003D R cmp FD_FUNC,MS_X_OPEN ; is it a shared open ? + 0129 7540 016B jnz set_error_data + 012B F70606007000 R test FD_MODE,0$111$0$000b ; mode + 0131 7438 016B jz set_error_data + 0133 EB1B 0150 jmps set_e30 ; return a logical "access denied" + + set_e10: + 0135 3DDFFF cmp ax,ED_LOCKFAIL ; have we a lockfail error ? + 0138 750C 0146 jne set_e20 + ; + ; ED_LOCKFAIL returns ED_ACCESS if a lock attempt fails, but a critical error + ; on an attempt to read/write a locked region. + ; + 013A 833E000052 R cmp FD_FUNC,FD_LOCK ; was it a result of specific lock + 013F 7412 0153 je set_logical_error ; call ? yes, it's a logical error + 0141 BBE1FF mov bx,ED_GENFAIL ; no, generate a critical error + 0144 EB25 016B jmps set_error_data + + set_e20: + 0146 F606000040 E test valid_flg,NO_CRIT_ERRORS + 014B 741E 016B jz set_error_data ; do we allow critical errors ? + 014D B8FBFF mov ax,ED_ACCESS ; extended error code is Access Denied + set_e30: + 0150 BBFBFF mov bx,ED_ACCESS ; return access denied to caller + ; jmps set_logical_error + + set_logical_error: + 0153 33FF xor di,di + 0155 893E0000 E mov word ptr error_dev+0,di ; must be a logical error so force + 0159 893E0200 E mov word ptr error_dev+2,di ; the ERROR_DEV to 0000:0000 + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 27 + + + 015D BF0000 R mov di,offset logical_error ; scan the Logical error table + 0160 E83900 019C call scan_error_table + 0163 3DBFFF cmp ax,ED_NETACCESS ; if it's a networked access denied + 0166 7503 016B jne set_error_data ; turn it into ordinary one + 0168 BBFBFF mov bx,ED_ACCESS ; return a logical "access denied" + ; jmps set_error_data + + set_error_data: + ; On Entry: + ; AX = Internal Error Code for extended error + ; BX = Internal Error Code for returned error + ; CS:DI -> error table entry + ; On Exit: + ; AX = DOS Error Code + ; BX = Internal Error Code + ; ZF set on logical error + ; + 016B F7D8 neg ax + 016D A30000 E mov error_code,ax ; Save the Error Code + 0170 2E8A4501 mov al,cs:ERR_TBL_CLASS[di] + 0174 A20000 E mov error_class,al ; Save the Class + 0177 2E8A4502 mov al,cs:ERR_TBL_ACTION[di] + 017B A20000 E mov error_action,al ; Save the Action + 017E 2E8A4503 mov al,cs:ERR_TBL_LOCUS[di] ; Get the Locus + 0182 A20000 E mov error_locus,al ; Save the Locus and then check + 0185 84C0 test al,al ; if the function overrides + 0187 7506 018F jnz set_d10 ; this value + 0189 A00000 E mov al,locus ; Get the Global Locus value + 018C A20000 E mov error_locus,al ; set by the calling function + set_d10: ; and save for FUNC 59 + 018F 8BC3 mov ax,bx ; Return to the caller with + 0191 F7D8 neg ax ; the DOS error code. + 0193 8B3E0000 E mov di,word ptr error_dev ; set ZF if logical error + 0197 0B3E0200 E or di,word ptr error_dev+2 ; error_dev = 0:0 + 019B C3 ret + + scan_error_table: + 019C 2E803D00 cmp cs:ERR_TBL_CODE[di],0 + 01A0 740A 01AC je scan_et10 ; Check for the end of the list + 01A2 2E3A05 cmp al,cs:ERR_TBL_CODE[di] + 01A5 7406 01AD je scan_et20 + 01A7 83C704 add di,ERR_TBL_LEN + 01AA EBF0 019C jmps scan_error_table + scan_et10: + 01AC F9 stc + scan_et20: + 01AD C3 ret + + + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 28 + + + eject + PCM_RODATA CSEG WORD + 0000 logical_error rb 0 + ; + ; Internal Code Error Class Error Action Error Locus + ; ============= =========== ============ =========== + 0000 FF070400 db ED_FUNCTION, CLASS_APPLIC, ACT_ABORT, 00 + 0004 FE080302 db ED_FILE, CLASS_LOST, ACT_USER, LOC_BLOCK + 0008 FD080302 db ED_PATH, CLASS_LOST, ACT_USER, LOC_BLOCK + 000C FC010401 db ED_HANDLE, CLASS_RESOURCE, ACT_ABORT, LOC_UNKNOWN + 0010 FB030300 db ED_ACCESS, CLASS_AUTHOR, ACT_USER, 00 + 0014 BF030300 db ED_NETACCESS, CLASS_AUTHOR, ACT_USER, 00 + 0018 FA070401 db ED_H_MATCH, CLASS_APPLIC, ACT_ABORT, LOC_UNKNOWN + 001C F9070505 db ED_DMD, CLASS_APPLIC, ACT_TERM, LOC_MEMORY + 0020 F8010405 db ED_MEMORY, CLASS_RESOURCE, ACT_ABORT, LOC_MEMORY + 0024 F7070405 db ED_BLOCK, CLASS_APPLIC, ACT_ABORT, LOC_MEMORY + 0028 F6070405 db ED_ENVIRON, CLASS_APPLIC, ACT_ABORT, LOC_MEMORY + 002C F5090301 db ED_FORMAT, CLASS_FORMAT, ACT_USER, LOC_UNKNOWN + 0030 F4070401 db ED_ACC_CODE, CLASS_APPLIC, ACT_ABORT, LOC_UNKNOWN + 0034 F3090401 db ED_DATA, CLASS_FORMAT, ACT_ABORT, LOC_UNKNOWN + 0038 F1080302 db ED_DRIVE, CLASS_LOST, ACT_USER, LOC_BLOCK + 003C F0030302 db ED_DIR, CLASS_AUTHOR, ACT_USER, LOC_BLOCK + 0040 EF0D0302 db ED_DEVICE, CLASS_UNKNOWN, ACT_USER, LOC_BLOCK + 0044 EE080302 db ED_ROOM, CLASS_LOST, ACT_USER, LOC_BLOCK + 0048 B00C0302 db ED_EXISTS, CLASS_EXISTS, ACT_USER, LOC_BLOCK + 004C AC010400 db ED_STRUCT, CLASS_RESOURCE, ACT_ABORT, 00 + 0050 AA030301 db ED_PASSWORD, CLASS_AUTHOR, ACT_USER, LOC_UNKNOWN + 0054 AE010402 db ED_MAKE, CLASS_RESOURCE, ACT_ABORT, LOC_BLOCK + ;; db ED_NET, CLASS_FORMAT, ACT_USER, LOC_NET + 0058 AB0C0303 db ED_ASSIGN, CLASS_EXISTS, ACT_USER, LOC_NET + 005C A9090301 db ED_PARAM, CLASS_FORMAT, ACT_USER, LOC_UNKNOWN + 0060 AD0D0401 db ED_FAIL, CLASS_UNKNOWN, ACT_ABORT, LOC_UNKNOWN + 0064 E00A0202 db ED_SHAREFAIL, CLASS_LOCKED, ACT_DELAY, LOC_BLOCK + 0068 DF0A0202 db ED_LOCKFAIL, CLASS_LOCKED, ACT_DELAY, LOC_BLOCK + 006C DC010405 db ED_NOLOCKS, CLASS_RESOURCE, ACT_ABORT, LOC_MEMORY + 0070 00060501 db 00, CLASS_SYSTEM, ACT_TERM, LOC_UNKNOWN + + 0074 critical_error rb 0 + ; + ; Internal Code Error Class Error Action Error Locus + ; ============= =========== ============ =========== + 0074 ED0B0702 db ED_PROTECT, CLASS_MEDIA, ACT_URETRY, LOC_BLOCK + 0078 EC040501 db ED_BADUNIT, CLASS_INTERNAL, ACT_TERM, LOC_UNKNOWN + 007C EB050700 db ED_NOTREADY, CLASS_HARDWARE, ACT_URETRY, 00 + 0080 EA040501 db ED_BADCMD, CLASS_INTERNAL, ACT_TERM, LOC_UNKNOWN + 0084 E90B0402 db ED_BADDATA, CLASS_MEDIA, ACT_ABORT, LOC_BLOCK + 0088 E7050102 db ED_BADSEEK, CLASS_HARDWARE, ACT_RETRY, LOC_BLOCK + 008C E60B0702 db ED_BADMEDIA, CLASS_MEDIA, ACT_URETRY, LOC_BLOCK + 0090 E50B0402 db ED_RNF, CLASS_MEDIA, ACT_ABORT, LOC_BLOCK + 0094 E4020704 db ED_NOPAPER, CLASS_TEMP, ACT_URETRY, LOC_CHAR + 0098 E3050400 db ED_WRFAIL, CLASS_HARDWARE, ACT_ABORT, 00 + 009C E2050400 db ED_RDFAIL, CLASS_HARDWARE, ACT_ABORT, 00 + PC-DOS RASM-86 1.4a Source: ERROR.A86 Page 29 + + + 00A0 E10D0400 db ED_GENFAIL, CLASS_UNKNOWN, ACT_ABORT, 00 + 00A4 E00A0202 db ED_SHAREFAIL, CLASS_LOCKED, ACT_DELAY, LOC_BLOCK + 00A8 DF0A0202 db ED_LOCKFAIL, CLASS_LOCKED, ACT_DELAY, LOC_BLOCK + 00AC DD070401 db ED_NOFCBS, CLASS_APPLIC, ACT_ABORT, LOC_UNKNOWN + + 00B0 default_error rb 0 + 00B0 00060501 db 00, CLASS_SYSTEM, ACT_TERM, LOC_UNKNOWN + + PCMODE_DATA DSEG WORD + extrn indos_flag:byte + extrn internal_flag:byte + extrn int21regs_ptr:dword + extrn current_psp:word + extrn retry_off:word, retry_sp:word + extrn valid_flg:byte + extrn error_locus:byte ; Error Locus + extrn error_code:word ; DOS format error Code + extrn error_action:byte ; Error Action Code + extrn error_class:byte ; Error Class + extrn error_dev:dword ; Failing Device Header + extrn error_drive:byte ; Failing Disk Drive + extrn err_drv:byte + extrn locus:byte + extrn rwmode:byte + end + + +End of assembly. Number of errors: 0. Use factor: 25% + extrn error_class:byte ; Error Class + \ No newline at end of file diff --git a/IBMDOS/BIN/ERROR.OBJ b/IBMDOS/BIN/ERROR.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..dc77e3a7269cfbd14c1f0bf95d528ec2f4950e69 GIT binary patch literal 1664 zcma)6TWl0%6h8lDW_EY>(iSM-11VjE+1i7jcyGD~bFOaX_81X-aD}w4k9O%r%N6nvi9}Q=astH!>NYgpFx70n*rny` z(mE~j1wEO`4H&w6-y~Bu)1LT-gZ?h5oRtYqZrPa2>(hzDvA3z9)3-~myQS`{b(4Wu9y zBmy~z#y{Y=uk!T|vp{Jq-L08!eUCjrqIKY!hP@Stoarm1w{8a@v5+E?r^rD+9*zH@E#9~TB$`{jp){?DmI3$7IeP+Sc2HbQ$O=PoQte!NOM!u-& zSUHP(FigCILUYh9W-=rpj5lG*a(ivF{%Dv5Ty`d}Wl1CyTD?RKyGrLZ%Oa7iVdEQR zWS3~&%sB>$hZ-$y=ZXaqb+mj=N1ywuuweyNu5LO+P4}6mQLx=!^pE8V;`OOl{kd`k zD1g5UU{u5!j5dHz0lx15IIcI0ycHXHo{r>s^V%yoZPY+XuI+~suhxF5-`jAcrKfU4)^z%t*NzA`nS#9jFqD6o>?j|mkrKVQFEVcx5}zaIx6i(Ze(kekcsIa!1bZJ|mLdK+NA|a1 z?8F{3PLrQ=l75fFhx;;Qcwa{GU$IsHHH!cxyx z$EK$|sJ#mZb{U>aIe&#}O6er(V+C4AJ@G5xQ<{s{x2}*InnqCv;=hlZ)Uo*KF zoLLMu2P2po*+pRrptc=4r-BkgetsJNM%$=C%HyrzOE~0}cFJ#YnExa;w;7`gqkwO4&{|yKs|y(!rL@F7#_oCOL928vFiNv7#3BrXtk}}30|yihvdme&+)k% z3)S)QN5Ln!;RtRxg&S_hqO0*-heg&q{JYAVkiwxV9PULJ{TJgd;bf69n8LWDaI&CC z(rv<}d4)^2F#f@>)!)ef73Jh6>TfVc|4cA?9q~k*(XR-HFBv1J2&X6GjD3OnuM?b{ zk5M{<@e6u^ED@!$8&V!zQx*CL$4{Z8z*Ri2sGMGw2>l)TONeKw!Y@i3e#5ws;IL%# XE4Hw=5`okN2)Fk~DS-FT|K0z8m2BH5 literal 0 HcmV?d00001 diff --git a/IBMDOS/BIN/ERROR.SYM b/IBMDOS/BIN/ERROR.SYM new file mode 100644 index 0000000..fd2bf0b --- /dev/null +++ b/IBMDOS/BIN/ERROR.SYM @@ -0,0 +1,152 @@ + 0000 VARIABLES +0074 CRITICAL_ERROR 0000 CURRENT_PSP +00B0 DEFAULT_ERROR 0000 DMD_ID 0006 DMD_IDLE_FLAGS +0003 DMD_LEN 0008 DMD_NAME 0001 DMD_PSP 0000 ERROR_ACTION +0000 ERROR_CLASS 0000 ERROR_CODE 0000 ERROR_DEV +0000 ERROR_DRIVE 0000 ERROR_LOCUS 0000 ERR_DRV +0000 FDOS_DATA 0008 FD_ADJUST 0008 FD_ATTRIB 0002 FD_BPBOFF 0004 FD_BPBSEG +0004 FD_BUF 0004 FD_BUFOFF 0006 FD_BUFSEG 0008 FD_COUNT 0006 FD_DATE +000A FD_DDIO_DMAOFF 000C FD_DDIO_DMASEG +0002 FD_DDIO_DRV_OP 0004 FD_DDIO_NSECTORS +0008 FD_DDIO_STARTHIGH 0006 FD_DDIO_STARTLOW 0006 FD_DDSCOFF +0008 FD_DDSCSEG 0004 FD_DPB 0004 FD_DPBOFF 0006 FD_DPBSEG 0002 FD_DRIVE +0002 FD_FCBADR 0006 FD_FCBCNT 0008 FD_FCBFUNC 0002 FD_FCBOFF 0004 FD_FCBSEG +0006 FD_FLAG 0000 FD_FUNC 0002 FD_HANDLE 0004 FD_IOCTLFUNC +0006 FD_IOCTLSTAT 0008 FD_LENGTH 000C FD_LFLAG 0008 FD_METHOD +0006 FD_MODE 0002 FD_NAME 0002 FD_NAMEOFF 0004 FD_NAMESEG 0004 FD_NEWHND +000A FD_NNAME 000A FD_NNAMEOFF 000C FD_NNAMESEG +0002 FD_NUMOPEN 0004 FD_OFFSET 0002 FD_ONAME 0002 FD_ONAMEOFF +0004 FD_ONAMESEG 0004 FD_PATH 0004 FD_PATHOFF 0006 FD_PATHSEG +0002 FD_PSPSEG 0004 FD_SFLAG 0008 FD_TIME 0000 INDOS_FLAG +0000 INT21REGS_PTR 0000 INTERNAL_FLAG 0000 LOCUS +0000 LOGICAL_ERROR 0010 PSP_BREAK_CS +000E PSP_BREAK_IP 0080 PSP_COMLEN 0081 PSP_COMLINE +0050 PSP_DOSCALL 0052 PSP_DOSRETF +002C PSP_ENVIRON 0014 PSP_ERROR_CS +0012 PSP_ERROR_IP 005C PSP_FCB1 006C PSP_FCB2 0000 PSP_INT20 +0005 PSP_LONGCALL 0006 PSP_LONGOFF +0008 PSP_LONGSEG 0002 PSP_MEMORY 0016 PSP_PARENT 0038 PSP_RES1 +003A PSP_RES2 003C PSP_RIC 000C PSP_TERM_CS +000A PSP_TERM_IP 002E PSP_USERSP 0030 PSP_USERSS +0040 PSP_VERSION 0032 PSP_XFNMAX 0018 PSP_XFT 0034 PSP_XFTOFF +0034 PSP_XFTPTR 0036 PSP_XFTSEG 0001 REG_AH 0000 REG_AL 0000 REG_AX +0003 REG_BH 0002 REG_BL 000C REG_BP 0002 REG_BX 0005 REG_CH +0004 REG_CL 0014 REG_CS 0004 REG_CX 0007 REG_DH 000A REG_DI +0006 REG_DL 000E REG_DS 0006 REG_DX 0010 REG_ES 0016 REG_FLAGS +0012 REG_IP 0008 REG_SI 0000 RETRY_OFF 0000 RETRY_SP 0012 RH0_BPBOFF +0014 RH0_BPBSEG 0016 RH0_DRIVE 000D RH0_NUNITS 000E RH0_RESIDENT +000D RH19_CATEGORY 0011 RH19_DI 0013 RH19_GENPB 000D RH19_MAJOR +000E RH19_MINOR 000F RH19_SI 000D RH1_MEDIA 000E RH1_RETURN 000F RH1_VOLID +000E RH24_CMD 0011 RH24_RESVD 000F RH24_STATUS 0012 RH2_BPB +0012 RH2_BPBOFF 0014 RH2_BPBSEG 000E RH2_BUFFER 000D RH2_MEDIA +001A RH4_BIGSECTOR 001C RH4_BIGSECTORHI +001A RH4_BIGSECTORLO 000E RH4_BUFFER 000E RH4_BUFOFF 0010 RH4_BUFSEG +0012 RH4_COUNT 000D RH4_MEDIA 000D RH4_RIC 0014 RH4_SECTOR 0016 RH4_VOLID +000D RH5_CHAR 000D RH5_RIC 0002 RH_CMD 0000 RH_LEN 0003 RH_STATUS +0001 RH_UNIT 0000 RWMODE 0000 VALID_FLG + +0000 NUMBERS +0004 ACT_ABORT 0002 ACT_DELAY 0006 ACT_IGNORE 0001 ACT_RETRY 0005 ACT_TERM +0007 ACT_URETRY 0003 ACT_USER 0007 BELL 0001 CARRY_FLAG +0007 CLASS_APPLIC 0003 CLASS_AUTHOR +000C CLASS_EXISTS 0009 CLASS_FORMAT +0005 CLASS_HARDWARE 0004 CLASS_INTERNAL +000A CLASS_LOCKED 0008 CLASS_LOST 000B CLASS_MEDIA +0001 CLASS_RESOURCE 0006 CLASS_SYSTEM 0002 CLASS_TEMP +000D CLASS_UNKNOWN 0002 CMD_BUILD_BPB +000E CMD_DEVICE_CLOSE 000D CMD_DEVICE_OPEN +000F CMD_FIXED_MEDIA 0013 CMD_GENERIC_IOCTL +0017 CMD_GET_DEVICE 0000 CMD_INIT 0004 CMD_INPUT +0007 CMD_INPUT_FLUSH 0003 CMD_INPUT_IOCTL +0005 CMD_INPUT_NOWAIT 0006 CMD_INPUT_STATUS +0001 CMD_MEDIA_CHECK 0008 CMD_OUTPUT 000B CMD_OUTPUT_FLUSH +000C CMD_OUTPUT_IOCTL 000A CMD_OUTPUT_STATUS +0009 CMD_OUTPUT_VERIFY 0019 CMD_QUERY_IOCTL +0018 CMD_SET_DEVICE 000D CR 005E CTL 0001 CTLA +0002 CTLB 001C CTLBS 0003 CTLC 0004 CTLD 0005 CTLE +0006 CTLF 0007 CTLG 0008 CTLH 0009 CTLI 000A CTLJ +000B CTLK 000D CTLM 0010 CTLP 0011 CTLQ 0012 CTLR +0013 CTLS 0014 CTLT 0015 CTLU 001F CTLUB 001E CTLUP +0016 CTLV 0017 CTLW 0018 CTLX 0019 CTLY 001A CTLZ +007F DEL 0400 DIR_FLAG 0008 DMD_NAME_LEN 0021 DOS_INT +FFFB ED_ACCESS FFF4 ED_ACC_CODE FFAB ED_ASSIGN FFEA ED_BADCMD +FFE9 ED_BADDATA FFE6 ED_BADMEDIA FFE8 ED_BADRHLEN +FFE7 ED_BADSEEK FFEC ED_BADUNIT FFF7 ED_BLOCK FFA6 ED_COMPONENT +FFF3 ED_DATA FFEF ED_DEVICE FFF0 ED_DIR FFDE ED_DISKCHG FFF9 ED_DMD +FFF1 ED_DRIVE FFF6 ED_ENVIRON FFB0 ED_EXISTS FFAD ED_FAIL FFFE ED_FILE +FFF5 ED_FORMAT FFFF ED_FUNCTION FFE1 ED_GENFAIL FFFC ED_HANDLE +FFFA ED_H_MATCH FFA6 ED_LASTERROR FFDF ED_LOCKFAIL +FFAE ED_MAKE FFF8 ED_MEMORY FFCE ED_NET FFBF ED_NETACCESS +FFB3 ED_NETCOMM FFA7 ED_NETFUNC FFB1 ED_NETLOG FFB7 ED_NETPWD FFB5 ED_NETREQ +FFB2 ED_NETSRVR FFB4 ED_NETTIME FFB6 ED_NETVER FFA8 ED_NETWRITE +FFDD ED_NOFCBS FFDC ED_NOLOCKS FFE4 ED_NOPAPER FFEB ED_NOTREADY +FFA9 ED_PARAM FFAA ED_PASSWORD FFFD ED_PATH FFED ED_PROTECT +FFE2 ED_RDFAIL FFE5 ED_RNF FFEE ED_ROOM FFE0 ED_SHAREFAIL +FFAC ED_STRUCT FFE3 ED_WRFAIL 0002 ERR_ABORT 0003 ERR_FAIL 0000 ERR_IGNORE +0001 ERR_RETRY 0002 ERR_TBL_ACTION 0001 ERR_TBL_CLASS +0000 ERR_TBL_CODE 0004 ERR_TBL_LEN +0003 ERR_TBL_LOCUS 001B ESC 0000 FALSE +0007 FDOS_MAXPARM 0050 FD_COMMIT 0054 FD_DDIO +0048 FD_DISKINFO 004B FD_EXEC 004C FD_EXIT 0055 FD_EXPAND +004D FD_FCB 0049 FD_FLUSH 0052 FD_LOCK 0051 FD_NEW 0058 FD_REOPEN +004A FD_SELECT 0001 IDLE_COMMAND FFFF IDLE_DETECT +C000 IDLE_DISABLE 0002 IDLE_DOSFUNC 8000 IDLE_INIT +0004 IDLE_INT28 4000 IDLE_ON 004D IDM 005A IDZ 0200 INT_FLAG +000A LF 0002 LOC_BLOCK 0004 LOC_CHAR 0005 LOC_MEMORY 0003 LOC_NET +0001 LOC_UNKNOWN 000D MAX_FILELEN +0050 MAX_PATHLEN 0003 MS_A_READ 0004 MS_A_WRITE 000C MS_C_FLUSH +0008 MS_C_NOECHO 0007 MS_C_RAWIN 0006 MS_C_RAWIO 0001 MS_C_READ +000A MS_C_READSTR 000B MS_C_STAT 0002 MS_C_WRITE +0009 MS_C_WRITESTR 001B MS_DRV_ALLOC +001C MS_DRV_ALLOCSPEC 000D MS_DRV_ALLRESET 0019 MS_DRV_GET +000E MS_DRV_SET 0036 MS_DRV_SPACE 0010 MS_F_CLOSE +0013 MS_F_DELETE 002F MS_F_DMAGET +001A MS_F_DMAOFF 0059 MS_F_ERROR 0054 MS_F_GETVERIFY +005C MS_F_LOCK 0016 MS_F_MAKE 000F MS_F_OPEN 0029 MS_F_PARSE +0024 MS_F_RANDREC 0014 MS_F_READ 0027 MS_F_READBLK +0021 MS_F_READRAND 0017 MS_F_RENAME +0011 MS_F_SFIRST 0023 MS_F_SIZE 0012 MS_F_SNEXT +002E MS_F_VERIFY 0015 MS_F_WRITE 0028 MS_F_WRITEBLK +0022 MS_F_WRITERAND 0005 MS_L_WRITE 0048 MS_M_ALLOC 0049 MS_M_FREE +004A MS_M_SETBLOCK 0058 MS_M_STRATEGY +0062 MS_P_GETPSP 0026 MS_P_MKPSP 0050 MS_P_SETPSP +0000 MS_P_TERMCPM 0031 MS_P_TERMKEEP +0030 MS_S_BDOSVER 0033 MS_S_BREAK 0038 MS_S_COUNTRY +0035 MS_S_GETINT 0025 MS_S_SETINT +002A MS_T_GETDATE 002C MS_T_GETTIME +002B MS_T_SETDATE 002D MS_T_SETTIME 003B MS_X_CHDIR +0043 MS_X_CHMOD 003E MS_X_CLOSE 0068 MS_X_COMMIT 003C MS_X_CREAT +0047 MS_X_CURDIR 0057 MS_X_DATETIME 0045 MS_X_DUP +0046 MS_X_DUP2 004B MS_X_EXEC 004C MS_X_EXIT 0060 MS_X_EXPAND +004E MS_X_FIRST 6601 MS_X_GETCP 0044 MS_X_IOCTL 0042 MS_X_LSEEK 0039 MS_X_MKDIR +005B MS_X_MKNEW 005A MS_X_MKTEMP 004F MS_X_NEXT 003D MS_X_OPEN +003F MS_X_READ 0056 MS_X_RENAME 003A MS_X_RMDIR 6602 MS_X_SETCP +0067 MS_X_SETHC 0041 MS_X_UNLINK 004D MS_X_WAIT 0040 MS_X_WRITE +0040 NO_CRIT_ERRORS 0800 OFLW_FLAG 0008 OK_FAIL 0020 OK_IGNORE +0010 OK_RETRY 0018 OK_RF 0030 OK_RI 0038 OK_RIF 0004 PROC_DEVIN +0001 PROC_IDLE 0002 PROC_INT28 0003 PROC_KEYIN 0060 PSPILEN 0100 PSPLEN +0016 RH0_LEN 000D RH13_LEN 000D RH14_LEN 0017 RH19_LEN 000F RH1_LEN +0015 RH24_LEN 0018 RH2_LEN 001E RH4_LEN 000E RH5_LEN 0200 RHS_BUSY +0100 RHS_DONE 8000 RHS_ERROR 0400 RHS_IC 0800 RHS_RM 001E RH_SIZE +007F RQ19_DSP_GET 005F RQ19_DSP_SET +0042 RQ19_FORMAT 0060 RQ19_GET 004D RQ19_PRP_END +004C RQ19_PRP_START 006B RQ19_QRY_PRP +006A RQ19_QRY_SEL 0061 RQ19_READ 004A RQ19_SELECT +0040 RQ19_SET 0062 RQ19_VERIFY 0041 RQ19_WRITE 007F RUBOUT +0080 SIGN_FLAG 00C0 STACK_SIZE 0003 STDAUX 0002 STDERR 0000 STDIN +0001 STDOUT 0004 STDPRN 0009 TAB 0001 TERM_BREAK 0002 TERM_ERROR +0000 TERM_NORMAL 0003 TERM_RESIDENT FFFF TRUE +0006 TRUE_VERSION 0014 XFNMAX 0040 ZERO_FLAG 0001 __RASM__ + +0000 LABELS +0058 CHAR_E10 0079 CHAR_E20 004D CHAR_ERROR 00A5 DISK_E10 00C2 DISK_E20 +00FA DISK_E40 010B DISK_E50 009A DISK_ERROR 0000 DO_INT24 0028 ERROR_EXIT +0038 ERROR_R10 0035 ERROR_RET 0045 FCBERROR_EXIT 004C FE_E10 +0000 FUNC59 0000 GET_DSEG 0000 RELOAD_REGISTERS +0000 RETURN_AX_CLC 019C SCAN_ERROR_TABLE 01AC SCAN_ET10 +01AD SCAN_ET20 018F SET_D10 0135 SET_E10 0146 SET_E20 0150 SET_E30 +010E SET_ERROR 016B SET_ERROR_DATA 0153 SET_LOGICAL_ERROR +ION 0014 XFNMAX 0040 ZERO_FLAG 0001 __RASM__ + +0000 LABELS +005 \ No newline at end of file diff --git a/IBMDOS/BIN/FCBS.LST b/IBMDOS/BIN/FCBS.LST new file mode 100644 index 0000000..1cbd885 --- /dev/null +++ b/IBMDOS/BIN/FCBS.LST @@ -0,0 +1,1681 @@ + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 1 + + += 0001 __RASM__ EQU 1 + + title 'FCB - DOS file system FCB support' + ; File : $FCBS.A86$ + ; + ; Description : + ; + ; Original Author : DIGITAL RESEARCH + ; + ; Last Edited By : $CALDERA$ + ; + ;-----------------------------------------------------------------------; + ; Copyright Work of Caldera, Inc. All Rights Reserved. + ; + ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, + ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. + ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES + ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF + ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO + ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE + ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE + ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, + ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, + ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, + ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF + ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT + ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND + ; CIVIL LIABILITY. + ;-----------------------------------------------------------------------; + ; + ; *** Current Edit History *** + ; *** End of Current Edit History *** + ; $Log$ + ; FCBS.A86 1.10 93/11/11 15:38:14 + ; Chart Master fix - fcb_readblk over > 64k is truncated to 64k and + ; error 2 (Segment boundry overlap) is returned + ; FCBS.A86 1.9 93/10/18 17:37:06 + ; fix for >255 open files (PNW Server) + ; ENDLOG + + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 2 + + += eject ! include i:fdos.equ += ; File : $FDOS.EQU$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += ; += ; Structure of Buffer Control Blocks += ; ---------------------------------- += ; These BCBs immediately preceed the data buffers. BCBs are += ; always shared for all drives and therefore must be big += ; enough for the largest drive. += ; += += 0000 BCB_NEXT equ word ptr 00h ; link to next buffer += 0002 BCB_PREV equ word ptr 02h ; link to previous buffer += 0004 BCB_DRV equ byte ptr 04h ; drive of this buffer or 0FFh += 0005 BCB_FLAGS equ byte ptr 05h ; buffer flags += 0006 BCB_REC equ word ptr 06h ; low 16 bits of sector address += 0008 BCB_REC2 equ byte ptr 08h ; top 8 bits of record address += 000A BCB_COPIES equ byte ptr 0Ah ; number of copies to write += 000B BCB_SEPARATION equ word ptr 0Bh ; # sectors copies are apart += 000D BCB_DDSC equ dword ptr 0Dh ; DWORD ptr to DDSC_ += 0011 BCB_REMOTE equ word ptr 11h ; remote in-use count + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 3 + + += 0014 BCB_DATA equ byte ptr 14h ; buffer data += += 0002 BF_ISFAT equ 0002h ; buffer marked as FAT sector += 0004 BF_ISDIR equ 0004h ; buffer marked as Directory sector += 0008 BF_ISDAT equ 0008h ; buffer marked as Data sector += 0040 BF_DIRTY equ 0040h ; buffer marked as modified += 0080 BF_REMOTE equ 0080h ; buffer is remote += += 0FF6 MAX12 equ 0FF6h ; max. disk size w/ 12-bit media += += ; Structure of Hash Control Block += ; ------------------------------- += ; Each hash control block refers to the hash codes of one += ; disrectory cluster or a root directory. += += 0000 HCB_LINK equ word ptr 0 ; link to next control block += 0002 HCB_DRV equ byte ptr 2 ; drive for this entry or 0FFh += 0004 HCB_CLU equ word ptr 4 ; cluster number or 0000 if root += 0006 HCB_CNT equ word ptr 6 ; number of hashed entries += 0008 HCB_DATA equ word ptr 8 ; hash buffer data += += += ; Structure of DOS FCB += ; -------------------- += ; This is hopefully consistent with what DOS stores in an += ; open file control block for DOS 1.x functions += += 0000 MSF_EXTFLG equ byte ptr 0 ; if this is 0xFF, skip 1st 7 byte += 0006 MSF_ATTRIB equ byte ptr 6 ; file attributes if MSF_EXTFLG += 0000 MSF_DRIVE equ byte ptr 0 ; 1st byte normally drive code += 0001 MSF_NAME equ byte ptr 1 ; 8-bit ASCII file name, 11 characters += 000C MSF_BLOCK equ word ptr 12 ; current block number += 000E MSF_RECSIZE equ word ptr 14 ; current logical record size += 0010 MSF_SIZE equ word ptr 16 ; 32-bit file size += 0014 MSF_DATE equ word ptr 20 ; last date stamp += 0016 MSF_TIME equ word ptr 22 ; last time stamp += 0018 MSF_IFN equ byte ptr 24 ;; internal file number += 0019 MSF_IOCTL equ byte ptr 25 ;; file status += 001A MSF_BLOCK1 equ word ptr 26 ;; 1st block of file += 001C MSF_DBLK equ word ptr 28 ;; directory block += 001C MSF_DEVPTR equ dword ptr 28 ;; address of device driver += 001E MSF_DCNT equ word ptr 30 ;; directory count += 0020 MSF_CR equ byte ptr 32 ; current sequential record += 0021 MSF_RR equ word ptr 33 ; random record address (3 or 4 byte) += 0023 MSF_RR2 equ byte ptr 35 ; random record overflow += += += ; Structure of DOS DPB += ; -------------------- += ; The layout of this structure is a guess based on += ; examples. It is returned by PC MODE on functions 1Fh and += ; 32h and is required by various disk-related utilities + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 4 + + += ; like disk editors and CHKDSK. += += 0000 DDSC_UNIT equ byte ptr 0 ; absolute drive number += 0001 DDSC_RUNIT equ byte ptr 1 ; relative unit number += 0002 DDSC_SECSIZE equ word ptr 2 ; sector size in bytes += 0004 DDSC_CLMSK equ byte ptr 4 ; sectors/cluster - 1 += 0005 DDSC_CLSHF equ byte ptr 5 ; log2 (sectors/cluster) += 0006 DDSC_FATADDR equ word ptr 6 ; sector address of FAT += 0008 DDSC_NFATS equ byte ptr 8 ; # of FAT copies += 0009 DDSC_DIRENT equ word ptr 9 ; size of root directory += 000B DDSC_DATADDR equ word ptr 11 ; sector address of cluster #2 += 000D DDSC_NCLSTRS equ word ptr 13 ; # of clusters on disk += 000F DDSC_NFATRECS equ word ptr 15 ; # of sectors per FAT += 0011 DDSC_DIRADDR equ word ptr 17 ; sector address of root dir += 0013 DDSC_DEVHEAD equ dword ptr 19 ; device driver header += 0013 DDSC_DEVOFF equ word ptr 19 += 0015 DDSC_DEVSEG equ word ptr 21 += 0017 DDSC_MEDIA equ byte ptr 23 ; current media byte += 0018 DDSC_FIRST equ byte ptr 24 ; "drive never accessed" flag += 0019 DDSC_LINK equ dword ptr 25 ; next drive's DDSC += 001D DDSC_BLOCK equ word ptr 29 ; next block to allocate += 001F DDSC_FREE equ word ptr 31 ; total free clusters on drive += 0021 DDSC_LEN equ 33 += += += += ; DELWATCH hooks called by OS += += 0000 DELW_RDMASK equ 0 ; delete dir search mask += 0002 DELW_DELETE equ 2 ; delete this dir entry += 0003 DELW_FREECLU equ 3 ; free some clusters += 0004 DELW_FREERD equ 4 ; free root dir entry += 0005 DELW_SPACE equ 5 ; add "deletes" to free space += 0007 DELW_NEWDISK equ 7 ; new disk logged in += 000E DELW_PURGE equ 14 ; perge pd file += 000F DELW_UNDEL equ 15 ; undelete pd file += += ; SuperStore hook called by OS += += 0010 SSTOR_SPACE equ 10h ; enquire # physical free space += += ; Password hooks called by OS += += 0020 PASSWD_CREAT equ 20h ; initialise an entry += 0021 PASSWD_CHMOD equ 21h ; change an entry += 0022 PASSWD_CHECK equ 22h ; check an entry += += ; Share hooks in PCMODE data segment += ; += ; These point to a stub which does a "STC, RETF" += ; += + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 5 + + += 000F NUM_SHARE_STUB_ENTRIES equ 15 += += 0000 S_LOCKS equ DWORD*0 ; share lock/unlock region += 0004 S_UPDATE equ DWORD*1 ; update DHNDL from share += 0008 S_RECORD equ DWORD*2 ; update share from DHNDL += 000C S_FDOSRW equ DWORD*3 ; validate proposed operation += 0010 S_DISCARD equ DWORD*4 ; discard all files on drive += 0014 S_OPEN equ DWORD*5 ; files is opening, remember it += 0018 S_CLOSE equ DWORD*6 ; files is closing, forget it += 001C S_OM_COMPAT equ DWORD*7 ; check open mode compatible += 0020 S_CLOSE_IF_OPEN equ DWORD*8 ; close if compat open, else deny += 0024 S_DENY_IF_OPEN equ DWORD*9 ; deny if open shared/by others += 0028 S_GET_LIST_ENTRY equ DWORD*10 ; get open file list entry += 002C S_CLOSE_FILES equ DWORD*11 ; close all files for given PSP/UID += += ; struct dirfcb += += 0000 DNAME equ byte ptr 0 ;file name & type += 000B DATTS equ byte ptr 11 += 0001 DA_RO equ 01h ; 0x01 - read/only += 0002 DA_HIDDEN equ 02h ; 0x02 - hidden += 0004 DA_SYSTEM equ 04h ; 0x04 - system += 0008 DA_VOLUME equ 08h ; 0x08 - volume label += 0010 DA_DIR equ 10h ; 0x10 - sub-directory += 0020 DA_ARCHIVE equ 20h ; 0x20 - archive += 0080 DA_CLUSTER equ 80h ; 0x80 - return starting cluster from search (API ex + tenti += 0080 DA_DELWATCH equ 80h ; 0x88 - return pending delete files += 00D8 DA_FIXED equ 11011000b ; can't CHMOD label, dir, unused bits += FF27 DA_CHANGE equ not DA_FIXED ; all others are changeable += += ;DATTS2 equ 12 ;CP/M attributes += ; ; 0x80 - f1' modify default open rules += ; ; 0x40 - f2' partial close default += ; ; 0x20 - f3' ignore close checksum errors += ; ; 0x10 - f4' disable checksums += ; ; 0x08 - (reserved) += ; ; 0x04 - DELETE password += ; ; 0x02 - WRITE password += ; ; 0x01 - READ password += 000D DUNDEL equ 13 ;1st letter of deleted file += 000E DPWD equ word ptr 14 ;16-bit password hash code += 0010 DMODTIME equ word ptr 16 ;delwatch time (hhhhhmmmmmmsssss) += 0012 DMODDATE equ word ptr 18 ;delwatch date (yyyyyyymmmmddddd) += ;DRECSIZE equ 16 ;FlexOS record size += ;DUSER equ 18 ;FlexOS user ID of creator += ;DGROUP equ 19 ;FlexOS group ID of creator += 0014 DPWM equ word ptr 20 ;FlexOS access rights += 0016 DTIME equ 22 ;time (hhhhhmmmmmmsssss) += 0018 DDATE equ 24 ;date (yyyyyyymmmmddddd) += 001A DBLOCK1 equ 26 ;first block in file += 001C DSIZE equ 28 ;current file size + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 6 + + += += ; DOS Media Password Definitions += ; ------------------------------ += += 000F PWM_OWNER equ 000Fh ; PWD Owner mask += 00F0 PWM_GROUP equ 00F0h ; PWD Group mask += 0F00 PWM_WORLD equ 0F00h ; PWD World mask += 0888 PWM_R equ 0888h ; PWD required for reading += 0444 PWM_W equ 0444h ; PWD required for writing += 0222 PWM_E equ 0222h ; PWD req'd for executing += 0111 PWM_D equ 0111h ; PWD required for deleting += 0DDD PWM_ANY equ PWM_R+PWM_W+PWM_D ; PWD required for anything += += += ; literal constants += += 0FFF FAT12 equ 00fffh ; 12 bit fat += FFFF FAT16 equ 0ffffh ; 16 bit fat += += FFFF ENDDIR equ 0ffffh ;end of directory += + + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 7 + + += eject ! include i:msdos.equ += ; File : $MSDOS.EQU$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += += += 0000 MS_P_TERMCPM equ 00H += 0001 MS_C_READ equ 01H += 0002 MS_C_WRITE equ 02H += 0003 MS_A_READ equ 03H += 0004 MS_A_WRITE equ 04H += 0005 MS_L_WRITE equ 05H += 0006 MS_C_RAWIO equ 06H += 0007 MS_C_RAWIN equ 07H += 0008 MS_C_NOECHO equ 08H += 0009 MS_C_WRITESTR equ 09H += 000A MS_C_READSTR equ 0aH += 000B MS_C_STAT equ 0bH += 000C MS_C_FLUSH equ 0cH += 000D MS_DRV_ALLRESET equ 0dH += 000E MS_DRV_SET equ 0eH += 000F MS_F_OPEN equ 0fH + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 8 + + += 0010 MS_F_CLOSE equ 10H += 0011 MS_F_SFIRST equ 11H += 0012 MS_F_SNEXT equ 12H += 0013 MS_F_DELETE equ 13H += 0014 MS_F_READ equ 14H += 0015 MS_F_WRITE equ 15H += 0016 MS_F_MAKE equ 16H += 0017 MS_F_RENAME equ 17H += 0019 MS_DRV_GET equ 19H += 001A MS_F_DMAOFF equ 1aH += 001B MS_DRV_ALLOC equ 1bH += 001C MS_DRV_ALLOCSPEC equ 1cH += 0021 MS_F_READRAND equ 21H += 0022 MS_F_WRITERAND equ 22H += 0023 MS_F_SIZE equ 23H += 0024 MS_F_RANDREC equ 24H += 0025 MS_S_SETINT equ 25H += 0026 MS_P_MKPSP equ 26H += 0027 MS_F_READBLK equ 27H += 0028 MS_F_WRITEBLK equ 28H += 0029 MS_F_PARSE equ 29H += 002A MS_T_GETDATE equ 2aH += 002B MS_T_SETDATE equ 2bH += 002C MS_T_GETTIME equ 2cH += 002D MS_T_SETTIME equ 2dH += 002E MS_F_VERIFY equ 2eH += 002F MS_F_DMAGET equ 2fH += 0030 MS_S_BDOSVER equ 30H += 0031 MS_P_TERMKEEP equ 31H += 0033 MS_S_BREAK equ 33H += 0035 MS_S_GETINT equ 35H += 0036 MS_DRV_SPACE equ 36H += 0038 MS_S_COUNTRY equ 38H += 0039 MS_X_MKDIR equ 39H += 003A MS_X_RMDIR equ 3aH += 003B MS_X_CHDIR equ 3bH += 003C MS_X_CREAT equ 3cH += 003D MS_X_OPEN equ 3dH += 003E MS_X_CLOSE equ 3eH += 003F MS_X_READ equ 3fH += 0040 MS_X_WRITE equ 40H += 0041 MS_X_UNLINK equ 41H += 0042 MS_X_LSEEK equ 42H += 0043 MS_X_CHMOD equ 43H += 0044 MS_X_IOCTL equ 44H += 0045 MS_X_DUP equ 45H += 0046 MS_X_DUP2 equ 46H += 0047 MS_X_CURDIR equ 47H += 0048 MS_M_ALLOC equ 48H += 0049 MS_M_FREE equ 49H += 004A MS_M_SETBLOCK equ 4aH += 004B MS_X_EXEC equ 4bH + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 9 + + += 004C MS_X_EXIT equ 4cH += 004D MS_X_WAIT equ 4dH += 004E MS_X_FIRST equ 4eH += 004F MS_X_NEXT equ 4fH += 0050 MS_P_SETPSP equ 50H += 0054 MS_F_GETVERIFY equ 54H += 0056 MS_X_RENAME equ 56H += 0057 MS_X_DATETIME equ 57H += 0058 MS_M_STRATEGY equ 58h += 0059 MS_F_ERROR equ 59H += 005A MS_X_MKTEMP equ 5aH += 005B MS_X_MKNEW equ 5bH += 005C MS_F_LOCK equ 5cH += 0060 MS_X_EXPAND equ 60H += 0062 MS_P_GETPSP equ 62H += 6601 MS_X_GETCP equ 6601h += 6602 MS_X_SETCP equ 6602h += 0067 MS_X_SETHC equ 67h += 0068 MS_X_COMMIT equ 68h += += 0021 DOS_INT equ 21h ; DOS Entry Point += ; += 0000 STDIN equ 0 ; Standard Console Input Handle += 0001 STDOUT equ 1 ; Standard Console Output Handle += 0002 STDERR equ 2 ; Standard Error Output += 0003 STDAUX equ 3 ; Auxilary Device Handle += 0004 STDPRN equ 4 ; Printer Device Handle + + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 10 + + += eject ! include i:mserror.equ += ; File : $MSERROR.EQU$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += += FFFF ED_FUNCTION equ -01 ; invalid function number += FFFE ED_FILE equ -02 ; file not found += FFFD ED_PATH equ -03 ; path not found += FFFC ED_HANDLE equ -04 ; too many open files += FFFB ED_ACCESS equ -05 ; file access denied += FFFA ED_H_MATCH equ -06 ; invalid handle number += FFF9 ED_DMD equ -07 ; memory descriptor destroyed += FFF8 ED_MEMORY equ -08 ; insufficient memory += FFF7 ED_BLOCK equ -09 ; invalid memory block addr += FFF6 ED_ENVIRON equ -10 ; invalid environment += FFF5 ED_FORMAT equ -11 ; invalid format += FFF4 ED_ACC_CODE equ -12 ; invalid access code += FFF3 ED_DATA equ -13 ; invalid data += FFF1 ED_DRIVE equ -15 ; invalid drive specified += FFF0 ED_DIR equ -16 ; can't remove current dir += FFEF ED_DEVICE equ -17 ; not same device += FFEE ED_ROOM equ -18 ; no more files + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 11 + + += += FFED ED_PROTECT equ -19 ; disk write protected += FFEC ED_BADUNIT equ -20 ; invalid drive specified += FFEB ED_NOTREADY equ -21 ; drive doesn't respond += FFEA ED_BADCMD equ -22 ; invalid command to driver += FFE9 ED_BADDATA equ -23 ; data CRC error += FFE8 ED_BADRHLEN equ -24 ; (shouldn't happen) += FFE7 ED_BADSEEK equ -25 ; can't seek to track += FFE6 ED_BADMEDIA equ -26 ; unrecognizable medium += FFE5 ED_RNF equ -27 ; record/sector not found += FFE4 ED_NOPAPER equ -28 ; printer error += FFE3 ED_WRFAIL equ -29 ; write failed += FFE2 ED_RDFAIL equ -30 ; read failed += FFE1 ED_GENFAIL equ -31 ; anything failed += FFE0 ED_SHAREFAIL equ -32 ; sharing conflict += FFDF ED_LOCKFAIL equ -33 ; locking conflict += FFDE ED_DISKCHG equ -34 ; invalid disk change += FFDD ED_NOFCBS equ -35 ; FCB table exhausted += FFDC ED_NOLOCKS equ -36 ; lock list items exhausted += FFCE ED_NET equ -50 ; Network Request Not Supported += += FFBF ED_NETACCESS equ -65 ; file access denied += += FFB7 ED_NETPWD equ -73 ; Server Password Error += FFB6 ED_NETVER equ -74 ; Incorrect Server version += FFB5 ED_NETREQ equ -75 ; No Local Network Resources += FFB4 ED_NETTIME equ -76 ; Network Time Out Error += FFB3 ED_NETCOMM equ -77 ; Network Communications Error += FFB2 ED_NETSRVR equ -78 ; No Server Network Resources += FFB1 ED_NETLOG equ -79 ; Server Not Logged In += += FFB0 ED_EXISTS equ -80 ; file already exists += FFAE ED_MAKE equ -82 ; Cannot Make (Files ??) += FFAD ED_FAIL equ -83 ; FAIL code returned from INT 24 += FFAC ED_STRUCT equ -84 ; Out of Structures += FFAB ED_ASSIGN equ -85 ; Already Assigned += FFAA ED_PASSWORD equ -86 ; Invalid Password += FFA9 ED_PARAM equ -87 ; Invalid Parameter += FFA8 ED_NETWRITE equ -88 ; Network write fault += FFA7 ED_NETFUNC equ -89 ; Function not supported on network += FFA6 ED_COMPONENT equ -90 ; system component not installed += FFA6 ED_LASTERROR equ -90 ; Last Error Number Used += += += 0001 CLASS_RESOURCE equ 1 ; Out of Resource += 0002 CLASS_TEMP equ 2 ; Temporary Situation += 0003 CLASS_AUTHOR equ 3 ; Authorization Error += 0004 CLASS_INTERNAL equ 4 ; Internal System Software Error += 0005 CLASS_HARDWARE equ 5 ; Hardware Failure += 0006 CLASS_SYSTEM equ 6 ; Serious System Failure += 0007 CLASS_APPLIC equ 7 ; Application Program Error += 0008 CLASS_LOST equ 8 ; File/Item Not Found + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 12 + + += 0009 CLASS_FORMAT equ 9 ; File/Item Illegal Format += 000A CLASS_LOCKED equ 10 ; File/Item Locked += 000B CLASS_MEDIA equ 11 ; Media Failure += 000C CLASS_EXISTS equ 12 ; Item Already Exists += 000D CLASS_UNKNOWN equ 13 ; Unknown Classification += += 0001 ACT_RETRY equ 1 ; Retry a few times then prompt user += 0002 ACT_DELAY equ 2 ; Delay then as ACT_RETRY += 0003 ACT_USER equ 3 ; Prompt user to re-enter data += 0004 ACT_ABORT equ 4 ; Clean Up then ABORT the process += 0005 ACT_TERM equ 5 ; Terminate immeadiately NO CLEAN UP += 0006 ACT_IGNORE equ 6 ; Ignore the Error += 0007 ACT_URETRY equ 7 ; Retry the error after user intervention += += 0001 LOC_UNKNOWN equ 1 ; Unknown error location += 0002 LOC_BLOCK equ 2 ; Block Device Failure += 0003 LOC_NET equ 3 ; Network Failure += 0004 LOC_CHAR equ 4 ; Related to Serial/Character devices += 0005 LOC_MEMORY equ 5 ; Failure related to Memory + + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 13 + + += eject ! include i:doshndl.def ; DOS Handle Structures += ; File : $DOSHNDL.DEF$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += += 0000 DCNTRL_DSADD equ dword ptr 0000h += 0000 DCNTRL_DSOFF equ word ptr 0000h += 0002 DCNTRL_DSSEG equ word ptr 0002h += 0004 DCNTRL_COUNT equ word ptr 0004h += 0006 DCNTRL_LEN equ 6 += += 0000 DHNDL_COUNT equ word ptr 00h ; 00 - Usage Count += 0002 DHNDL_MODE equ word ptr 02h ; 02 - File Mode += += 8000 DHM_FCB equ 8000h ; marks as FCB += 4000 DHM_COMMIT equ 4000h ; auto-commit file += 2000 DHM_NOCRIT equ 2000h ; no critical errors += 0080 DHM_LOCAL equ 10000000b ; file is not inherited += 0070 DHM_SHAREMSK equ 01110000b ; sharing bits += 0000 DHM_COMPAT equ 00000000b += 0010 DHM_DENY_ALL equ 00010000b ; exclusive - deny all += 0020 DHM_DENY_WRITE equ 00100000b + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 14 + + += 0030 DHM_DENY_READ equ 00110000b += 0040 DHM_DENY_NONE equ 01000000b += 000F DHM_RWMSK equ 00001111b ; read write bits += 0002 DHM_RW equ 00000010b ; file opened read/write += 0001 DHM_WO equ 00000001b ; file opened write only += 0000 DHM_RO equ 00000000b ; file opened read only += += ; += ; 01h to 03h To be Determined += ; += 0004 DHNDL_DATRB equ byte ptr 04h ; Disk attribute byte += 0005 DHNDL_ATTR equ byte ptr 05h ; Attribute Byte += 0005 DHNDL_WATTR equ word ptr 05h ; Attribute Word += += 8000 DHAT_REMOTE equ 8000h ; set if file remote += 4000 DHAT_TIMEOK equ 4000h ; set if timestamp up to date += 1000 DHAT_LOCAL equ 1000h ; file is not inherited += 0800 DHAT_NETPRN equ 0800h ; device is networked printer += 0080 DHAT_DEV equ 0080h ; device/file bit += 0040 DHAT_READY equ 0040h ; ready/not ready bit += 0040 DHAT_CLEAN equ 0040h ; this bit CLEAR if dirty += 0020 DHAT_BIN equ 0020h ; raw/cooked bit += 001F DHAT_DRVMSK equ 001Fh ; drive in bottom bits += 0008 DHAT_CLK equ 0008h ; -reserved- += 0004 DHAT_NUL equ 0004h ; handle is null device += 0002 DHAT_COT equ 0002h ; handle is console output device += 0001 DHAT_CIN equ 0001h ; handle is console input device += += 0007 DHNDL_DEVPTR equ dword ptr 07h ; 07 - pointer to device += 0007 DHNDL_DEVOFF equ word ptr 07h ; 07 - offset of device += 0009 DHNDL_DEVSEG equ word ptr 09h ; 09 - segment of device += 000B DHNDL_BLK1 equ word ptr 0Bh ; 0B - first cluster in file += 000D DHNDL_TIME equ word ptr 0Dh ; 0D - file time stamp += 000F DHNDL_DATE equ word ptr 0Fh ; 0F - file date stamp += 0011 DHNDL_SIZE equ dword ptr 11h ; 11 - file length += 0011 DHNDL_SIZELO equ word ptr 11h += 0013 DHNDL_SIZEHI equ word ptr 13h += 0015 DHNDL_POS equ dword ptr 15h ; 15 - current file position += 0015 DHNDL_POSLO equ word ptr 15h += 0017 DHNDL_POSHI equ word ptr 17h += 0019 DHNDL_IDX equ word ptr 19h ; 19 - relative cluster within file of last + read += 001B DHNDL_DBLK equ word ptr 1Bh ; 1B - cluster # of dir entry += 001E DHNDL_DCNTHI equ byte ptr 1Eh ; 1E - dir offset # within cluster += 001F DHNDL_DCNTLO equ byte ptr 1Fh ; 1F - dir offset # within cluster += 0020 DHNDL_NAME equ byte ptr 20h ; 20 - File/Device Name += 0028 DHNDL_EXT equ byte ptr 28h ; 28 - File extension += 002B DHNDL_SFT equ dword ptr 2Bh ; 2B - pointer to previous SFT += 002F DHNDL_UID equ word ptr 2Fh ; 2F - Owning Machine ID += 0031 DHNDL_PSP equ word ptr 31h ; 31 - Owning PSP += 0033 DHNDL_SHARE equ word ptr 33h ; 33 - Offset of sharing record += 0035 DHNDL_BLK equ word ptr 35h ; 35 - absolute cluster of last read + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 15 + + += ; 37 - dword reserved for IFS += 003B DHNDL_LEN equ 3Bh += += ; With DOS 3 structures _DBLK is a 16 bit += += += ; Logical Drive Table format += 0000 LDT_NAME equ byte ptr 00h ; 00 - Ascii Name field += 0043 LDT_FLAGS equ word ptr 43h ; 43 - Flag field += 0045 LDT_PDT equ dword ptr 45h ; 45 - PDT for this drive += 0049 LDT_BLK equ word ptr 49h ; 49 - directory sector += 004B LDT_ROOT equ word ptr 4bh ; 4B - virtual block root += 004D LDT_DRV equ byte ptr 4dh ; 4D - physical drive += 004F LDT_ROOTLEN equ word ptr 4fh ; 4F - Length of root portion += 0058 LDT_LEN equ 58h += += 8000 LFLG_NETWRKD equ 8000h += 4000 LFLG_PHYSICAL equ 4000h += 2000 LFLG_JOINED equ 2000h += 1000 LFLG_SUBST equ 1000h + + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 16 + + + eject + + + BDOS_DATA dseg word + + BDOS_CODE cseg + + extrn ifn2dhndl:near + extrn parse_one:near + extrn fdos_entry:near + + Public fdos_exit + + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 17 + + + eject + ; TERMINATE CHILD (EXIT) + + ; +----+----+ + ; | 24 | + ; +----+----+ + + ; entry: + ; ------ + ; -none- + + ; exit: + ; ----- + ; -none- + + ; Close down all FCB handles associated with the current PSP + ; + fdos_exit: + ;--------- + 0000 1E push ds + 0001 161F push ss ! pop ds ; DS -> PCM_DSEG + 0003 2BC0 sub ax,ax ; start with first DHNDL_ + fdos_exit10: + 0005 E80000 E call ifn2dhndl ; get DHNDL_ + 0008 7238 0042 jc fdos_exit40 ; stop if we have run out + 000A A30200 E mov fcb_pb+2,ax ; we may close this IFN + 000D 50 push ax + 000E 268B0F mov cx,es:DHNDL_COUNT[bx] ; get the open count + 0011 E32A 003D jcxz fdos_exit30 ; skip if nothing to do + 0013 A10000 E mov ax,current_psp ; get current PSP + 0016 263B4731 cmp ax,es:DHNDL_PSP[bx] ; does it belong to this PSP + 001A 7521 003D jne fdos_exit30 + 001C 36A10000 E mov ax,ss:machine_id ; get current process + 0020 263B472F cmp ax,es:DHNDL_UID[bx] + 0024 7517 003D jne fdos_exit30 + 0026 26F747020080 test es:DHNDL_MODE[bx],DHM_FCB + 002C 740A 0038 jz fdos_exit20 ; skip close if not FCB + 002E 06 push es + 002F 53 push bx ; save the DHNDL + 0030 B83E00 mov ax,MS_X_CLOSE + 0033 E8DB04 0511 call fcb_fdos ; make the FDOS do the work + 0036 5B pop bx + 0037 07 pop es ; recover the DHNDL + fdos_exit20: + 0038 26C7070000 mov es:DHNDL_COUNT[bx],0 ; always free the handle if it's ours + fdos_exit30: + 003D 58 pop ax + 003E FEC0 inc al ; onto next IFN + 0040 75C3 0005 jnz fdos_exit10 + fdos_exit40: + 0042 1F pop ds + 0043 C3 ret + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 18 + + + + + + + + Public fdos_fcb + + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 19 + + + eject + ; GENERIC FCB FUNCTION (FCB) + + ; +----+----+----+----+----+----+----+----+ + ; | 22 | fcbadr | count | + ; +----+----+----+----+----+----+----+----+ + ; | func | + ; +----+----+ + + ; entry: + ; ------ + ; fcbadr: FCB address + ; count: multi-sector count for read/write + ; func: FCB sub-function + + ; exit: + ; ----- + ; AX: return code or error code ( < 0) + + fdos_fcb: + ;-------- + 0044 8B5E02 mov bx,2[bp] ; BX -> parameter block + 0047 8B5F08 mov bx,8[bx] ; get subfunction code + 004A D1E3 shl bx,1 ; make it word index + 004C 80EB1E sub bl,15*WORD ; adjust to base address + 004F 721E 006F jc fcb_error ; reject if too low + 0051 80FB12 cmp bl,FCB_MAX1 ; is it in 1st block + 0054 720F 0065 jb fdos_fcb10 + 0056 80EB12 sub bl,(33-24)*WORD ; adjust for gap + 0059 7214 006F jc fcb_error + 005B 80FB1A cmp bl,FCB_MAX2 ; is it in 2nd block + 005E 7205 0065 jb fdos_fcb10 + 0060 80EB04 sub bl,(39-37)*WORD ; adjust for gap + 0063 720A 006F jc fcb_error + fdos_fcb10: + 0065 83FB1E cmp bx,FCB_MAX3 ; check the range + 0068 7305 006F jae fcb_error ; skip if invalid function + 006A 2EFFA77300 R jmp fcb_table[bx] ; call the right function + + fcb_error: + 006F BBFFFF mov bx,ED_FUNCTION + 0072 C3 ret + + 0073 9900 R fcb_table dw fcb_open ; 15-open file + 0075 3001 R dw fcb_close ; 16-close file + 0077 6001 R dw fcb_first ; 17-find first + 0079 6801 R dw fcb_next ; 18-find next + 007B 5801 R dw fcb_delete ; 19-delete file + 007D 9E01 R dw fcb_read ; 20-read from file + 007F 9901 R dw fcb_write ; 21-write to file + 0081 9100 R dw fcb_make ; 22-make file + 0083 4D01 R dw fcb_rename ; 23-rename file + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 20 + + + 0012 FCB_MAX1 equ (offset $ - offset fcb_table) + 0085 3102 R dw fcb_readrand ; 33-read from file + 0087 2C02 R dw fcb_writerand ; 34-write to file + 0089 9602 R dw fcb_size ; 35-compute file size + 008B 7901 R dw fcb_setrecord ; 36-set relative record + 001A FCB_MAX2 equ (offset $ - offset fcb_table) + 008D 5102 R dw fcb_readblk ; 39-read from file + 008F 4C02 R dw fcb_writeblk ; 40-write to file + 001E FCB_MAX3 equ (offset $ - offset fcb_table) + + fcb_make: + ;-------- + 0091 E8C302 0357 call fcb_path_prep ; build pathname + 0094 B83C00 mov ax,MS_X_CREAT + 0097 EB06 009F jmps fcb_open_make_common + + fcb_open: + ;-------- + 0099 E8BB02 0357 call fcb_path_prep ; build pathname + 009C B83D00 mov ax,MS_X_OPEN + fcb_open_make_common: + 009F C70606000280 E mov fcb_pb+6,DHM_RW+DHM_FCB ; open as an FCB for read/write + 00A5 E86904 0511 call fcb_fdos ; lets try and open the file + 00A8 7301 00AB jnc fcb_open10 ; skip if we can't + 00AA C3 ret + fcb_open10: + 00AB E80000 E call ifn2dhndl ; ES:BX -> DHNDL_ we have opened + 00AE 1E push ds + 00AF 0653 push es ! push bx ; save DHNDL_ + 00B1 E8E802 039C call fcb_point ; ES:BX = FCB + 00B4 5E1F pop si ! pop ds ; DS:SI -> DHNDL_ + 00B6 26884718 mov es:MSF_IFN[bx],al ; store IFN away + 00BA 26C7470C0000 mov es:MSF_BLOCK[bx],0 ; current block number + 00C0 26C7470E8000 mov es:MSF_RECSIZE[bx],128 ; current logical record size + 00C6 E83900 0102 call fcb_update ; update misc changing fields + 00C9 8B4407 mov ax,ds:DHNDL_DEVOFF[si] + 00CC 2689471C mov es:word ptr MSF_DEVPTR[bx],ax + 00D0 8B4409 mov ax,ds:DHNDL_DEVSEG[si] + 00D3 2689471E mov es:word ptr MSF_DEVPTR+2[bx],ax + 00D7 8B440B mov ax,ds:DHNDL_BLK1[si] + 00DA 2689471A mov es:MSF_BLOCK1[bx],ax + 00DE 8A4405 mov al,ds:DHNDL_ATTR[si] + 00E1 26884719 mov es:MSF_IOCTL[bx],al + 00E5 268A07 mov al,es:MSF_DRIVE[bx] ; get drive from FCB + 00E8 FEC8 dec al ; was absolute drive specified ? + 00EA 7904 00F0 jns fcb_open20 ; if so use it + 00EC 36A00000 E mov al,ss:current_dsk ; else use default drive + fcb_open20: + 00F0 FEC0 inc al ; make drive 1 rather than 0 based + 00F2 268807 mov es:MSF_DRIVE[bx],al ; drive code + if 0 + test ds:DHNDL_DATRB[si],DA_VOLUME + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 21 + + + else + 00F5 36F706080008 E test ss:fcb_pb+8,DA_VOLUME + 00 E + endif + 00FC 1F pop ds + 00FD 7531 0130 jnz fcb_close ; don't leave VOL label's open + 00FF 33DB xor bx,bx ; no errors ! + 0101 C3 ret + + + fcb_update: + ;---------- + ; On Entry: + ; DS:SI -> DHNDL_ + ; ES:BX -> FCB + ; On Exit: + ; DATE/TIME/SIZE/DBLK/DCNT fields updated + ; + 0102 8B440D mov ax,ds:DHNDL_TIME[si] + 0105 26894716 mov es:MSF_TIME[bx],ax + 0109 8B440F mov ax,ds:DHNDL_DATE[si] + 010C 26894714 mov es:MSF_DATE[bx],ax + 0110 8B4411 mov ax,ds:DHNDL_SIZELO[si] + 0113 26894710 mov es:MSF_SIZE[bx],ax + 0117 8B4413 mov ax,ds:DHNDL_SIZEHI[si] + 011A 26894712 mov es:MSF_SIZE+2[bx],ax + 011E 8B441B mov ax,ds:DHNDL_DBLK[si] + 0121 2689471C mov es:MSF_DBLK[bx],ax + 0125 8A441F mov al,ds:DHNDL_DCNTLO[si] + 0128 8A641E mov ah,ds:DHNDL_DCNTHI[si] + 012B 2689471E mov es:MSF_DCNT[bx],ax + 012F C3 ret + + fcb_close: + ;--------- + ; close file (DOS function 10h) + 0130 E86902 039C call fcb_point ; ES:BX -> FCB + 0133 B0FF mov al,0FFh + 0135 263A4718 cmp al,es:MSF_IFN[bx] ; is it a multiple close ? + 0139 740F 014A je fcb_fdos_common10 ; don't re-open for this... + 013B E8A201 02E0 call fcb_handle_vfy ; verify we have a sensible handle + 013E 26884718 mov es:MSF_IFN[bx],al ; mark FCB as closed (it will be) + 0142 B83E00 mov ax,MS_X_CLOSE ; now close it + ; jmps fcb_fdos_common + + fcb_fdos_common: + ;--------------- + 0145 E8C903 0511 call fcb_fdos ; make the FDOS do the work + 0148 7202 014C jc fcb_fdos_common20 ; return any error codes + fcb_fdos_common10: + 014A 33DB xor bx,bx ; else return zero + fcb_fdos_common20: + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 22 + + + 014C C3 ret + + + + fcb_rename: + ;---------- + 014D E80702 0357 call fcb_path_prep + 0150 E8EE01 0341 call fcb_path2_prep + 0153 B85600 mov ax,MS_X_RENAME ; it's a rename + 0156 EBED 0145 jmps fcb_fdos_common + + fcb_delete: + ;---------- + 0158 E8FC01 0357 call fcb_path_prep + 015B B84100 mov ax,MS_X_UNLINK ; it's a delete + 015E EBE5 0145 jmps fcb_fdos_common + + + fcb_first: + ;--------- + 0160 E8F401 0357 call fcb_path_prep ; prepare pathname + 0163 B84E00 mov ax,MS_X_FIRST ; we want to search 1st + 0166 EB06 016E jmps fcb_search_common + + fcb_next: + ;-------- + 0168 E88C03 04F7 call fcb_restore_search_state + 016B B84F00 mov ax,MS_X_NEXT + fcb_search_common: + 016E E8F502 0466 call fcb_search ; 0 of OK, otherwise ED_.. + 0171 7205 0178 jc fcb_search_common10 + 0173 E81503 048B call fcb_save_search_state ; save sucessful state + 0176 33DB xor bx,bx ; return code in BX + fcb_search_common10: + 0178 C3 ret + + + fcb_setrecord: + ;------------- + 0179 E82002 039C call fcb_point ; ES:BX -> FCB + 017C B88000 mov ax,128 ; multiply current block by 128 + 017F 26F7670C mul es:MSF_BLOCK[bx] ; to give current record number + 0183 33C9 xor cx,cx + 0185 268A4F20 mov cl,es:MSF_CR[bx] ; Add in the current record + 0189 03C1 add ax,cx ; to DX:AX to give the + 018B 83D200 adc dx,0 ; relative record + 018E 26894721 mov es:MSF_RR[bx],ax ; save the result + 0192 26885723 mov es:MSF_RR2[bx],dl + 0196 33DB xor bx,bx ; we did OK + 0198 C3 ret + + fcb_write: + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 23 + + + ;--------- + 0199 B84000 mov ax,MS_X_WRITE ; make it a write + 019C EB03 01A1 jmps fcb_seq_rw + + fcb_read: + ;-------- + 019E B83F00 mov ax,MS_X_READ ; make it a read + fcb_seq_rw: + 01A1 E83C01 02E0 call fcb_handle_vfy ; verify we have a sensible handle + 01A4 50 push ax ; save the operation + 01A5 E80402 03AC call fcb_get_count ; AX = bytes to read + 01A8 50 push ax ; save byte count + 01A9 E86402 0410 call fcb_seek_seq ; Seek to position in the file + 01AC 59 pop cx ; recover byte to xfer + 01AD 58 pop ax ; and the Operation Code + 01AE 720A 01BA jc fcb_seq_rw10 + 01B0 E80800 01BB call fcb_rw ; do the Op + 01B3 7205 01BA jc fcb_seq_rw10 + 01B5 53 push bx ; save the error code + 01B6 E80102 03BA call fcb_update_seq ; update FCB filepos + 01B9 5B pop bx ; recover error + fcb_seq_rw10: + 01BA C3 ret + + fcb_rw: + ; On Entry: + ; AX = operation code + ; CX = count + ; fcb_pb+2 = IFN + ; On Exit: + ; BX = error code + 01BB 36C4160000 E les dx,ss:dword ptr dma_offset + 01C0 03CA add cx,dx ; see if we overflow + 01C2 7236 01FA jc fcb_rw20 + 01C4 2BCA sub cx,dx ; count back to normal + 01C6 51 push cx ; save target count + 01C7 89160400 E mov fcb_pb+4,dx + 01CB 8C060600 E mov fcb_pb+6,es ; setup buffer address + 01CF 890E0800 E mov fcb_pb+8,cx ; and target count + 01D3 E83B03 0511 call fcb_fdos ; ask the FDOS to do the read/write + 01D6 7220 01F8 jc fcb_rw10 ; we got a real error... + 01D8 1E push ds + 01D9 06 push es + 01DA A10200 E mov ax,fcb_pb+2 ; get IFN + 01DD E80000 E call ifn2dhndl ; ES:BX -> DHNDL_ we have open + 01E0 0653 push es ! push bx ; save DHNDL_ + 01E2 E8B701 039C call fcb_point ; ES:BX = FCB + 01E5 5E1F pop si ! pop ds ; DS:SI -> DHNDL_ + 01E7 E818FF 0102 call fcb_update ; update file size/time-stamp + 01EA 07 pop es + 01EB 1F pop ds + 01EC 58 pop ax ; recover target count + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 24 + + + 01ED 8B0E0800 E mov cx,fcb_pb+8 ; we xfered this much + 01F1 3BC8 cmp cx,ax ; did we xfer enough + 01F3 7209 01FE jb fcb_rw30 ; nope.. + 01F5 33DB xor bx,bx ; xfer went OK + 01F7 C3 ret + + fcb_rw10: + 01F8 58 pop ax ; discard target count + 01F9 C3 ret + + fcb_rw20: + ; Our DTA is too small - return 2 + 01FA BB0200 mov bx,2 ; indicate the DTA is too small + ; stc ; error - don't update FCB + 01FD C3 ret + + fcb_rw30: + ; We have some form of EOF - lets look into it + 01FE E89B01 039C call fcb_point ; ES:BX = FCB + 0201 268B5F0E mov bx,es:MSF_RECSIZE[bx] ; BX = record size + 0205 8BC1 mov ax,cx + 0207 33D2 xor dx,dx ; DX:AX = bytes xfer'd + 0209 F7F3 div bx ; did we xfer a complete + 020B 85D2 test dx,dx ; number of records ? + 020D 7419 0228 jz fcb_rw40 ; if so return 1 + ; Partial data was read - fill out with zero's and return 3 + 020F 40 inc ax ; allow for incomplete record + 0210 50 push ax ; save rounded up xfer count + 0211 36C43E0000 E les di,ss:dword ptr dma_offset + 0216 03F9 add di,cx ; point to 1st byte after xfer + 0218 8BCB mov cx,bx ; this many in a record + 021A 2BCA sub cx,dx ; so this many weren't xfer'd + 021C 33C0 xor ax,ax ; fill them with zero's + 021E F3AA rep stosb ; zap the bytes we didn't xfer to + 0220 58 pop ax ; recover xfer count + 0221 F7E3 mul bx ; and work out # bytes xfered + 0223 91 xchg ax,cx ; return bytes in CX + 0224 BB0300 mov bx,3 ; indicate EOF (partial read) + ; clc ; update FCB + 0227 C3 ret + + fcb_rw40: + ; No Data was xfered - return 1 + 0228 BB0100 mov bx,1 ; indicate EOF (no data read) + ; clc ; update FCB + 022B C3 ret + + fcb_writerand: + ;------------- + 022C B84000 mov ax,MS_X_WRITE ; make it a write + 022F EB03 0234 jmps fcb_random_rw + + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 25 + + + fcb_readrand: + ;------------ + 0231 B83F00 mov ax,MS_X_READ ; make it a read + fcb_random_rw: + 0234 E8A900 02E0 call fcb_handle_vfy ; check the handle is OK + 0237 50 push ax ; save the code + 0238 E87101 03AC call fcb_get_count ; AX = bytes to read + 023B 50 push ax ; save byte count + 023C 33C9 xor cx,cx ; cause update of seq posn from + 023E E8A101 03E2 call fcb_update_rr ; random record position + 0241 E8ED01 0431 call fcb_seek_rr ; Seek to position in the file + 0244 59 pop cx ; recover byte to xfer + 0245 58 pop ax ; and the Operation Code + 0246 7203 024B jc fcb_random_rw10 + 0248 E870FF 01BB call fcb_rw ; do the Op + fcb_random_rw10: + 024B C3 ret + + + fcb_writeblk: + ;------------ + 024C B84000 mov ax,MS_X_WRITE ; make it a write + 024F EB03 0254 jmps fcb_block_rw + + fcb_readblk: + ;----------- + 0251 B83F00 mov ax,MS_X_READ ; make it a read + fcb_block_rw: + 0254 E88900 02E0 call fcb_handle_vfy ; check the handle is OK + 0257 50 push ax ; save the code + 0258 E85101 03AC call fcb_get_count ; AX = bytes per record, CX = # records + 025B 91 xchg ax,cx ; CX = bytes per record + 025C F7E1 mul cx ; AX = bytes to xfer + 025E 85D2 test dx,dx ; more than 64K ? + 0260 740F 0271 jz fcb_block_rw10 ; then we should truncate it + 0262 B80F00 mov ax,15 ; AX = handy mask + 0265 99 cwd ; DX = 0 + 0266 3623060000 E and ax,ss:dma_offset ; get dma offset for para + 026B F7D0 not ax ; DX/AX = maximum bytes we can xfer + 026D F7F1 div cx ; AX = maximum blocks we can xfer + 026F F7E1 mul cx ; AX = bytes to xfer (now < 64K) + fcb_block_rw10: + 0271 50 push ax ; save byte count + 0272 E8BC01 0431 call fcb_seek_rr ; Seek to position in the file + 0275 59 pop cx ; recover byte to xfer + 0276 58 pop ax ; and the Operation Code + 0277 721C 0295 jc fcb_block_rw20 + 0279 E83FFF 01BB call fcb_rw ; do the Op + 027C 7217 0295 jc fcb_block_rw20 + 027E 53 push bx ; save the error code + 027F E86001 03E2 call fcb_update_rr ; update FCB filepos, get records xferd + 0282 8B5E02 mov bx,2[bp] ; BX -> parameter block + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 26 + + + 0285 874F06 xchg cx,6[bx] ; update amount xfered + 0288 2B4F06 sub cx,6[bx] ; CX = # we didn't xfer (normally 0) + 028B 5B pop bx ; recover (possible) error + 028C E307 0295 jcxz fcb_block_rw20 ; skip if we read all we wanted to + 028E 85DB test bx,bx ; did we have a partial read for + 0290 7503 0295 jnz fcb_block_rw20 ; a reason like EOF ? + 0292 BB0200 mov bx,2 ; no, we must have truncated it + fcb_block_rw20: + 0295 C3 ret + + + fcb_size: + ;-------- + 0296 E8BE00 0357 call fcb_path_prep + 0299 B84300 mov ax,MS_X_CHMOD ; it's a get info + 029C C70606000000 E mov fcb_pb+6,0 + 02A2 E86C02 0511 call fcb_fdos + 02A5 7238 02DF jc fcb_size40 + 02A7 E8F200 039C call fcb_point ; ES:BX = FCB + 02AA 268B4F0E mov cx,es:MSF_RECSIZE[bx] ; get the record size + 02AE 85C9 test cx,cx ; is it non-zero ? + 02B0 7503 02B5 jnz fcb_size10 ; if not + 02B2 B98000 mov cx,128 ; make it 128 bytes + fcb_size10: + 02B5 A10A00 E mov ax,fcb_pb+10 + 02B8 8B160C00 E mov dx,fcb_pb+12 ; DX:AX = file length in bytes + 02BC E87002 052F call div_32 ; DX:AX = file length in records + 02BF E306 02C7 jcxz fcb_size20 ; was there an overflow + 02C1 050100 add ax,1 + 02C4 83D200 adc dx,0 ; include an extra record + fcb_size20: + 02C7 E8D200 039C call fcb_point ; ES:BX = FCB + 02CA 26894721 mov es:MSF_RR[bx],ax ; low word of size + 02CE 26885723 mov es:MSF_RR2[bx],dl ; hi byte of size + 02D2 26837F0E40 cmp es:MSF_RECSIZE[bx],64 ; if record size < 64 bytes + 02D7 7304 02DD jae fcb_size30 ; then we use a 4 byte + 02D9 26887724 mov es:MSF_RR2+1[bx],dh ; random record position + fcb_size30: + 02DD 33DB xor bx,bx ; good return + fcb_size40: + 02DF C3 ret + + + ; Utility FCB subroutines + ;======================== + + fcb_handle_vfy: + ;-------------- + ; Verify FCB is valid and open, do not return if it isn't + ; nb. Called with nothing on stack + ; + ; On Entry: + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 27 + + + ; FCB address in parameter block + ; On Exit: + ; AX preserved + ; ES:BX -> FCB (skipping EXT bit if present) + ; fcb_pb+2 = IFN of handle + ; On Error - blow away caller and return error in BX + ; + + ; DEBUG - on reopen we could do more checks to ensure we are re-opening the + ; same file + 02E0 50 push ax + 02E1 E8B800 039C call fcb_point + 02E4 26837F0E00 cmp es:MSF_RECSIZE[bx],0 + 02E9 7506 02F1 jne fcb_handle_vfy10 + 02EB 26C7470E8000 mov es:MSF_RECSIZE[bx],128 + fcb_handle_vfy10: + 02F1 268A4718 mov al,es:MSF_IFN[bx] ; get IFN + 02F5 E80000 E call ifn2dhndl ; ES:BX -> DHNDL_ + 02F8 720E 0308 jc fcb_handle_vfy20 ; it must be a valid IFN + 02FA 26F747020080 test es:DHNDL_MODE[bx],DHM_FCB + 0300 7406 0308 jz fcb_handle_vfy20 ; it must be an FCB.. + 0302 26833F00 cmp es:DHNDL_COUNT[bx],0 + 0306 7520 0328 jne fcb_handle_vfy30 ; it must also be open.. + fcb_handle_vfy20: + 0308 E89100 039C call fcb_point + 030B 26FF770E push es:MSF_RECSIZE[bx] ; save current record size + 030F 26FF770C push es:MSF_BLOCK[bx] ; save current block number + 0313 0653 push es ! push bx + 0315 E881FD 0099 call fcb_open ; try to re-open the file + 0318 5B07 pop bx ! pop es ; point back at FCB + 031A 268F470C pop es:MSF_BLOCK[bx] ; restore current block number + 031E 268F470E pop es:MSF_RECSIZE[bx] ; restore record size + 0322 720F 0333 jc fcb_handle_err + 0324 268A4718 mov al,es:MSF_IFN[bx] ; get new IFN + fcb_handle_vfy30: + 0328 32E4 xor ah,ah + 032A A30200 E mov fcb_pb+2,ax ; set parameter block accordingly + 032D E86C00 039C call fcb_point ; ES:BX -> MSF_ + 0330 58 pop ax + 0331 F8 clc + 0332 C3 ret + + fcb_handle_err: + 0333 83C404 add sp,2*WORD ; discard AX and near return address + 0336 3DFCFF cmp ax,ED_HANDLE ; if we have run out of handles then + 0339 7503 033E jne fcb_handle_err10 ; say no FCB's, else return error + 033B B8DDFF mov ax,ED_NOFCBS + fcb_handle_err10: + 033E 93 xchg ax,bx ; error code in BX + 033F F9 stc + 0340 C3 ret + + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 28 + + + + fcb_path2_prep: + ;-------------- + ; On Entry: + ; FCB address in parameter block + ; On Exit: + ; ES:BX -> FCB (skipping EXT bit if present) + ; fcb_pb+6/8 -> unparse name from FCB + ; + 0341 E85800 039C call fcb_point ; point at the FCB + 0344 268A07 mov al,es:MSF_DRIVE[bx] ; get drive + 0347 83C310 add bx,16 ; point at 2nd name in FCB + 034A BF0000 E mov di,offset fcb_path2 + 034D 893E0600 E mov fcb_pb+6,di + 0351 8C1E0800 E mov fcb_pb+8,ds ; point at buffer we want + 0355 EB26 037D jmps fcb_path_prep_common + + fcb_path_prep: + ;------------- + ; On Entry: + ; FCB address in parameter block + ; On Exit: + ; ES:BX -> FCB (skipping EXT bit if present) + ; fcb_pb+2/4 -> unparse name from FCB + ; + 0357 33C0 xor ax,ax ; assume no attribute + 0359 8B5E02 mov bx,2[bp] ; BX -> parameter block + 035C C45F02 les bx,2[bx] ; ES:BX -> FCB + 035F 26803FFF cmp es:MSF_EXTFLG[bx],0ffh ; is it an extended FCB + 0363 7507 036C jne fcb_path_prep10 + 0365 260A4706 or al,es:MSF_ATTRIB[bx] ; we can use file mode from XFCB + 0369 83C307 add bx,7 ; skip EXT bit of FCB + fcb_path_prep10: + 036C A30800 E mov fcb_pb+8,ax ; remember the attribute + 036F 268A07 mov al,es:MSF_DRIVE[bx] ; get drive + 0372 BF0000 E mov di,offset fcb_path + 0375 893E0200 E mov fcb_pb+2,di + 0379 8C1E0400 E mov fcb_pb+4,ds ; point at buffer we want + fcb_path_prep_common: + 037D FEC8 dec al ; 0 = default drive + 037F 7903 0384 jns fcb_path_prep20 + 0381 A00000 E mov al,current_dsk ; use default drive + fcb_path_prep20: + 0384 1E push ds + 0385 1E06 push ds ! push es + 0387 1F07 pop ds ! pop es ; ES:DI -> name buffer + 0389 0441 add al,'A' ; make drive ASCII + 038B AA stosb + 038C B03A mov al,':' + 038E AA stosb ; now we have 'd:' + 038F 8D7701 lea si,MSF_NAME[bx] ; DS:SI -> source name + 0392 A5A5 movsw ! movsw + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 29 + + + 0394 A5A5 movsw ! movsw ; copy the name leaving spaces intact + 0396 B02E mov al,'.' + 0398 AA stosb + 0399 A5A4 movsw ! movsb ; copy the extention + 039B 1F pop ds + ; jmps fcb_point ; point ES:BX at FCB again + + + fcb_point: + ;--------- + ; On Entry: + ; FCB address in parameter block + ; On Exit: + ; ES:BX -> FCB (skipping EXT bit if present) + ; (All other regs preserved) + ; + 039C 8B5E02 mov bx,2[bp] ; BX -> parameter block + 039F C45F02 les bx,2[bx] ; ES:BX -> FCB + 03A2 26803FFF cmp es:MSF_EXTFLG[bx],0ffh ; is it an extended FCB + 03A6 7503 03AB jne fcb_point10 + 03A8 83C307 add bx,7 ; skip EXT bit of FCB + fcb_point10: + 03AB C3 ret + + fcb_get_count: + ;------------- + ; On Entry: + ; none + ; On Exit: + ; AX = bytes per record + ; CX = callers CX count + ; All regs fair game + ; + 03AC E8EDFF 039C call fcb_point ; ES:BX -> FCB + 03AF 8B7602 mov si,2[bp] ; SI -> parameter block + 03B2 8B4C06 mov cx,6[si] ; CX = count + 03B5 268B470E mov ax,es:MSF_RECSIZE[bx] ; get record size + 03B9 C3 ret + + fcb_update_seq: + ;-------------- + ; On Entry: + ; CX = byte count actually transferred + ; On Exit: + ; CX = record count transferred + ; All other regs fair game + ; CR/BLOCK updated with new value + ; + 03BA 8BC1 mov ax,cx + 03BC 33D2 xor dx,dx ; DX:AX = byte count transfered + 03BE E8DBFF 039C call fcb_point ; ES:BX -> FCB + 03C1 26F7770E div es:MSF_RECSIZE[bx] ; make records xfered + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 30 + + + 03C5 50 push ax ; save records xfered + 03C6 91 xchg ax,cx ; also in CX for later + 03C7 B88000 mov ax,128 + 03CA 26F7670C mul es:MSF_BLOCK[bx] ; DX:AX = record of block + 03CE 03C1 add ax,cx + 03D0 83D200 adc dx,0 ; add in amount just xfered + 03D3 268A4F20 mov cl,es:MSF_CR[bx] + 03D7 32ED xor ch,ch ; now add in CR as a word + 03D9 03C1 add ax,cx + 03DB 83D200 adc dx,0 ; DX:AX = record + 03DE 8AF2 mov dh,dl ; DH:AX = record for common code + 03E0 EB1C 03FE jmps fcb_update_common + + + fcb_update_rr: + ;------------- + ; On Entry: + ; CX = byte count actually transferred + ; On Exit: + ; CX = record count transferred + ; All other regs fair game + ; Random Record and CR/BLOCK updated with new value + ; + 03E2 91 xchg ax,cx + 03E3 33D2 xor dx,dx ; DX:AX = byte count transfered + 03E5 E8B4FF 039C call fcb_point ; ES:BX -> FCB + 03E8 26F7770E div es:MSF_RECSIZE[bx] ; make records xfered + 03EC 50 push ax ; save records xfered + 03ED 26014721 add es:MSF_RR[bx],ax ; update the RR field + 03F1 2680572300 adc es:MSF_RR2[bx],0 ; and the overflow + 03F6 268B4721 mov ax,es:MSF_RR[bx] ; get low part of RR + 03FA 268A7723 mov dh,es:MSF_RR2[bx] ; and the hi part + fcb_update_common: + 03FE 8AD4 mov dl,ah ; DX will be block number + 0400 D0E0 shl al,1 ; get top bit of CR into CY + 0402 13D2 adc dx,dx ; then into DX + 0404 D0E8 shr al,1 ; AL = CR (remember mod 128) + 0406 26884720 mov es:MSF_CR[bx],al ; set the CR field + 040A 2689570C mov es:MSF_BLOCK[bx],dx ; and the block field + 040E 59 pop cx ; recover records xfered + 040F C3 ret + + + fcb_seek_seq: + ;------------ + ; Seek to position in file indicated by the RR position + ; On Entry: + ; ES:BX -> FCB_ + ; On Exit: + ; CY clear if no problem, fcb_pb+2=IFN + ; else + ; CY set, AX = BX = error code + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 31 + + + ; All other regs fair game + ; + 0410 E889FF 039C call fcb_point ; ES:BX -> FCB_ + 0413 B88000 mov ax,128 + 0416 26F7670C mul es:MSF_BLOCK[bx] ; get record in DX:AX + 041A 268A4F20 mov cl,es:MSF_CR[bx] + 041E 32ED xor ch,ch + 0420 03C1 add ax,cx ; add in CR + 0422 83D200 adc dx,0 ; so DX:AX is really the record + 0425 50 push ax ; save low word of record + 0426 8BC2 mov ax,dx + 0428 26F7670E mul es:MSF_RECSIZE[bx] ; DX:AX = byte offset in file/10000h + 042C 8BC8 mov cx,ax ; save the important word + 042E 58 pop ax ; recover low word of record + 042F EB13 0444 jmps fcb_seek_common + + fcb_seek_rr: + ;----------- + ; Seek to position in file indicated by the RR position + ; On Entry: + ; ES:BX -> FCB_ + ; On Exit: + ; CY clear if no problem, fcb_pb+2=IFN + ; else + ; CY set, AX = BX = error code + ; All other regs fair game + ; + 0431 E868FF 039C call fcb_point ; ES:BX -> FCB_ + 0434 268A4723 mov al,es:MSF_RR2[bx] + 0438 32E4 xor ah,ah + 043A 26F7670E mul es:MSF_RECSIZE[bx] ; DX:AX = byte offset in file/10000h + 043E 8BC8 mov cx,ax ; save the important word + 0440 268B4721 mov ax,es:MSF_RR[bx] + fcb_seek_common: + 0444 26F7670E mul es:MSF_RECSIZE[bx] ; DX:AX = byte offset in file + 0448 03D1 add dx,cx ; add the two bits together + 044A A30400 E mov fcb_pb+4,ax + 044D 89160600 E mov fcb_pb+6,dx ; save position + 0451 C70608000000 E mov fcb_pb+8,0 ; seek from start + 0457 33C0 xor ax,ax + 0459 268A4718 mov al,es:MSF_IFN[bx] ; AX = IFN + 045D A30200 E mov fcb_pb+2,ax ; save IFN + 0460 B84200 mov ax,MS_X_LSEEK + 0463 E9AB00 0511 jmp fcb_fdos ; try and seek to this position + + + fcb_search: + ;---------- + ; On Entry: + ; AX = operation to perform + ; On Exit: + ; AX = 0, or ED_ error code (CY set if error) + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 32 + + + 0466 FF360000 E push dma_offset + 046A FF360000 E push dma_segment + 046E C70600000000 E mov dma_offset,offset fcb_search_buf + 0474 8C1E0000 E mov dma_segment,ds + 0478 E89600 0511 call fcb_fdos ; do the search + 047B 8F060000 E pop dma_segment + 047F 8F060000 E pop dma_offset + 0483 85C0 test ax,ax ; was there an error + 0485 F9 stc ; assume there was + 0486 7802 048A js fcb_search10 ; return the error + 0488 33C0 xor ax,ax ; no problems + fcb_search10: + 048A C3 ret + + fcb_save_search_state: + ;--------------------- + ; On entry DS=PCMODE + + 048B E80EFF 039C call fcb_point + 048E 8D7F01 lea di,MSF_NAME[bx] ; ES:DI -> FCB name + 0491 BE0000 E mov si,offset fcb_search_buf + 0494 AC lodsb ; get 1st byte = drive info + 0495 B90A00 mov cx,20/WORD ; copy 20 bytes to FCB + 0498 F3A5 rep movsw ; (the rest of the search template) + 049A AA stosb ; drive info byte follow them + + 049B C43E0000 E les di,dword ptr dma_offset ; ES:DI -> search state in DMA address + 049F 8B7602 mov si,2[bp] ; SI -> parameter block + 04A2 C57402 lds si,2[si] ; DS:SI -> FCB_ + 04A5 803CFF cmp ds:MSF_EXTFLG[si],0ffh ; extended FCB ? + 04A8 7505 04AF jne fcb_sss10 + 04AA B90700 mov cx,7 ; copy extended FCB portions too + 04AD F3A4 rep movsb ; we have copied up to name + fcb_sss10: + 04AF AA stosb ; save drive byte info + 04B0 57 push di + 04B1 B020 mov al,' ' ; space fill name + 04B3 B90B00 mov cx,11 + 04B6 F3AA rep stosb ; all blanks now + 04B8 5F pop di + 04B9 161F push ss ! pop ds ; DS:SI -> pathname + 04BB BE1E00 E mov si,offset fcb_search_buf+1Eh + + 04BE 57 push di ; unparse knowing name is good + 04BF B90800 mov cx,8 ; length of name field + fcb_sss20: + 04C2 AC lodsb ; treat '.' and '..' specially + 04C3 3C2E cmp al,'.' ; is either possible ? + 04C5 7505 04CC jne fcb_sss30 ; no, continue as normal + 04C7 AA stosb ; copy the '.' + 04C8 E2F8 04C2 loop fcb_sss20 ; go around for another '.' + 04CA EB04 04D0 jmps fcb_sss40 ; this name is rubbish!! + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 33 + + + fcb_sss30: + 04CC 4E dec si ; forget the non '.' + 04CD E80000 E call parse_one ; parse just the name + fcb_sss40: + 04D0 5F pop di + 04D1 83C708 add di,8 ; di -> fcb ext field + 04D4 3C2E cmp al,'.' ; do we have an extention ? + 04D6 7508 04E0 jne fcb_sss50 + 04D8 B90300 mov cx,3 ; length of ext field + 04DB 57 push di + 04DC E80000 E call parse_one ; parse just extension + 04DF 5F pop di + fcb_sss50: + 04E0 83C703 add di,3 ; di -> rest of fcb + 04E3 BE1500 E mov si,offset fcb_search_buf+15h + 04E6 A4 movsb ; copy the attribute field + 04E7 33C0 xor ax,ax + 04E9 B90500 mov cx,10/WORD + 04EC F3AB rep stosw ; 10 bytes of zeros + 04EE A5 movsw ; copy time + 04EF A5 movsw ; copy date + 04F0 A12F00 E mov ax,word ptr srch_buf+21+DBLOCK1 + 04F3 AB stosw ; 1st block + 04F4 A5A5 movsw ! movsw ; copy filesize + 04F6 C3 ret + + fcb_restore_search_state: + ;------------------------ + ; On entry DS=PCMODE + 04F7 1E push ds + 04F8 E8A1FE 039C call fcb_point ; ES:BX -> FCB_ + 04FB 061E push es ! push ds + 04FD 071F pop es ! pop ds ; swap DS/ES + 04FF BF0100 E mov di,offset fcb_search_buf+1 + ; ES:DI -> internal state + 0502 8D7701 lea si,1[bx] ; DS:SI -> FCB+1 + 0505 B90A00 mov cx,10 + 0508 F3A5 rep movsw ; copy info from FCB + 050A AC lodsb ; get "drive" info + 050B 26A20000 E mov es:fcb_search_buf,al ; it's the 1st byte in the srch state + 050F 1F pop ds + 0510 C3 ret + + fcb_fdos: + ;-------- + ; Make an FDOS call (NB. We don't have MX here, so it's OK) + ; Set top bit of remote_call flag so we use IFN's not XFN's + ; On Entry: + ; AX = FDOS operation + ; fcb_pb -> FDOS parameter block + ; On Exit: + ; As FDOS call + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 34 + + + ; + 0511 A30000 E mov fcb_pb,ax ; save operation type + 0514 810E00000080 E or remote_call,DHM_FCB ; forget about PSP during FCB call + 051A BA0000 E mov dx,offset fcb_pb ; DS:DX -> parameter block + 051D 1E push ds + 051E 55 push bp + 051F E80000 E call fdos_entry ; call the FDOS + 0522 5D pop bp + 0523 1F pop ds + 0524 81260000FF7F E and remote_call,not DHM_FCB ; FCB operation over + 052A 3DA6FF cmp ax,ED_LASTERROR + 052D F5 cmc ; CY set if an error occurred + 052E C3 ret + + div_32: + ; Entry: DX,AX = long dividend + ; CX = word divisor + ; Exit: DX,AX = long result + ; CX = remainder + + 052F E31F 0550 jcxz div0 ; divide by 0 + 0531 83F901 cmp cx,1 + 0534 7420 0556 je div1 ; divide by 1 + 0536 57 push di + 0537 53 push bx + 0538 33DB xor bx,bx ; BX = 0 + 053A 93 xchg ax,bx ; low word in BX, AX = 0 + 053B 92 xchg ax,dx ; high word in DX:AX + 053C 50 push ax ; save high word + 053D F7F1 div cx ; divide high part + 053F 8BF8 mov di,ax ; save result + 0541 F7E1 mul cx ; AX = even divisor part + 0543 5A pop dx ; old high in DX + 0544 2BD0 sub dx,ax ; eliminate even part + 0546 93 xchg ax,bx ; AX = low word + 0547 F7F1 div cx ; low part in AX + 0549 8BCA mov cx,dx ; CX = remainder + 054B 8BD7 mov dx,di ; high result in DX + 054D 5B pop bx + 054E 5F pop di + 054F C3 ret + + div0: + 0550 B8FFFF mov ax,-1 + 0553 8BD0 mov dx,ax + 0555 C3 ret + div1: + 0556 49 dec cx ; CX = remainder = 0 + 0557 C3 ret + + + PCMODE_DATA DSEG WORD + PC-DOS RASM-86 1.4a Source: FCBS.A86 FCB - DOS file system FCB supp Page 35 + + + + extrn fcb_pb:word + extrn fcb_path:byte + extrn fcb_path2:byte + extrn fcb_search_buf:byte + + extrn current_dsk:byte + extrn current_psp:word + extrn dma_offset:word + extrn dma_segment:word + extrn machine_id:word + extrn remote_call:word + extrn srch_buf:byte + + end + + +End of assembly. Number of errors: 0. Use factor: 23% + extrn fcb_search_buf:byte + + \ No newline at end of file diff --git a/IBMDOS/BIN/FCBS.OBJ b/IBMDOS/BIN/FCBS.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..2b3a1565301f078783330399aeb106a24e1d61a7 GIT binary patch literal 2176 zcma)7ZERE58Gg^XAO3bAK={gRw^^^+ra%)@4@&rOd~GKpj!kTCoU&n%I<=jsMxA&m z+BD1@w8WRT%aG8}tSTv_Qv*NvQEARHQFr%F0rn?l)Al2pI+|8GlLb*(APJDT0H<2$R*?FJCS z>C`}w55?uMkW2+b`*}H-YK(2&ay*$ahYio%<4A;JXzH_Fzp}v703t`Wq1OXo5s1^A zOAA(xEH>tB0nwung@PWPq&h_yaIoidP5&%6%~ITp+$!_io{KSdk^ z;aEHs&V+(}eZ+>FGKpZSrxOo7a*5mYlHuS$s3+5XFhcAN?*7!k5V6OCp`PCUaHdx# zj?lq@0i?{x$^FEd{O|VvO(&8GVmGgjMVI`+|HT5u6GuBU*^HopQlYh{hZOT`hvupDYHf4o;mCxD>4?M%dR^vCrFmD*z zd3c^2A+M4zN>9O<7;)+j#ig%R?7By>=&z?ZeHf8Lj3Q2?xI0rn1@6a?ChwB-WD;Ve zgFZ*k(G%nV?W0Vij|dQ71lZA?nTp z+X<>{ktU+8s%%5!QDq03O+{J2tsAAH<>9pxd|(RTVMQ9ZG?#XQ4k(5qc!Y?sBJ2n! z!i`vkXhy6>NQ!H$10Oc5ST9ZGfx8QVnrHb6rrG&OGX)OR1bdkdrL%Tsg{+WdgdWlYdJDF~jclO(#({|z9?oF&C)`$G zySS{+BTiGm9AFB5OAdS42E#H}+6a0~ap-AG_;(RU5I?|Jy&iG?#1vO0-n5DYyRKzz zs35J)Q_$G2iKJ%S>c{?@wUyI1M>g(D1oS<4@qP7A?Kk|DmDzM{d2*fuZJxkm)gM5D zy+IQG>uj2^+XSU^?6~oGeFE1HkjdIDq--iT0V~-+=TXozisLg=%=hW}K${3qTdaLq zyOm(SH#u6_UL(6c$&L^#`k%+e_PBUx*>ZX*$JM1?g>tA~gaGUq&F)}dfuzRWr?2O@ zxjanUL2YpYJ5HBHfdGb^J&w3kIO*Ou%uC~=-}WzAORG&W4t*yII)FH+xc+L2`jl!3 zRt9r3S@3dm-mzlOP$RZiEwaaO&UKv+qQm2zR#0Jkt3&c04-< z>3dp1=XZZ?q*cto#-56)hBarUiIGJ}6t zw$9F6^nQba!{ZveZKyw@YM&^nQMYDR09!Jo+Ne7*`KWa3MO#H-_yKY0n-m^DA};+& z#50POGll(`GmE?Pc712@t7_{cvV7QJkqB0Mey|Obgidj^t@xM4f2_H=$gs0uV~C|ymgXX1-LwChn1OG zvj;Fbe;lFtE+Z$*SzzVj?BEsOoC8*7GcDe$9vGan!sV{5IpJvO1<)x*MMSJdY{uI1 zDnxHX`;;PJw21yZVmpq*I8LDbp(6B|!Wa12&+b+Eeyp)fVZn-g);SIa8$<5uI=JYs z%n7h^X=Y}68{mJr+{@B?0AB3^z$rJrG5gqv6oMW>?8k@16{@H3 w6EYML^^8KFp4tptP^jH{seSP*65LS#b||Bj4MSbjdbNE;3NW(i|Ihz_0Cc7Cd;kCd literal 0 HcmV?d00001 diff --git a/IBMDOS/BIN/FCBS.SYM b/IBMDOS/BIN/FCBS.SYM new file mode 100644 index 0000000..1174202 --- /dev/null +++ b/IBMDOS/BIN/FCBS.SYM @@ -0,0 +1,142 @@ + 0000 VARIABLES +0000 CURRENT_DSK 0000 CURRENT_PSP 0000 DMA_OFFSET +0000 DMA_SEGMENT 0000 FCB_PATH 0000 FCB_PATH2 0000 FCB_PB +0000 FCB_SEARCH_BUF 0073 FCB_TABLE 0000 MACHINE_ID +0000 REMOTE_CALL 0000 SRCH_BUF + +0000 NUMBERS +0004 ACT_ABORT 0002 ACT_DELAY 0006 ACT_IGNORE 0001 ACT_RETRY 0005 ACT_TERM +0007 ACT_URETRY 0003 ACT_USER 000A BCB_COPIES 0014 BCB_DATA 000D BCB_DDSC +0004 BCB_DRV 0005 BCB_FLAGS 0000 BCB_NEXT 0002 BCB_PREV 0006 BCB_REC +0008 BCB_REC2 0011 BCB_REMOTE 000B BCB_SEPARATION 0040 BF_DIRTY +0008 BF_ISDAT 0004 BF_ISDIR 0002 BF_ISFAT 0080 BF_REMOTE +0007 CLASS_APPLIC 0003 CLASS_AUTHOR +000C CLASS_EXISTS 0009 CLASS_FORMAT +0005 CLASS_HARDWARE 0004 CLASS_INTERNAL +000A CLASS_LOCKED 0008 CLASS_LOST 000B CLASS_MEDIA +0001 CLASS_RESOURCE 0006 CLASS_SYSTEM 0002 CLASS_TEMP +000D CLASS_UNKNOWN 000B DATTS 0020 DA_ARCHIVE FF27 DA_CHANGE +0080 DA_CLUSTER 0080 DA_DELWATCH 0010 DA_DIR 00D8 DA_FIXED +0002 DA_HIDDEN 0001 DA_RO 0004 DA_SYSTEM 0008 DA_VOLUME 001A DBLOCK1 +0004 DCNTRL_COUNT 0000 DCNTRL_DSADD +0000 DCNTRL_DSOFF 0002 DCNTRL_DSSEG 0006 DCNTRL_LEN +0018 DDATE 001D DDSC_BLOCK 0004 DDSC_CLMSK 0005 DDSC_CLSHF +000B DDSC_DATADDR 0013 DDSC_DEVHEAD +0013 DDSC_DEVOFF 0015 DDSC_DEVSEG +0011 DDSC_DIRADDR 0009 DDSC_DIRENT +0006 DDSC_FATADDR 0018 DDSC_FIRST 001F DDSC_FREE 0021 DDSC_LEN +0019 DDSC_LINK 0017 DDSC_MEDIA 000D DDSC_NCLSTRS +000F DDSC_NFATRECS 0008 DDSC_NFATS 0001 DDSC_RUNIT +0002 DDSC_SECSIZE 0000 DDSC_UNIT 0002 DELW_DELETE +0003 DELW_FREECLU 0004 DELW_FREERD +0007 DELW_NEWDISK 000E DELW_PURGE 0000 DELW_RDMASK +0005 DELW_SPACE 000F DELW_UNDEL 0020 DHAT_BIN 0001 DHAT_CIN 0040 DHAT_CLEAN +0008 DHAT_CLK 0002 DHAT_COT 0080 DHAT_DEV 001F DHAT_DRVMSK +1000 DHAT_LOCAL 0800 DHAT_NETPRN 0004 DHAT_NUL 0040 DHAT_READY +8000 DHAT_REMOTE 4000 DHAT_TIMEOK 4000 DHM_COMMIT +0000 DHM_COMPAT 0010 DHM_DENY_ALL 0040 DHM_DENY_NONE +0030 DHM_DENY_READ 0020 DHM_DENY_WRITE 8000 DHM_FCB +0080 DHM_LOCAL 2000 DHM_NOCRIT 0000 DHM_RO 0002 DHM_RW 000F DHM_RWMSK +0070 DHM_SHAREMSK 0001 DHM_WO 0005 DHNDL_ATTR 0035 DHNDL_BLK +000B DHNDL_BLK1 0000 DHNDL_COUNT 000F DHNDL_DATE +0004 DHNDL_DATRB 001B DHNDL_DBLK 001E DHNDL_DCNTHI +001F DHNDL_DCNTLO 0007 DHNDL_DEVOFF +0007 DHNDL_DEVPTR 0009 DHNDL_DEVSEG 0028 DHNDL_EXT +0019 DHNDL_IDX 003B DHNDL_LEN 0002 DHNDL_MODE 0020 DHNDL_NAME 0015 DHNDL_POS +0017 DHNDL_POSHI 0015 DHNDL_POSLO 0031 DHNDL_PSP +002B DHNDL_SFT 0033 DHNDL_SHARE 0011 DHNDL_SIZE +0013 DHNDL_SIZEHI 0011 DHNDL_SIZELO 000D DHNDL_TIME +002F DHNDL_UID 0005 DHNDL_WATTR 0012 DMODDATE 0010 DMODTIME +0000 DNAME 0021 DOS_INT 000E DPWD 0014 DPWM 001C DSIZE +0016 DTIME 000D DUNDEL FFFB ED_ACCESS FFF4 ED_ACC_CODE +FFAB ED_ASSIGN FFEA ED_BADCMD FFE9 ED_BADDATA FFE6 ED_BADMEDIA +FFE8 ED_BADRHLEN FFE7 ED_BADSEEK FFEC ED_BADUNIT FFF7 ED_BLOCK +FFA6 ED_COMPONENT FFF3 ED_DATA FFEF ED_DEVICE FFF0 ED_DIR +FFDE ED_DISKCHG FFF9 ED_DMD FFF1 ED_DRIVE FFF6 ED_ENVIRON FFB0 ED_EXISTS +FFAD ED_FAIL FFFE ED_FILE FFF5 ED_FORMAT FFFF ED_FUNCTION +FFE1 ED_GENFAIL FFFC ED_HANDLE FFFA ED_H_MATCH FFA6 ED_LASTERROR +FFDF ED_LOCKFAIL FFAE ED_MAKE FFF8 ED_MEMORY FFCE ED_NET +FFBF ED_NETACCESS FFB3 ED_NETCOMM FFA7 ED_NETFUNC FFB1 ED_NETLOG +FFB7 ED_NETPWD FFB5 ED_NETREQ FFB2 ED_NETSRVR FFB4 ED_NETTIME FFB6 ED_NETVER +FFA8 ED_NETWRITE FFDD ED_NOFCBS FFDC ED_NOLOCKS FFE4 ED_NOPAPER +FFEB ED_NOTREADY FFA9 ED_PARAM FFAA ED_PASSWORD +FFFD ED_PATH FFED ED_PROTECT FFE2 ED_RDFAIL FFE5 ED_RNF FFEE ED_ROOM +FFE0 ED_SHAREFAIL FFAC ED_STRUCT FFE3 ED_WRFAIL FFFF ENDDIR +0FFF FAT12 FFFF FAT16 0012 FCB_MAX1 001A FCB_MAX2 001E FCB_MAX3 +0004 HCB_CLU 0006 HCB_CNT 0008 HCB_DATA 0002 HCB_DRV 0000 HCB_LINK +0049 LDT_BLK 004D LDT_DRV 0043 LDT_FLAGS 0058 LDT_LEN 0000 LDT_NAME +0045 LDT_PDT 004B LDT_ROOT 004F LDT_ROOTLEN +2000 LFLG_JOINED 8000 LFLG_NETWRKD +4000 LFLG_PHYSICAL 1000 LFLG_SUBST 0002 LOC_BLOCK 0004 LOC_CHAR +0005 LOC_MEMORY 0003 LOC_NET 0001 LOC_UNKNOWN 0FF6 MAX12 +0006 MSF_ATTRIB 000C MSF_BLOCK 001A MSF_BLOCK1 0020 MSF_CR 0014 MSF_DATE +001C MSF_DBLK 001E MSF_DCNT 001C MSF_DEVPTR 0000 MSF_DRIVE 0000 MSF_EXTFLG +0018 MSF_IFN 0019 MSF_IOCTL 0001 MSF_NAME 000E MSF_RECSIZE +0021 MSF_RR 0023 MSF_RR2 0010 MSF_SIZE 0016 MSF_TIME 0003 MS_A_READ +0004 MS_A_WRITE 000C MS_C_FLUSH 0008 MS_C_NOECHO 0007 MS_C_RAWIN +0006 MS_C_RAWIO 0001 MS_C_READ 000A MS_C_READSTR 000B MS_C_STAT +0002 MS_C_WRITE 0009 MS_C_WRITESTR 001B MS_DRV_ALLOC +001C MS_DRV_ALLOCSPEC 000D MS_DRV_ALLRESET 0019 MS_DRV_GET +000E MS_DRV_SET 0036 MS_DRV_SPACE 0010 MS_F_CLOSE +0013 MS_F_DELETE 002F MS_F_DMAGET +001A MS_F_DMAOFF 0059 MS_F_ERROR 0054 MS_F_GETVERIFY +005C MS_F_LOCK 0016 MS_F_MAKE 000F MS_F_OPEN 0029 MS_F_PARSE +0024 MS_F_RANDREC 0014 MS_F_READ 0027 MS_F_READBLK +0021 MS_F_READRAND 0017 MS_F_RENAME +0011 MS_F_SFIRST 0023 MS_F_SIZE 0012 MS_F_SNEXT +002E MS_F_VERIFY 0015 MS_F_WRITE 0028 MS_F_WRITEBLK +0022 MS_F_WRITERAND 0005 MS_L_WRITE 0048 MS_M_ALLOC 0049 MS_M_FREE +004A MS_M_SETBLOCK 0058 MS_M_STRATEGY +0062 MS_P_GETPSP 0026 MS_P_MKPSP 0050 MS_P_SETPSP +0000 MS_P_TERMCPM 0031 MS_P_TERMKEEP +0030 MS_S_BDOSVER 0033 MS_S_BREAK 0038 MS_S_COUNTRY +0035 MS_S_GETINT 0025 MS_S_SETINT +002A MS_T_GETDATE 002C MS_T_GETTIME +002B MS_T_SETDATE 002D MS_T_SETTIME 003B MS_X_CHDIR +0043 MS_X_CHMOD 003E MS_X_CLOSE 0068 MS_X_COMMIT 003C MS_X_CREAT +0047 MS_X_CURDIR 0057 MS_X_DATETIME 0045 MS_X_DUP +0046 MS_X_DUP2 004B MS_X_EXEC 004C MS_X_EXIT 0060 MS_X_EXPAND +004E MS_X_FIRST 6601 MS_X_GETCP 0044 MS_X_IOCTL 0042 MS_X_LSEEK 0039 MS_X_MKDIR +005B MS_X_MKNEW 005A MS_X_MKTEMP 004F MS_X_NEXT 003D MS_X_OPEN +003F MS_X_READ 0056 MS_X_RENAME 003A MS_X_RMDIR 6602 MS_X_SETCP +0067 MS_X_SETHC 0041 MS_X_UNLINK 004D MS_X_WAIT 0040 MS_X_WRITE +000F NUM_SHARE_STUB_ENTRIES 0022 PASSWD_CHECK +0021 PASSWD_CHMOD 0020 PASSWD_CREAT 0DDD PWM_ANY +0111 PWM_D 0222 PWM_E 00F0 PWM_GROUP 000F PWM_OWNER 0888 PWM_R +0444 PWM_W 0F00 PWM_WORLD 0010 SSTOR_SPACE 0003 STDAUX +0002 STDERR 0000 STDIN 0001 STDOUT 0004 STDPRN 0018 S_CLOSE +002C S_CLOSE_FILES 0020 S_CLOSE_IF_OPEN +0024 S_DENY_IF_OPEN 0010 S_DISCARD 000C S_FDOSRW +0028 S_GET_LIST_ENTRY 0000 S_LOCKS 001C S_OM_COMPAT +0014 S_OPEN 0008 S_RECORD 0004 S_UPDATE 0001 __RASM__ + +0000 LABELS +0550 DIV0 0556 DIV1 052F DIV_32 0254 FCB_BLOCK_RW +0271 FCB_BLOCK_RW10 0295 FCB_BLOCK_RW20 0130 FCB_CLOSE +0158 FCB_DELETE 006F FCB_ERROR 0511 FCB_FDOS 0145 FCB_FDOS_COMMON +014A FCB_FDOS_COMMON10 014C FCB_FDOS_COMMON20 0160 FCB_FIRST +03AC FCB_GET_COUNT 0333 FCB_HANDLE_ERR +033E FCB_HANDLE_ERR10 02E0 FCB_HANDLE_VFY +02F1 FCB_HANDLE_VFY10 0308 FCB_HANDLE_VFY20 +0328 FCB_HANDLE_VFY30 0091 FCB_MAKE 0168 FCB_NEXT 0099 FCB_OPEN +00AB FCB_OPEN10 00F0 FCB_OPEN20 009F FCB_OPEN_MAKE_COMMON +0341 FCB_PATH2_PREP 0357 FCB_PATH_PREP +036C FCB_PATH_PREP10 0384 FCB_PATH_PREP20 +037D FCB_PATH_PREP_COMMON 039C FCB_POINT 03AB FCB_POINT10 +0234 FCB_RANDOM_RW 024B FCB_RANDOM_RW10 019E FCB_READ +0251 FCB_READBLK 0231 FCB_READRAND 014D FCB_RENAME +04F7 FCB_RESTORE_SEARCH_STATE 01BB FCB_RW 01F8 FCB_RW10 01FA FCB_RW20 +01FE FCB_RW30 0228 FCB_RW40 048B FCB_SAVE_SEARCH_STATE 0466 FCB_SEARCH +048A FCB_SEARCH10 016E FCB_SEARCH_COMMON +0178 FCB_SEARCH_COMMON10 0444 FCB_SEEK_COMMON +0431 FCB_SEEK_RR 0410 FCB_SEEK_SEQ 01A1 FCB_SEQ_RW +01BA FCB_SEQ_RW10 0179 FCB_SETRECORD 0296 FCB_SIZE +02B5 FCB_SIZE10 02C7 FCB_SIZE20 02DD FCB_SIZE30 02DF FCB_SIZE40 04AF FCB_SSS10 +04C2 FCB_SSS20 04CC FCB_SSS30 04D0 FCB_SSS40 04E0 FCB_SSS50 0102 FCB_UPDATE +03FE FCB_UPDATE_COMMON 03E2 FCB_UPDATE_RR +03BA FCB_UPDATE_SEQ 0199 FCB_WRITE 024C FCB_WRITEBLK +022C FCB_WRITERAND 0000 FDOS_ENTRY 0000 FDOS_EXIT +0005 FDOS_EXIT10 0038 FDOS_EXIT20 +003D FDOS_EXIT30 0042 FDOS_EXIT40 0044 FDOS_FCB +0065 FDOS_FCB10 0000 IFN2DHNDL 0000 PARSE_ONE +_SE \ No newline at end of file diff --git a/IBMDOS/BIN/FDOS.OBJ b/IBMDOS/BIN/FDOS.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..6bb2b7c6514b682498297c99b446e2b495d40098 GIT binary patch literal 12032 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 literal 0 HcmV?d00001 diff --git a/IBMDOS/BIN/HEADER.OBJ b/IBMDOS/BIN/HEADER.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..7cdacdb11cd290cd691fca922a871bd020a5a5a1 GIT binary patch literal 7040 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 literal 0 HcmV?d00001 diff --git a/IBMDOS/BIN/HISTORY.LST b/IBMDOS/BIN/HISTORY.LST new file mode 100644 index 0000000..4aa0391 --- /dev/null +++ b/IBMDOS/BIN/HISTORY.LST @@ -0,0 +1,1064 @@ + PC-DOS RASM-86 1.4a Source: HISTORY.A86 Page 1 + + += 0001 __RASM__ EQU 1 + + ; File : $HISTORY.A86$ + ; + ; Description : + ; + ; Original Author : DIGITAL RESEARCH + ; + ; Last Edited By : $CALDERA$ + ; + ;-----------------------------------------------------------------------; + ; Copyright Work of Caldera, Inc. All Rights Reserved. + ; + ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, + ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. + ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES + ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF + ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO + ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE + ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE + ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, + ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, + ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, + ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF + ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT + ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND + ; CIVIL LIABILITY. + ;-----------------------------------------------------------------------; + ; + ; *** Current Edit History *** + ; *** End of Current Edit History *** + ; + ; $Log$ + ; ENDLOG + ; + ; DOSPLUS Command Line Editor Routines + ; + += include pcmode.equ += ; File : $PCMODE.EQU$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. + PC-DOS RASM-86 1.4a Source: HISTORY.A86 Page 2 + + += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += ; This file contains all the general purpose definitions += ; and equates used by the PCMODE Module. += ; += += FFFF TRUE equ 0FFFFh ; value of TRUE += 0000 FALSE equ 0 ; value of FALSE += += 0006 TRUE_VERSION equ 6 += += FFFF IDLE_DETECT equ TRUE ; Check for IDLE Process's += += if IDLE_DETECT += 0001 IDLE_COMMAND equ 0001h ; Command Processor Active += 0002 IDLE_DOSFUNC equ 0002h ; DOS Function Called += 0004 IDLE_INT28 equ 0004h ; INT 28 Called += += 4000 IDLE_ON equ 4000h ; ReSet when Idle Checking Enabled += 8000 IDLE_INIT equ 8000h ; ReSet when $IDLE$ Loaded and Active += C000 IDLE_DISABLE equ IDLE_INIT + IDLE_ON += += 0001 PROC_IDLE equ 0001 ; Process is IDLE += 0002 PROC_INT28 equ 0002 ; INT28 Polling Loop += 0003 PROC_KEYIN equ 0003 ; Keyboard Input += 0004 PROC_DEVIN equ 0004 ; Device Input Routine += endif += += += 00C0 STACK_SIZE equ 192 ; Local Stack Size (Levels) += 0050 MAX_PATHLEN equ 80 ; Maximum Path length += 000D MAX_FILELEN equ 13 += += ; + PC-DOS RASM-86 1.4a Source: HISTORY.A86 Page 3 + + += ; DOS process termination Codes += ; += 0000 TERM_NORMAL equ 0 ; Normal Termination += 0001 TERM_BREAK equ 1 ; Termination by Control Break += 0002 TERM_ERROR equ 2 ; Termination by Critical Error += 0003 TERM_RESIDENT equ 3 ; Terminate and Stay Resident += += ; += ; Critical Error responses from the default INT 24 handler and += ; the DO_INT24 routine. += ; += 0000 ERR_IGNORE equ 0 ; Ignore Error += 0001 ERR_RETRY equ 1 ; Retry the Operation += 0002 ERR_ABORT equ 2 ; Terminate the Process += 0003 ERR_FAIL equ 3 ; Fail Function += ; += 0008 OK_FAIL equ 0000$1000b ; Fail is a Valid Response += 0010 OK_RETRY equ 0001$0000b ; Retry is a Valid Response += 0020 OK_IGNORE equ 0010$0000b ; Ignore is a valid Response += 0038 OK_RIF equ 0011$1000b ; All Responsese are Valid += 0030 OK_RI equ 0011$0000b ; Retry and Ignore are Valid += 0018 OK_RF equ 0001$1000b ; Retry and Fail are Valid += ; += 0040 NO_CRIT_ERRORS equ 0100$0000b ; critical error shouldn't be generated += ; warning - must match FDOS.A86 += ; + PC-DOS RASM-86 1.4a Source: HISTORY.A86 Page 4 + + += eject += ; The following equates define the format in which the users registers += ; are saved on the stack. This format is also seen by an application += ; when a critical error occurs. += ; += CodeMacro POP$DOS ; Pop User Registers a la MS-DOS += db 058h ! db 05Bh ; pop AX ! pop BX += db 059h ! db 05Ah ; pop BX ! pop CX += db 05Eh ! db 05Fh ; pop SI ! pop DI += db 05Dh ; pop BP += db 01Fh ! db 007h ; pop DS ! pop ES += EndM += += CodeMacro PUSH$DOS ; Push User Registers += db 006h ! db 01Eh ; push ES ! push DS += db 055h ; push BP += db 057h ! db 056h ; push DI ! push SI += db 052h ! db 051h ; push DX ! push CX += db 053h ! db 050h ; push BX ! push AX += EndM += += 0000 reg_AX equ word ptr .00 += 0000 reg_AL equ byte ptr .00 += 0001 reg_AH equ byte ptr .01 += += 0002 reg_BX equ word ptr .02 += 0002 reg_BL equ byte ptr .02 += 0003 reg_BH equ byte ptr .03 += += 0004 reg_CX equ word ptr .04 += 0004 reg_CL equ byte ptr .04 += 0005 reg_CH equ byte ptr .05 += += 0006 reg_DX equ word ptr .06 += 0006 reg_DL equ byte ptr .06 += 0007 reg_DH equ byte ptr .07 += += 0008 reg_SI equ word ptr .08 += 000A reg_DI equ word ptr .10 += 000C reg_BP equ word ptr .12 += += 000E reg_DS equ word ptr .14 += 0010 reg_ES equ word ptr .16 += += 0012 reg_IP equ word ptr .18 += 0014 reg_CS equ word ptr .20 += 0016 reg_FLAGS equ word ptr .22 += += ; Processor Flags += 0001 CARRY_FLAG equ 0001h ; Carry Flag += 0040 ZERO_FLAG equ 0040h ; Zero Flag += 0080 SIGN_FLAG equ 0080h ; Sign Flag + PC-DOS RASM-86 1.4a Source: HISTORY.A86 Page 5 + + += 0200 INT_FLAG equ 0200h ; Interrupt Flag += 0400 DIR_FLAG equ 0400h ; Direction Flag += 0800 OFLW_FLAG equ 0800h ; OverFlow Flag += += 0000 DMD_ID equ es:byte ptr .0 ; id code ('M' or 'Z') += 0001 DMD_PSP equ es:word ptr .1 ; owner of memory block += 0003 DMD_LEN equ es:word ptr .3 ; length of memory block += 0006 DMD_IDLE_FLAGS equ es:word ptr .6 ; idle flags live here += 0008 DMD_NAME equ es:byte ptr .8 ; ASCIIZ name field += 0008 DMD_NAME_LEN equ 8 ; 8 Bytes long += 004D IDM equ 'M' ; not last id code += 005A IDZ equ 'Z' ; last id code += += PCMCODE GROUP PCM_HEADER, PCM_CODE, BDOS_CODE, PCM_RODATA += PCMCODE GROUP PCM_HISTORY, PCM_ICODE, PCM_CODEND += += PCM_HEADER CSEG PARA += PCM_CODE CSEG BYTE += PCM_RODATA CSEG WORD += BDOS_CODE CSEG WORD += PCM_HISTORY CSEG BYTE += PCM_ICODE CSEG BYTE += PCM_CODEND CSEG PARA += += += PCMDATA GROUP PCMODE_DATA, FDOS_DSEG, FIXED_DOS_DATA += PCMDATA GROUP PCMODE_CODE, GLOBAL_DATA, BDOS_DATA, PCMODE_DSIZE += += PCMODE_DATA DSEG WORD ; DOS Data += FDOS_DSEG DSEG WORD COMMON ; FDOS Parameter Block +=0000 fdos_data rw 7 += FIXED_DOS_DATA CSEG WORD 'DATA' ; Fixed DOS Data Area += PCMODE_CODE CSEG WORD 'DATA' ; DATA relative CODE += GLOBAL_DATA DSEG WORD ; GLOBAL DOS DATA (Process Independant) += BDOS_DATA DSEG WORD ; BDOS Data Area += PCMODE_DSIZE DSEG PARA ; End of DOS Data Area + += include i:msdos.equ += ; File : $MSDOS.EQU$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES + PC-DOS RASM-86 1.4a Source: HISTORY.A86 Page 6 + + += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += += += 0000 MS_P_TERMCPM equ 00H += 0001 MS_C_READ equ 01H += 0002 MS_C_WRITE equ 02H += 0003 MS_A_READ equ 03H += 0004 MS_A_WRITE equ 04H += 0005 MS_L_WRITE equ 05H += 0006 MS_C_RAWIO equ 06H += 0007 MS_C_RAWIN equ 07H += 0008 MS_C_NOECHO equ 08H += 0009 MS_C_WRITESTR equ 09H += 000A MS_C_READSTR equ 0aH += 000B MS_C_STAT equ 0bH += 000C MS_C_FLUSH equ 0cH += 000D MS_DRV_ALLRESET equ 0dH += 000E MS_DRV_SET equ 0eH += 000F MS_F_OPEN equ 0fH += 0010 MS_F_CLOSE equ 10H += 0011 MS_F_SFIRST equ 11H += 0012 MS_F_SNEXT equ 12H += 0013 MS_F_DELETE equ 13H += 0014 MS_F_READ equ 14H += 0015 MS_F_WRITE equ 15H += 0016 MS_F_MAKE equ 16H += 0017 MS_F_RENAME equ 17H += 0019 MS_DRV_GET equ 19H += 001A MS_F_DMAOFF equ 1aH += 001B MS_DRV_ALLOC equ 1bH += 001C MS_DRV_ALLOCSPEC equ 1cH += 0021 MS_F_READRAND equ 21H += 0022 MS_F_WRITERAND equ 22H += 0023 MS_F_SIZE equ 23H + PC-DOS RASM-86 1.4a Source: HISTORY.A86 Page 7 + + += 0024 MS_F_RANDREC equ 24H += 0025 MS_S_SETINT equ 25H += 0026 MS_P_MKPSP equ 26H += 0027 MS_F_READBLK equ 27H += 0028 MS_F_WRITEBLK equ 28H += 0029 MS_F_PARSE equ 29H += 002A MS_T_GETDATE equ 2aH += 002B MS_T_SETDATE equ 2bH += 002C MS_T_GETTIME equ 2cH += 002D MS_T_SETTIME equ 2dH += 002E MS_F_VERIFY equ 2eH += 002F MS_F_DMAGET equ 2fH += 0030 MS_S_BDOSVER equ 30H += 0031 MS_P_TERMKEEP equ 31H += 0033 MS_S_BREAK equ 33H += 0035 MS_S_GETINT equ 35H += 0036 MS_DRV_SPACE equ 36H += 0038 MS_S_COUNTRY equ 38H += 0039 MS_X_MKDIR equ 39H += 003A MS_X_RMDIR equ 3aH += 003B MS_X_CHDIR equ 3bH += 003C MS_X_CREAT equ 3cH += 003D MS_X_OPEN equ 3dH += 003E MS_X_CLOSE equ 3eH += 003F MS_X_READ equ 3fH += 0040 MS_X_WRITE equ 40H += 0041 MS_X_UNLINK equ 41H += 0042 MS_X_LSEEK equ 42H += 0043 MS_X_CHMOD equ 43H += 0044 MS_X_IOCTL equ 44H += 0045 MS_X_DUP equ 45H += 0046 MS_X_DUP2 equ 46H += 0047 MS_X_CURDIR equ 47H += 0048 MS_M_ALLOC equ 48H += 0049 MS_M_FREE equ 49H += 004A MS_M_SETBLOCK equ 4aH += 004B MS_X_EXEC equ 4bH += 004C MS_X_EXIT equ 4cH += 004D MS_X_WAIT equ 4dH += 004E MS_X_FIRST equ 4eH += 004F MS_X_NEXT equ 4fH += 0050 MS_P_SETPSP equ 50H += 0054 MS_F_GETVERIFY equ 54H += 0056 MS_X_RENAME equ 56H += 0057 MS_X_DATETIME equ 57H += 0058 MS_M_STRATEGY equ 58h += 0059 MS_F_ERROR equ 59H += 005A MS_X_MKTEMP equ 5aH += 005B MS_X_MKNEW equ 5bH += 005C MS_F_LOCK equ 5cH += 0060 MS_X_EXPAND equ 60H += 0062 MS_P_GETPSP equ 62H + PC-DOS RASM-86 1.4a Source: HISTORY.A86 Page 8 + + += 6601 MS_X_GETCP equ 6601h += 6602 MS_X_SETCP equ 6602h += 0067 MS_X_SETHC equ 67h += 0068 MS_X_COMMIT equ 68h += += 0021 DOS_INT equ 21h ; DOS Entry Point += ; += 0000 STDIN equ 0 ; Standard Console Input Handle += 0001 STDOUT equ 1 ; Standard Console Output Handle += 0002 STDERR equ 2 ; Standard Error Output += 0003 STDAUX equ 3 ; Auxilary Device Handle += 0004 STDPRN equ 4 ; Printer Device Handle + += include i:char.def += ; File : $CHAR.DEF$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += ;************************************************; += ;* *; += ;* Character Definitions *; += ;* *; += ;************************************************; + PC-DOS RASM-86 1.4a Source: HISTORY.A86 Page 9 + + += += 0001 CTLA equ 'A' - '@' += 0002 CTLB equ 'B' - '@' += 0003 CTLC equ 'C' - '@' += 0004 CTLD equ 'D' - '@' += 0005 CTLE equ 'E' - '@' += 0006 CTLF equ 'F' - '@' += 0007 CTLG equ 'G' - '@' += 0007 BELL equ 'G' - '@' += 0008 CTLH equ 'H' - '@' += 0009 CTLI equ 'I' - '@' += 0009 TAB equ 'I' - '@' += 000A CTLJ equ 'J' - '@' += 000A LF equ 'J' - '@' += 000B CTLK equ 'K' - '@' += 000D CTLM equ 'M' - '@' += 000D CR equ 'M' - '@' += 0010 CTLP equ 'P' - '@' += 0011 CTLQ equ 'Q' - '@' += 0012 CTLR equ 'R' - '@' += 0013 CTLS equ 'S' - '@' += 0014 CTLT equ 'T' - '@' += 0015 CTLU equ 'U' - '@' += 0016 CTLV equ 'V' - '@' += 0017 CTLW equ 'W' - '@' += 0018 CTLX equ 'X' - '@' += 0019 CTLY equ 'Y' - '@' += 001A CTLZ equ 'Z' - '@' += 001B ESC equ '[' - '@' += 001C CTLBS equ '\' - '@' += 001F CTLUB equ '_' - '@' += 001E CTLUP equ '^' - '@' += 007F DEL equ 07Fh += 007F RUBOUT equ DEL += += 005E CTL equ '^' + += include i:cmdline.equ += ; File : $CMDLINE.EQU$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES + PC-DOS RASM-86 1.4a Source: HISTORY.A86 Page 10 + + += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += += FFFE RL_INPUT equ word ptr -2[bp] ; READ_LINE Input Handle += FFFC RL_OUTPUT equ word ptr -4[bp] ; READ_LINE Output Handle += FFFA RL_BUFSEG equ word ptr -6[bp] ; Retained line Segment += FFF8 RL_BUFOFF equ word ptr -8[bp] ; Retained line Offset += FFF8 RL_BUFPTR equ dword ptr -8[bp] ; Retained line Buffer += FFF6 RL_INICOL equ word ptr -10[bp] ; initial column += FFF4 RL_FLAGS equ word ptr -12[bp] ; Control Flags += FFF2 RL_MAXLEN equ word ptr -14[bp] ; Maximum Buffer Size += FFF0 RL_KANJI equ word ptr -16[bp] ; Kanji Character Buffer += FFEE RL_SAVMAX equ word ptr -18[bp] ; Size of retained data += FFEC RL_SAVPOS equ word ptr -20[bp] ; Current Position in data += FFEA RL_HIST_RECL equ word ptr -22[bp] ; We recall from here += FFE8 RL_HIST_SAVE equ word ptr -24[bp] ; We save to here += FFE6 RL_HIST_SIZE equ word ptr -26[bp] ; buffer is this big += FFE4 RL_HIST_SEG equ word ptr -28[bp] ; buffer is at this segment += 001C RL_LENGTH equ 28 += += 0001 RLF_ENHANCED equ 0000$0001b ; Enhanced features are on += 0002 RLF_INS equ 0000$0010b ; Insert Flag += 0004 RLF_SEARCH equ 0000$0100b ; Search mode on += 0008 RLF_MATCH equ 0000$1000b ; We are matching a command += 0010 RLF_RECALLED equ 0001$0000b ; Line already recalled += 0020 RLF_DIRTY equ 0010$0000b ; Partial line needs saved += 0040 RLF_KANJI equ 0100$0000b ; RL_KANJI is valid += 0080 RLF_INROOT equ 1000$0000b ; In root += += 0001 CHAR_SPACE equ 0000$0001b ; Space Character += 0002 CHAR_TAB equ 0000$0010b ; Tab Character += 0004 CHAR_CTL equ 0000$0100b ; Control Character expanded to "^X" += 0008 CHAR_KANJI equ 0000$1000b ; Japanese Kanji character += 0010 CHAR_ALPHAN equ 0001$0000b ; Alpha/Numeric += 0020 CHAR_OTHER equ 0010$0000b ; Non AlphaNumeric + PC-DOS RASM-86 1.4a Source: HISTORY.A86 Page 11 + + += 0080 CHAR_STD equ 1000$0000b ; Stored as a Byte displayed in 1 Col += += 008E CHAR_SIZE equ CHAR_STD or CHAR_KANJI or CHAR_TAB or CHAR_CTL += 0031 CHAR_ONECOL equ CHAR_SPACE or CHAR_OTHER or CHAR_ALPHAN + + + + + PCM_HISTORY CSEG + + public init_history, save_history + public del_history_buffers, del_cur_history_buffer + public prev_cmd, next_cmd, match_cmd, search_cmd + public prev_word, next_word, match_word + public goto_eol + public del_bol + public deln_word + + extrn next_char:near + extrn save_line:near + extrn space_out:near + extrn bs_out:near + extrn goto_bol:near + extrn del_eol:near + extrn del_line:near + extrn char_info:near + extrn put_string:near + extrn prev_w20:near + extrn deln_w10:near + + init_history: + ;------------ + ; On Entry: + ; SS:BP -> history structure + ; On Exit: + ; SS:SP filled in with appropriate history buffer + ; Preserve DX + ; + 0000 1E push ds + 0001 06 push es + 0002 16 push ss + 0003 07 pop es + 0004 8D7EE4 lea di,RL_HIST_SEG ; point at history buffer variables + 0007 BE0000 E mov si,offset histbuf1 ; assume root buffer + 000A F746F48000 test RL_FLAGS,RLF_INROOT ; root task after all? + 000F 7503 0014 jnz init_history10 ; if not we need to switch + 0011 BE0000 E mov si,offset histbuf2 ; application buffer + init_history10: + 0014 A5 movsw ; copy the seg + 0015 AD lodsw ; get overall length + 0016 2D0400 sub ax,2*WORD ; last two words contain pointers + 0019 AB stosw ; save the working length + PC-DOS RASM-86 1.4a Source: HISTORY.A86 Page 12 + + + 001A 96 xchg ax,si ; SI -> saved buffer positions + 001B 8E5EE4 mov ds,RL_HIST_SEG ; in the buffer segment + 001E A5 movsw ; update save and + 001F A5 movsw ; recall positions + 0020 07 pop es + 0021 1F pop ds + 0022 C3 ret + + + save_history: + ;------------ + ; We are exiting from READLINE - if line has been modified save the + ; current line and update our pointers. + ; + 0023 85D2 test dx,dx ; skip update of sav/recall pointers + 0025 7421 0048 jz save_history30 ; if empty line + 0027 E83700 0061 call save_current ; save away current command line + 002A 8B7EE8 mov di,RL_HIST_SAVE ; start with the old one + 002D E89F01 01CF call find_current_hist ; wrap it if we need to + 0030 E86701 019A call find_next_null ; find end of "new" command + 0033 47 inc di ; onto next character + 0034 3B7EE6 cmp di,RL_HIST_SIZE ; do we need to wrap ? + 0037 7202 003B jb save_history10 + 0039 33FF xor di,di ; wrap the line + save_history10: + 003B 897EE8 mov RL_HIST_SAVE,di ; update "save" pointer + 003E F746F42000 test RL_FLAGS,RLF_DIRTY ; if a line has been changed we'd + 0043 7403 0048 jz save_history30 ; better update "recall" pointer + 0045 897EEA mov RL_HIST_RECL,di ; too + save_history30: + 0048 1E push ds + 0049 06 push es + 004A 161F push ss ! pop ds + 004C 8D76E8 lea si,RL_HIST_SAVE ; point at history buffer variables + 004F 8E46E4 mov es,RL_HIST_SEG + 0052 8B7EE6 mov di,RL_HIST_SIZE + 0055 A5 movsw ; save the "save" pointer + 0056 A5 movsw ; and the "recall" one + 0057 07 pop es + 0058 1F pop ds + 0059 C3 ret + + save_current_if_dirty: + ;--------------------- + 005A F746F42000 test RL_FLAGS,RLF_DIRTY ; if data is dirty (ie. user modified) + 005F 7436 0097 jz save_current20 ; then save it + save_current: + ;------------ + ; Copy current buffer contents to next free location in history buffer + ; + 0061 56 push si + 0062 57 push di + PC-DOS RASM-86 1.4a Source: HISTORY.A86 Page 13 + + + 0063 52 push dx + 0064 3B56E6 cmp dx,RL_HIST_SIZE ; is history buffer big enough ? + 0067 732B 0094 jae save_current10 ; no, skip saving this line + 0069 E81201 017E call find_free_hist ; Find the next bit of space + 006C 5951 pop cx ! push cx ; CX = chars to save + 006E E324 0094 jcxz save_current10 ; none, forget about it + 0070 1E push ds + 0071 06 push es + 0072 C576F8 lds si,RL_BUFPTR + 0075 8E46E4 mov es,RL_HIST_SEG + 0078 F3A4 rep movsb ; and save the data. + 007A 33C0 xor ax,ax ; Null terminate it. + 007C AA stosb + 007D 07 pop es + 007E 1F pop ds + 007F 57 push di + 0080 E81701 019A call find_next_null ; Find the end of the entry we just + 0083 8BCF mov cx,di ; overwrote - if any remains zap it + 0085 5F pop di + 0086 FC cld + 0087 33C0 xor ax,ax ; Null terminate this entry + 0089 2BCF sub cx,di ; Figure out number of zeros to write + 008B 7607 0094 jbe save_current10 + 008D 06 push es + 008E 8E46E4 mov es,RL_HIST_SEG + 0091 F3AA rep stosb ; and pad to the next entry + 0093 07 pop es + save_current10: + 0094 5A pop dx + 0095 5F pop di + 0096 5E pop si + save_current20: + 0097 C3 ret + + + ; + ; Here is the code to deal with history buffers + ; + ; match_cmd Does a string search based on what the user has typed so far + ; search_cmd Matches string, but doesn't change match state + ; prev_cmd Retrieves the previous command from the history buffer + ; next_cmd " " next " " " " " + ; + match_cmd: + 0098 A00000 E mov al,@hist_flg ; is matching enabled ? + 009B 250800 and ax,RLF_MATCH + 009E 7408 00A8 jz search_cmd ; no, always match + 00A0 3146F4 xor RL_FLAGS,ax ; toggle match bit + 00A3 8546F4 test RL_FLAGS,ax ; turning matching off ? + 00A6 7458 0100 jz match30 ; then just exit + search_cmd: + 00A8 8976EC mov RL_SAVPOS,si ; any chars to save ? + PC-DOS RASM-86 1.4a Source: HISTORY.A86 Page 14 + + + 00AB 85F6 test si,si + 00AD 7452 0101 jz prev_cmd ; blank line - just get previous + 00AF E8A8FF 005A call save_current_if_dirty ; save current line if it needs saving + 00B2 56 push si ; save current offset in line + 00B3 57 push di + 00B4 52 push dx ; Save index to end of current line + 00B5 8BD6 mov dx,si ; discard rest of line if no match + 00B7 8B7EEA mov di,RL_HIST_RECL ; Point to the current entry + match_loop: + 00BA E8ED00 01AA call find_prev_hist ; DI-> previous cmd in buffer + 00BD 57 push di ; save this command position + 00BE 8B7EEA mov di,RL_HIST_RECL ; get starting position + 00C1 E80B01 01CF call find_current_hist ; handle any wrapping + 00C4 5E pop si ; recover previous command + 00C5 3BFE cmp di,si ; have we been all round ? + 00C7 7414 00DD je match_error ; YES - We've looped so no match found + 00C9 1E push ds + 00CA 56 push si ; save this entry + 00CB 8E5EE4 mov ds,RL_HIST_SEG + 00CE 8B7EF8 mov di,RL_BUFOFF ; ES:DI -> match string + 00D1 8B4EEC mov cx,RL_SAVPOS ; try to match CX characters + 00D4 F3A6 repe cmpsb + 00D6 5F pop di ; recover this entry + 00D7 1F pop ds + 00D8 75E0 00BA jne match_loop ; try again if we didn't match + 00DA E86C00 0149 call copy_from_hist ; if it did match copy it + match_error: + 00DD 59 pop cx ; Get end of displayed line + 00DE 5F pop di ; user's buffer + 00DF 5E pop si + 00E0 56 push si ; save current position in lines + 00E1 E80000 E call space_out ; Rub the displayed line out + 00E4 E80000 E call bs_out ; And backspace to it's start + 00E7 E84E00 0138 call goto_eol ; display the line + 00EA E80000 E call goto_bol ; Move cursor to begining + 00ED 59 pop cx ; CX = end of matched portion + 00EE 894EEC mov RL_SAVPOS,cx ; CX = Current position in command + 00F1 E307 00FA jcxz match20 + match10: ; Move cursor forward to current + 00F3 51 push cx ; position + 00F4 E80000 E call next_char ; next_char destroys our loop count + 00F7 59 pop cx ; so keep it + 00F8 E2F9 00F3 loop match10 + match20: + 00FA 8B4EEE mov cx,RL_SAVMAX ; we can't copy any more + 00FD 894EEC mov RL_SAVPOS,cx + match30: + 0100 C3 ret + + + prev_cmd: + ; Get the previous command from the buffer + PC-DOS RASM-86 1.4a Source: HISTORY.A86 Page 15 + + + 0101 F746F41000 test RL_FLAGS,RLF_RECALLED ; is this the 1st recall ? + 0106 750D 0115 jnz prev_cmd10 + 0108 51 push cx + 0109 57 push di + 010A 8B7EE8 mov di,RL_HIST_SAVE ; get existing "save" ptr + 010D E8BF00 01CF call find_current_hist ; wrap it if we need to + 0110 897EEA mov RL_HIST_RECL,di ; and update "recall" pointer + 0113 5F pop di + 0114 59 pop cx + prev_cmd10: + 0115 E842FF 005A call save_current_if_dirty ; save current line if it needs saving + 0118 E80000 E call del_line ; then delete it + 011B 56 push si + 011C 57 push di + 011D 8B7EEA mov di,RL_HIST_RECL ; point to the current entry + 0120 E88700 01AA call find_prev_hist ; DI -> previous entry + 0123 EB0E 0133 jmps found_cmd ; now go and copy it to the user buffer + + next_cmd: + ; Get the next command from the buffer + 0125 E832FF 005A call save_current_if_dirty ; save current line if it needs saving + 0128 E80000 E call del_line ; then delete it + 012B 56 push si + 012C 57 push di + 012D 8B7EEA mov di,RL_HIST_RECL ; point to the current entry + 0130 E89600 01C9 call find_next_hist ; DI -> next entry + ; jmps found_cmd ; now go and copy it to the user buffer + + found_cmd: + 0133 E81300 0149 call copy_from_hist ; Copy from history to user buffer + 0136 5F pop di + 0137 5E pop si + ; jmp goto_eol ; Display new line. + + goto_eol: ; Move the cursor to the end of the + 0138 8BCA2BCE mov cx,dx ! sub cx,si ; displayed line + 013C E30A 0148 jcxz goto_e10 ; Already at the EOL + 013E 0376F8 add si,RL_BUFOFF ; Get the Offset in the buffer + 0141 E80000 E call put_string ; Output the sub_string + 0144 03F9 add di,cx ; Update the local variables + 0146 8BF2 mov si,dx ; and return + goto_e10: + 0148 C3 ret + + ; DI-> Current entry in history buffer + ; + copy_from_hist: + 0149 814EF41000 or RL_FLAGS,RLF_RECALLED ; remember we have recalled something + 014E 8166F4DFFF and RL_FLAGS,not RLF_DIRTY ; this entry is already in buffers + 0153 897EEA mov RL_HIST_RECL,di ; update pointer for next time + 0156 E84100 019A call find_next_null ; how big is this entry ? + 0159 8BCF mov cx,di + PC-DOS RASM-86 1.4a Source: HISTORY.A86 Page 16 + + + 015B 8B76EA mov si,RL_HIST_RECL + 015E 2BCE sub cx,si ; (CX-SI)=No of bytes to copy + 0160 3B4EF2 cmp cx,RL_MAXLEN ; is the line bigger than our buffer ? + 0163 7203 0168 jb copy_from_hist1 ; if so we want to clip it + 0165 8B4EF2 mov cx,RL_MAXLEN ; to the maximum possible value + copy_from_hist1: + 0168 8BD1 mov dx,cx + 016A 1E push ds + 016B 8E5EE4 mov ds,RL_HIST_SEG + 016E 8B7EF8 mov di,RL_BUFOFF + 0171 F3A4 rep movsb ; copy to line buffer + 0173 1F pop ds + 0174 E80000 E call save_line ; save the line + 0177 8B4EEE mov cx,RL_SAVMAX ; we can't copy any more + 017A 894EEC mov RL_SAVPOS,cx + 017D C3 ret + + ; Some primitives for history buffer handling: + ; + ; find_free_hist Find the next free entry in the history buffer + ; find_next_null Finds the end of the current entry + ; find_prev_hist Finds the start of the previous entry + ; find_next_hist Finds the start of the next entry + ; find_current_hist Finds the start of current entry + + ; + ; Make DI-> next entry of sufficient length for the current cmd buffer + ; If we can't fit at the end zero the remainder of the buffer then wrap + ; back to the start. + ; + + find_free_hist: + 017E 8B7EE8 mov di,RL_HIST_SAVE ; Point at current last entry + 0181 57 push di ; Will DX bytes fit? + 0182 03FA add di,dx + 0184 3B7EE6 cmp di,RL_HIST_SIZE ; Did we run out of buffer? + 0187 5F pop di + 0188 720F 0199 jb find_free_hist20 + 018A 33C0 xor ax,ax ; doesn't fit, so zero to end of buffer + find_free_hist10: + 018C 06 push es + 018D 8E46E4 mov es,RL_HIST_SEG + 0190 AA stosb ; keep on zeroing + 0191 07 pop es + 0192 3B7EE6 cmp di,RL_HIST_SIZE + 0195 72F5 018C jb find_free_hist10 + 0197 33FF xor di,di ; wrap back to start of history buffer + find_free_hist20: + 0199 C3 ret + + ; Entry DI-> entry in the history buffer + ; Make DI-> next NULL in the history buffer ( end of current entry ) + PC-DOS RASM-86 1.4a Source: HISTORY.A86 Page 17 + + + ; + find_next_null: + 019A 8B4EE6 mov cx,RL_HIST_SIZE + 019D 2BCF sub cx,di ; Calc no of bytes left + 019F 33C0 xor ax,ax ; Look for next terminator + 01A1 06 push es + 01A2 8E46E4 mov es,RL_HIST_SEG + 01A5 F2AE repnz scasb + 01A7 4F dec di ; point at the NUL + 01A8 07 pop es + 01A9 C3 ret + + ; Entry DI-> entry in the history buffer + ; Make DI-> previous entry in the history buffer + ; Preserve CX + find_prev_hist: + 01AA E82200 01CF call find_current_hist ; handle any wrapping + 01AD 8BC7 mov ax,di ; AX = entry we want previous for + find_prev_hist10: + 01AF 50 push ax ; save current offset + 01B0 57 push di ; save initial offset + 01B1 97 xchg ax,di ; find next from here until + 01B2 E81400 01C9 call find_next_hist ; we get back where we started + 01B5 97 xchg ax,di ; AX = current offset + 01B6 5F pop di ; recover initial value + 01B7 5B pop bx ; recover previous offset + 01B8 3BC7 cmp ax,di ; have we wrapped yet ? + 01BA 740A 01C6 je find_prev_hist20 ; yes, BX = previous entry + 01BC 77F1 01AF ja find_prev_hist10 ; we are above target so continue + 01BE 3BDF cmp bx,di ; we are below target - if previous + 01C0 73ED 01AF jae find_prev_hist10 ; was above target we are OK + 01C2 3BC3 cmp ax,bx ; if new below previous then we + 01C4 73E9 01AF jnb find_prev_hist10 ; have ERROR wrap, so stop + find_prev_hist20: + 01C6 8BFB mov di,bx ; DI -> Previous entry + 01C8 C3 ret + + find_next_hist: + 01C9 E80300 01CF call find_current_hist ; handle any wrapping + 01CC E8CBFF 019A call find_next_null ; point to end of current entry + ; jmp find_current_hist ; handle any wrapping + + find_current_hist: + ; This routine is complicated by the need to handle switchers, where + ; our buffers and pointers may get out of step + 01CF 06 push es + 01D0 33C0 xor ax,ax + 01D2 8E46E4 mov es,RL_HIST_SEG ; now work backwards to start of line + find_current_hist10: + 01D5 83FF01 cmp di,1 ; are we at the start of the buffer + 01D8 7211 01EB jb find_current_hist30 ; then don't wrap + 01DA FD std + PC-DOS RASM-86 1.4a Source: HISTORY.A86 Page 18 + + + 01DB AE scasb ; is previous char a NUL ? + 01DC FC cld ; (it should be!) + 01DD 75F6 01D5 jne find_current_hist10 + 01DF 47 inc di ; ES:DI -> 1st char of line + find_current_hist20: + 01E0 8B4EE6 mov cx,RL_HIST_SIZE + 01E3 2BCF sub cx,di ; CX= Remaining no: of bytes in buffer + 01E5 7604 01EB jbe find_current_hist30 + 01E7 F3AE repe scasb ; skip over zero's + 01E9 7503 01EE jne find_current_hist40 + find_current_hist30: + 01EB BF0100 mov di,1 ; wrap to start of buffer + find_current_hist40: + 01EE 4F dec di + 01EF 07 pop es + 01F0 C3 ret + + del_history_buffers: + ;------------------- + ; Delete contents of both history buffers + ; + 01F1 A10000 E mov ax,histbuf1 ; Segment of 1st history buffer + 01F4 8B0E0000 E mov cx,histsiz1 ; End of 1st history buffer + 01F8 E80F00 020A call zap_buffer + 01FB A10000 E mov ax,histbuf2 ; Segment of 2nd history buffer + 01FE 8B0E0000 E mov cx,histsiz2 ; End of 2nd history buffer + 0202 EB06 020A jmps zap_buffer + + del_cur_history_buffer: + ;---------------------- + ; Delete contents of the current history buffer + ; + 0204 8B46E4 mov ax,RL_HIST_SEG ; zero the current buffer + 0207 8B4EE6 mov cx,RL_HIST_SIZE + zap_buffer: + 020A 06 push es ; zero fill CX bytes at AX:0 + 020B 57 push di + 020C 8EC0 mov es,ax + 020E 33C0 xor ax,ax + 0210 8946EA mov RL_HIST_RECL,ax + 0213 8946E8 mov RL_HIST_SAVE,ax + 0216 33FF xor di,di + 0218 F3AA rep stosb ; zero fill the buffer + 021A 5F pop di + 021B 07 pop es + 021C E80000 E call del_line ; then delete current line + 021F E90000 E jmp save_line + + + next_word: + 0222 8BCA mov cx,dx ; Calculate the number of bytes + 0224 2BCE sub cx,si ; left to scan + PC-DOS RASM-86 1.4a Source: HISTORY.A86 Page 19 + + + 0226 E314 023C jcxz next_w10 ; Skip if at the EOL + 0228 56 push si ; Save the current Index + 0229 8BF7 mov si,di ; Scan from the current location + 022B E80F00 023D call match_word ; Get the next word boundary + 022E 8BCE mov cx,si + 0230 2BCF sub cx,di ; Calculate the string length + 0232 8BF7 mov si,di ; to be displayed from the current + 0234 E80000 E call put_string ; location and output the data + 0237 5E pop si + 0238 03F1 add si,cx ; Update the Index and Offset pointers + 023A 03F9 add di,cx + next_w10: + 023C C3 ret + + ; + ; MATCH_WORD scans the buffer at ES:SI for word boundaries + ; and returns to the calling routine whenever it detects such + ; a boundary. + ; + ; On Entry: ES:SI Buffer Address + ; CX Maximum No of bytes to Scan + ; + ; On Exit: ES:SI Next Word Boundary + ; + match_word: + 023D E80000 E call char_info + 0240 F6C418 test ah,CHAR_ALPHAN or CHAR_KANJI + 0243 E0F8 023D loopnz match_word ; scan the rest of the current word + 0245 E314 025B jcxz match_w30 ; end of word or kanji ? + + 0247 52 push dx + match_w10: + 0248 8BD6 mov dx,si + 024A E80000 E call char_info + 024D F6C418 test ah,CHAR_ALPHAN or CHAR_KANJI + 0250 E1F6 0248 loopz match_w10 + 0252 7406 025A jz match_w20 + 0254 2BF2 sub si,dx ; Correct the count in CX + 0256 03CE add cx,si ; and return the location of the + 0258 8BF2 mov si,dx ; word boundary + + match_w20: + 025A 5A pop dx + match_w30: + 025B C3 ret + + prev_word: + 025C 8BCEE3FB 025B mov cx,si ! jcxz match_w30 ; Initialize the count + 0260 525657 push dx ! push si ! push di + 0263 8B76F8 mov si,RL_BUFOFF ; Scan from the begining of the buffer + 0266 8BD6 mov dx,si ; keeping the last match in DX + prev_w10: + PC-DOS RASM-86 1.4a Source: HISTORY.A86 Page 20 + + + 0268 E8D2FF 023D call match_word ; Find the next word boundary + 026B E304 0271 jcxz prev_w15 ; Stop when we get to the current offset + 026D 8BD6 mov dx,si ; Save current location + 026F EBF7 0268 jmps prev_w10 ; and repeat + prev_w15: + 0271 E90000 E jmp prev_w20 + + del_bol: ; Delete to the begining of the line + 0274 0BF6740C 0284 or si,si ! jz del_bol10 ; Ignore if at the begining + 0278 0BD27408 0284 or dx,dx ! jz del_bol10 ; Or the line is empty + 027C 57 push di ; Save the current index + 027D E80000 E call goto_bol ; Move to the start of the line + 0280 59 pop cx ; Restore the current offset + 0281 E90000 E jmp deln_w10 ; and jump to common code + del_bol10: + 0284 C3 ret + + deln_word: + 0285 8BCA mov cx,dx ; Calculate the number of bytes + 0287 2BCE sub cx,si ; left to scan + 0289 E3F9 0284 jcxz del_bol10 ; Skip if at the EOL + 028B 56 push si ; Save the current Index + 028C 8BF7 mov si,di ; Scan from the current location + 028E E8ACFF 023D call match_word ; Get the next word boundary + 0291 8BCE mov cx,si + 0293 5E pop si + 0294 E90000 E jmp deln_w10 + + PCMODE_DATA DSEG WORD + + extrn @hist_flg:byte ; To select between histbufs 1 or 2 + + GLOBAL_DATA dseg word + + extrn histbuf1:word, histsiz1:word, histbuf2:word, histsiz2:word + + end + + +End of assembly. Number of errors: 0. Use factor: 15% + pop si + 0294 E90000 \ No newline at end of file diff --git a/IBMDOS/BIN/HISTORY.OBJ b/IBMDOS/BIN/HISTORY.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..97e100f9c3e04071878ef19379b3dad711e39221 GIT binary patch literal 1664 zcmYLH{cBrg6h3cml6!By`mwrAk+yCY2C=d>x>bT=n%p-HrZ?S9dee52%M^5=2zF_P zBB8@uT)nRN(>A2wgmsLn`@uiJ6%rXJv{-S!Zkk!|+HSD6cCDMcp7-8#gM2*aoaa2} zdC&Wfi@^7#vbl^h{MzZK0YHgm`#XCMwRgSv(y{ig?#}*Wqn$m6o6i0Y;E{%MO3WS4 zBqUEZ7mL5)PQ-GtCqIFKct6&(L^d@d2^eUMYV*b3L?){-x`S9jWQ-I;K8E_FSVB_# z$#kYSmbR&On$_h*h^B_5g!Wj3+9)d}{W~*JnqjSen4LUp=P}Pl+j>fdL6%}A^E?m7 z0R#_OL398>>F%4{I`7NInvINU*5kIE(TD;}5 zJXV7hw7ixWm~!KNjoyPE)eOf-FBwlrq-3ckJ z#Rrugg4R1osie4FglCoBOuFbIyBMsmvrfp~BSaifB-Ivr(?vuX--I3P!@!w=%RY|- zvr*FZ#jua2bSuj^p_)J%;mUMNElpw+vZKU2Q-Bfx#SF%DxKqM7eI-SF+% zslu(98NRJDu~>Z0JPbzJG`}Y1yCfMcFO9k))@0elo^~j5ljUX9X**Lgr|2!CykxgI zwL@xNiKM+NgI>ul_QAW$Hi5 zOnpG`RO=VpP_6C@?c}+C@nW>mhR7US+APnm>7R&IG32H2f|FdklHn`nJ}|BgqVtFHTDDtUAMw|Y-@^EZ3X{(gn>nEo@pz|~| z&WxDk${2T*0IGh2UP8Fl2B@PIuYr$2Uh?Lr<|1>Gba|4R5o>)`#V6(dS=2oo*@6`$Z*erU(YuvoCHc~O>YY!Clqv;N)`tbdPRKD7x za@D=6U~j31hV*{w*HtR&Z&UI1g;yZ>mMd?Rwoq)*s=1BpEBDcWf3q0yFBXM7P8i0x mVmsPqj=r;u`2wbv*bOvNkNzwT>g}{akI;rsK6e2WpZOoZVm&zk literal 0 HcmV?d00001 diff --git a/IBMDOS/BIN/HISTORY.SYM b/IBMDOS/BIN/HISTORY.SYM new file mode 100644 index 0000000..c65306a --- /dev/null +++ b/IBMDOS/BIN/HISTORY.SYM @@ -0,0 +1,91 @@ + 0000 VARIABLES +0000 @HIST_FLG 0000 DMD_ID 0006 DMD_IDLE_FLAGS 0003 DMD_LEN +0008 DMD_NAME 0001 DMD_PSP 0000 FDOS_DATA 0000 HISTBUF1 0000 HISTBUF2 +0000 HISTSIZ1 0000 HISTSIZ2 0001 REG_AH 0000 REG_AL 0000 REG_AX +0003 REG_BH 0002 REG_BL 000C REG_BP 0002 REG_BX 0005 REG_CH +0004 REG_CL 0014 REG_CS 0004 REG_CX 0007 REG_DH 000A REG_DI +0006 REG_DL 000E REG_DS 0006 REG_DX 0010 REG_ES 0016 REG_FLAGS +0012 REG_IP 0008 REG_SI FFF8 RL_BUFOFF FFF8 RL_BUFPTR FFFA RL_BUFSEG +FFF4 RL_FLAGS FFEA RL_HIST_RECL FFE8 RL_HIST_SAVE +FFE4 RL_HIST_SEG FFE6 RL_HIST_SIZE FFF6 RL_INICOL +FFFE RL_INPUT FFF0 RL_KANJI FFF2 RL_MAXLEN FFFC RL_OUTPUT FFEE RL_SAVMAX +FFEC RL_SAVPOS + +0000 NUMBERS +0007 BELL 0001 CARRY_FLAG 0010 CHAR_ALPHAN 0004 CHAR_CTL +0008 CHAR_KANJI 0031 CHAR_ONECOL 0020 CHAR_OTHER 008E CHAR_SIZE +0001 CHAR_SPACE 0080 CHAR_STD 0002 CHAR_TAB 000D CR 005E CTL +0001 CTLA 0002 CTLB 001C CTLBS 0003 CTLC 0004 CTLD +0005 CTLE 0006 CTLF 0007 CTLG 0008 CTLH 0009 CTLI +000A CTLJ 000B CTLK 000D CTLM 0010 CTLP 0011 CTLQ +0012 CTLR 0013 CTLS 0014 CTLT 0015 CTLU 001F CTLUB +001E CTLUP 0016 CTLV 0017 CTLW 0018 CTLX 0019 CTLY +001A CTLZ 007F DEL 0400 DIR_FLAG 0008 DMD_NAME_LEN +0021 DOS_INT 0002 ERR_ABORT 0003 ERR_FAIL 0000 ERR_IGNORE 0001 ERR_RETRY +001B ESC 0000 FALSE 0001 IDLE_COMMAND +FFFF IDLE_DETECT C000 IDLE_DISABLE +0002 IDLE_DOSFUNC 8000 IDLE_INIT 0004 IDLE_INT28 4000 IDLE_ON +004D IDM 005A IDZ 0200 INT_FLAG 000A LF +000D MAX_FILELEN 0050 MAX_PATHLEN 0003 MS_A_READ +0004 MS_A_WRITE 000C MS_C_FLUSH 0008 MS_C_NOECHO 0007 MS_C_RAWIN +0006 MS_C_RAWIO 0001 MS_C_READ 000A MS_C_READSTR 000B MS_C_STAT +0002 MS_C_WRITE 0009 MS_C_WRITESTR 001B MS_DRV_ALLOC +001C MS_DRV_ALLOCSPEC 000D MS_DRV_ALLRESET 0019 MS_DRV_GET +000E MS_DRV_SET 0036 MS_DRV_SPACE 0010 MS_F_CLOSE +0013 MS_F_DELETE 002F MS_F_DMAGET +001A MS_F_DMAOFF 0059 MS_F_ERROR 0054 MS_F_GETVERIFY +005C MS_F_LOCK 0016 MS_F_MAKE 000F MS_F_OPEN 0029 MS_F_PARSE +0024 MS_F_RANDREC 0014 MS_F_READ 0027 MS_F_READBLK +0021 MS_F_READRAND 0017 MS_F_RENAME +0011 MS_F_SFIRST 0023 MS_F_SIZE 0012 MS_F_SNEXT +002E MS_F_VERIFY 0015 MS_F_WRITE 0028 MS_F_WRITEBLK +0022 MS_F_WRITERAND 0005 MS_L_WRITE 0048 MS_M_ALLOC 0049 MS_M_FREE +004A MS_M_SETBLOCK 0058 MS_M_STRATEGY +0062 MS_P_GETPSP 0026 MS_P_MKPSP 0050 MS_P_SETPSP +0000 MS_P_TERMCPM 0031 MS_P_TERMKEEP +0030 MS_S_BDOSVER 0033 MS_S_BREAK 0038 MS_S_COUNTRY +0035 MS_S_GETINT 0025 MS_S_SETINT +002A MS_T_GETDATE 002C MS_T_GETTIME +002B MS_T_SETDATE 002D MS_T_SETTIME 003B MS_X_CHDIR +0043 MS_X_CHMOD 003E MS_X_CLOSE 0068 MS_X_COMMIT 003C MS_X_CREAT +0047 MS_X_CURDIR 0057 MS_X_DATETIME 0045 MS_X_DUP +0046 MS_X_DUP2 004B MS_X_EXEC 004C MS_X_EXIT 0060 MS_X_EXPAND +004E MS_X_FIRST 6601 MS_X_GETCP 0044 MS_X_IOCTL 0042 MS_X_LSEEK 0039 MS_X_MKDIR +005B MS_X_MKNEW 005A MS_X_MKTEMP 004F MS_X_NEXT 003D MS_X_OPEN +003F MS_X_READ 0056 MS_X_RENAME 003A MS_X_RMDIR 6602 MS_X_SETCP +0067 MS_X_SETHC 0041 MS_X_UNLINK 004D MS_X_WAIT 0040 MS_X_WRITE +0040 NO_CRIT_ERRORS 0800 OFLW_FLAG 0008 OK_FAIL 0020 OK_IGNORE +0010 OK_RETRY 0018 OK_RF 0030 OK_RI 0038 OK_RIF 0004 PROC_DEVIN +0001 PROC_IDLE 0002 PROC_INT28 0003 PROC_KEYIN 0020 RLF_DIRTY +0001 RLF_ENHANCED 0080 RLF_INROOT 0002 RLF_INS 0040 RLF_KANJI +0008 RLF_MATCH 0010 RLF_RECALLED 0004 RLF_SEARCH 001C RL_LENGTH +007F RUBOUT 0080 SIGN_FLAG 00C0 STACK_SIZE 0003 STDAUX 0002 STDERR +0000 STDIN 0001 STDOUT 0004 STDPRN 0009 TAB 0001 TERM_BREAK +0002 TERM_ERROR 0000 TERM_NORMAL 0003 TERM_RESIDENT +FFFF TRUE 0006 TRUE_VERSION 0040 ZERO_FLAG 0001 __RASM__ + +0000 LABELS +0000 BS_OUT 0000 CHAR_INFO 0149 COPY_FROM_HIST +0168 COPY_FROM_HIST1 0000 DELN_W10 0285 DELN_WORD 0274 DEL_BOL +0284 DEL_BOL10 0204 DEL_CUR_HISTORY_BUFFER 0000 DEL_EOL +01F1 DEL_HISTORY_BUFFERS 0000 DEL_LINE 01CF FIND_CURRENT_HIST +01D5 FIND_CURRENT_HIST10 01E0 FIND_CURRENT_HIST20 +01EB FIND_CURRENT_HIST30 01EE FIND_CURRENT_HIST40 +017E FIND_FREE_HIST 018C FIND_FREE_HIST10 +0199 FIND_FREE_HIST20 01C9 FIND_NEXT_HIST +019A FIND_NEXT_NULL 01AA FIND_PREV_HIST +01AF FIND_PREV_HIST10 01C6 FIND_PREV_HIST20 0133 FOUND_CMD +0000 GOTO_BOL 0148 GOTO_E10 0138 GOTO_EOL 0000 INIT_HISTORY +0014 INIT_HISTORY10 00F3 MATCH10 00FA MATCH20 0100 MATCH30 +0098 MATCH_CMD 00DD MATCH_ERROR 00BA MATCH_LOOP 0248 MATCH_W10 +025A MATCH_W20 025B MATCH_W30 023D MATCH_WORD 0000 NEXT_CHAR 0125 NEXT_CMD +023C NEXT_W10 0222 NEXT_WORD 0101 PREV_CMD 0115 PREV_CMD10 0268 PREV_W10 +0271 PREV_W15 0000 PREV_W20 025C PREV_WORD 0000 PUT_STRING +0061 SAVE_CURRENT 0094 SAVE_CURRENT10 +0097 SAVE_CURRENT20 005A SAVE_CURRENT_IF_DIRTY +0023 SAVE_HISTORY 003B SAVE_HISTORY10 +0048 SAVE_HISTORY30 0000 SAVE_LINE 00A8 SEARCH_CMD 0000 SPACE_OUT +020A ZAP_BUFFER + 0100 MATCH30 +0098 MATCH_CMD 00DD MATCH_ERROR 00BA MATCH_LOOP 0248 MATCH_W10 +025A MATCH_W20 025B MATCH_W30 023D MATCH_WO \ No newline at end of file diff --git a/IBMDOS/BIN/IBMDOS.COM b/IBMDOS/BIN/IBMDOS.COM new file mode 100644 index 0000000000000000000000000000000000000000..4bb8498765b73fd42fe97c4dee02841109bae173 GIT binary patch literal 30081 zcmZU*3qVw5-ar1#IWuR50S1`C@!AY3PAY~bMFk_GB4{cXNkCBCTeq$DGMpo|T^zy- zGY4qJw%UDn-xbl;09|a^8nYGjkd$SqwME%QLF+ktT@6VG@@ zlEf(QNUq1~9m(5h@Q(aUGRYTdr%r7qqrz0aA%*v*rA4_Uq5fk_LmFQ{k8g1Ewe50; zt09rNs_pa0Hes`&;j*Fn7=G;B3gx7VJOFN|8I@} zW;q`vjjR7Us^NUpSVbgbKu0vkw^2n#C3oyak&@J|42=Bw&wq9ZH#->JH=P?53VAJg z7mnRHUdFK(MHfYIP4L-E0+P>95*ATSrIrQLj=+5Va{rq!6Gmb_advUys zV>gan{HUeyht?XMfBDN_%J}}SK_%&o|MOEliQ4PdzlJ(WF6CSuzlu=&9WU*;`Fw|* zNoq4KN-G!ST6H51VYS0ZpU|;UuC`AL^SR=}h8*M3|HF&K+m;Kt`K#%p>)UjkXMCHH zbIDneNvB=@LjB_Y?k%SWB`!%TE-5mWSziohxa9FJc@xs)=v^HfgofR`&+;3kvMKO4pHwNmp^dy-n-u(2IhrVwF9e zC@t~w&_PYRy1)O_a``G`nW9BsnJFM@n!Lipe$cbH^viKF8o0tnxS!zf)28rcoyN%sL|)Kbrj zroIkdVzedX<`vMI8+{!*(UcG3qZKzwKrWJr?m@5D^SPyK(Z>7$*?eO5s3l;Pc=~Vi zO^!NQD4<52#~R=XqgEY}_<%mdV@r)CN{c?owV3iNFFNGUlaCo4$-Y8Ma&=*JvMs{a_gOb73QEnV4DN@*63HCX1^8?W&SGLUKdmgPl;tEmB z&u`|=(7QFUfIgJs$pdW|h)J{sTrnr+mPL3$ZKHvBTnCeXEM1!264@t!{K3vF>^p39 zSgy*8k)ftVvX;=slFE+AqLLz~!npf#LjN8C7M2@`Lvcm+v8VTvx|bjl=<^Xfvxu_V ze{%Hrr`K#4 z?|2K`ta_=%x1Iw7eKGtsFJ^O@s(x*uewOtPQWhcP(>E+7Ml`}RJyeYOW-(DX=Qw#w zBcIeBDp3BEo(orN!UM}f72T^7x%sDAUFk2vI~*_bN{3?(fAf>kp-(1Prg;oR;tmLO zQuvRpYUI@g;nWmfnYN2}ivsJ&JkklN4>jaddfEJAw%qvNxYLWuBXi@U++0z)pFGLoXcr2@v-U;Xy)9n7@I`u=d zLU)9+u#QDPQ!DXA*1yclklQpaTz%E7{yoy?*v+du%=BS1K1P>oo*@0n;NA)-iR>HS znYXL5dE2M0X>_O$r_2@;U1Sakf0pk7Grir++OwLlske9>dBh7P0_ndvuSzO-gupg+Nr{k-vq{`*hwjAyM@X&5~m7ScR$ z*YGmrGlsH!GELSzcKY(b=61;vs(F%`HB-IEtffJWkuD;+<*P~UJ6z41+eH(d znJ8V$3|`6h4zCl<-r>2T!F5c(E;Da+0i8%ni`TZ6P@%6Z0uRXoNV{*;XCu^2VFiIm z>xsD=c;OAJhJ%_QiuEL^y-}eMgoI$|^otsc4(LCm3XKh8owJ7gr^RR>^@g$bsm?G* ztz#ZvIUHNYABrWiWj;xGcViUe|26ltXubObBbt<#?=ZGaAV?%eS1M5`HJGHeE~AfK zuWc{!B+2h?LpHg88yHA+`!*q&)OIC&TBhgUO*&K1ySubSli%%a+|nl*T9?y%t~=E> zlT$quPMGWX}db0oM#ZhVf;=ZGLsqo$x>UQ)g(NO2l|7474 z>G~T7IY=qGpdat@Z$4i@=+YY{o?9XB`V^fsZpU6OfDVgpO;37@wwo zidwG~sVU)f*vJaZAO{~Xxpgg(p0ER%q9J%E?J;6Vj|ppe`!V4G9z^vZi05Gt)+77^ zD=7b)S*mhs*&;#lv(Zu2jL~vrHjdPK$bx3NrM zO2}$+{a#)P35ANZbV9VUsKk2n-HEb&+TC=AQJrB_yRUbG3x*SQg|WWT>>c7f9||WSn<9Sa zso)MJFe64yuysOn)`-B0bRHB)@1CrzJ$vj!)4^tQg&N1xbm5H@zT#V4 zEfEgmcZdXp_3C>Dw0B=aJn!09<+_#MtNs2p7D2` z>N(Z(mUC>}FlH`{o%(ujyl$7qDLZkXlG8*xtPcTmRlQ;i(UafqCTgxBbX|pO&LNksEyvcrIj>81aF+tGvGh#UI_DGwiMQ~u(#3szOLuOa{AIt z$(Y&m`SQl>=EmT^{U^=mMSV+LD5v|U9;5qr<$U}GC9hDh7~6if69ja1zZiDFbanrr z$hqT;8`dhA(g)u(@|M*Qak>1?0zMeYrnDu1`!_Jg)S*{r>gk)r6O%`ipxnL2Q-h8^ zeI3J(0r%b*Uq0X+OfB#Aj;5Ah@(%sHT+LgJCOjv+0U{0X!Bg~OLhrp^{~Dhv+{a5g zrQtq4U4A<~>GUBZ>F=$w7w}1^H2%aPfPk` zZ#<@JSk1qXbmm|LNlbmwy>p{}$&&8tr-D_EJbne{T>_p}4s%j;|1o$`%%?7$x|EsP zFXeAv^R*S;;fS(@{-ZDT9pR;L?2UgJApSXYi}5;L2W`RCo5 zq}x%)IAOZzUbY35m+f`d7iGuuR#--5VRmQI8EPkT>17I-IzHM$e zySayWl3EOH2f`0dAaoA#xLSm^bKwVJvN?%oVvDh@C*q)$FtsM4Mb}nmJvfC>18nS3 zO>yMstuA!Xg*xMg;b?-zB8>(nQ8FpcFQW*o~`!Q-0gmop?| zqigr_v%LzvWlm%FMWv38o8v#J9@43imn#Pio`IL-%OTPA#EMKYm|Y2*Jk*z!!|a0f z=N|~FU1qR5)yewg4hO7q*%DhH?F z$rRGNdu^pUWutX|dv9Yf;-G=h`8xSnQ*~F9-C6&+hw)xiWfzjB(6LaC~hz<4&g$|=UiXNNYes%u_BOD4!%Y7$OMz5BDP?Fz*tIoHM zD{+QyPz_&>{=aSt1>7*9Ls#oOIeh}hbD~8)lAwsDWpWqQbn>V00=XJs+0(1KqV!;V zD6x(6-0G^=kyPQdrMlf?lI>lV)T15_PBx#Nc^M<3)p;6>jHfhqeN4EQH>gf7l=l;z zCkO+TC$vmgGC#mmxKDhZQTBW0RY1Qq)*I5R*qAVC0zAsUG{+HQh4Z(d7 z55c{j?2Xw^XIEzLYxxC8ZBlYp*)m59%NZhN%we9q$ zI!}y1FA-zv5$Uq4%1%gtFMBK-aE&9I)e!t_qh9E^2`)q{ut8N<4RuP)#

#NBEO{;B}PJyioD{7S;P*yzSSjAI?P(B~B2lat|ZP2I$1~u6dPkJ7xJ>s=+ygsR~ z4St|6iD!+gG7ZH`b7ApSw~w{|eGeyJK`%^ZqaaA(?4%PTQ$HvRt3E0ZdR-hpOm8FT zFOR*tJr&iFT0^C>gy~X4@a0ev`GYJ`Uwd>wk>4LwT;4Q7R!M#M1~2d=y%v?e`D_|h zHJVR6lW$hV8mfiSwTqBNE*%CW`0oLulKQE5tILmGa`_x^a=_t2R?!wM)N!s(w3tA# zU+(fDy+SK*RJSjK$8aYh?o|+h#bT%*l#aBSyg%($-tTbn{>15geLT;|vN|K$_mmmL z>07A>YasB67D6Tn^dTbY6-c8o|J^DO)L@fBR}(0>nv&cntl-l_o>PYaMp#g2clwfN zLPed;3o|wm?|Xq{?wE_mrIf?h4|7vHwdDk>ZkePg6hgX_K)4%n1CAE8p ziJ0ge=EVs#EZDFsG~KsB^@sX{iOZ&WARp#+Jij201Pr8%Ysts-mAl%$-buF-PimFr zUVgz@O^Q8qPGk1-0x7*8>iBPncz1B}g0D0wf<0X=TJb(OW31f{n0tqYwIt1lPW7eD z=G#0w83$>DV8iqNE+~VE{-wHIx3UuljSwe(*K{7nqpYVt0A4dhR*dX6L z;HW(#e@3?o)m^;Oz!7Jskj@jLPT|~MaN~z`(22vLOD}WlHfE?{D#T>}QVyC$FLe*O z-jej_5tBe?8j9`CvA|DfCgzE&;sJ2={|*2#r>~Y68;zLLZ}^6Eep$mZURX^Z3|NQhx9plf(f z?BO&$J*KCTV`_6lI#C-2)!#z#MW$UMpPCUN8JFS0mjS_ULuib0#M9TKXyzV}`?mmn96XLti-kA|gbiVs6wMShtI=n)$ z=zQyQG{~0U@HEj-bPV%&0+W)Rkd|MrretJ6 zI26nJWjxGTO!e@PVFFXPbrLPUz$#!sOLda7veP1GL@!&`v_sCYG&yR!*w>sjV(h-A zJ?b0KN13s(+O=~Xq1hLUMebD%H;)p!h~2!V$xlTWf+oI~_%;$*j0TTqVO$#T%_!J>wF{7|Tlp}w1#lOu2(sf8XyAoJRR-TblmhO0v&8k|LV2vy1kxXy8nez$()ng2_C$zv3EDzLxNMOZ4Ymk zqC#exY?(u9kH~{Pc}eXDiB}%Dy1!?cE5#u7=P<&2r*Bcd{3-ucrD8i39Q*S*JUorz zOFZ$I2ziALp|;&Ae~{ECkAhchSPO$Ky$M-+cMm9mK5bCRXVmZxS9vsAJ}!R-iOAn) z_LT7JBH(S(G$s$d;$-==N+q2h;yjB%A}s#$PmaFIRd+dq7P^Nk3rqbBljqNzXF3Lt z@A5e^F!wWg#ACc^B9D-StRx&c7)|&i4U72_g+4|+x5}3Hqk8OlN$<$^vrz%Em>%t3 z>xtP8lh701DJ$#i%!8V{FAGZ^S|Jc15Q*0%gzX_QV9cLE~S`@8kBCZYXB$8%m)8 zviS_NMJNQD;=rxjyrlMM?{0)#-jaj>CQKy3l{tXf!V_qQLSgOE7n$j^dpm4qqf(y^ zCW+~*?`KzCbfm8`Z61qx;T8m0+kP++WG4^wHU+KB5rB!{V4}W8wC>sCWM7w)Gk7GT z^@H`lfnGU>U|g#eC{nbu-(y{pPc5W?&LX8Wml$2(Tu@_Rsc*E>f{7B}9P9-_eg}e7 zgX*^T6W(90w3!HdKanO+l)@S-wdgX-?%;Qg?nKBlE!xwghonOX=zSfXi=y(=?csazqLyoskLsc7h~e2I^p9&vyFHvXIp@XG({3VoBdfE>2NSMrR)AZa^iI-g+H}@)%hnEmH)6eA>AnnoQoAq1 zoWBx zXIt-8OV0Mdq53KOoOx%RV?x&->5`XnkTlURGRKKYoDy)xs6Qq0&|w23y52pq#X@M< zwWN0S=%2TFoT><53gqR_IIg^`)KeSwAn z8{V@7xO<%+43Bt6tYV&bBt~519f=mFdq?1sTA;gEY+AtGD>i#a>=4TT<{k8rb6TPr zJ$RfWZgbh?lV`uH?azStXlrRF(X>q`suJr1j}pCC5tMDfzVILP-$M zhe~c;m%pxL-R5)O{HU)QzHxcCTQ8KFORc37OJ|f0 z1~h_^{9l;D>kWOKUIefO@OS1aQ~aeS{tSOcQU7>W&NR8_B8s)ny-r!(%E<+AV0~Gv zIPknSlhDV{(tm!H+aY)j;P;4QvCh*X#bE`r&TnXb$+@fE%#>gRC{|*3 zX@o3u`Ig=e2U=b})1v95sT)d5);@FrI@3zv@VvO`Q3z)b)B#lq+F9@DvLwHBGt%X1F?#O8R^Ffyz#y zxJaRGU!jl`A&ZnbD$`)2h~slxi~7#LmFy<`%$W~wf?to}w$g_t&q?1H>7XmW zV&8L?a|7^)L53W>z`w%;2p5dDh zrt>H;{maA42#bk&MHiSwP1*`WL5*nceYsS!yL`!iGPtT8e>V7^(tAHR>+O#l2%6ry zgZa+h8$|5U^!*~%M*or41&p82f1P0`r8O;h8K{re#X+@oVeo={EPYVY4Jdv*$_Re! zpznS0mavRepK&U%|CFrK1*L!Z!{it8cEmpa?2cbP|IGGfrSz3A8b&QXJBd<&l*les zG%%pl{-dy~P0+aw@I&A70q_rBj0&@2MujvWrRKySdK%*}9-1Aak`V`e@QYCk-dWP3 zoC&8ts2mb%vUpS1;8pmPlq7R@uJazDmrd=N-o&LbFMU$p7 z`?V|GyC6fdr!Lh=F$hWb-_JYc&$i!8=uB!yT42^HFHZ55j{34k7BBV{3{+$5R*~e$-cbRhk)`RwQR$YiKmf z&kVS#)@ZBwp_a%-`jo!7Kl2*$@$}Ut@`d#Z6rqnp*)-AQ^4=3Eaq@?B883f~BH_t; zK%XdEZmmBwtA2*IX)LEXvEPWXO-C>*}i1>N| zJ+Y)H^;p^dT$-vY3SLh{3|c!C{HwxPjldU>dZ$5XSfmR*(KMT&np3JT@p3Gd58{4)dmaE{!c&?`7^^zI(n zQ0nAAyjeKEwWE=x;(H5N0;rOu+lJ`J+_oWghzoU+FY_`jQv2aM{y2C&;c7v`GXwo!^8IuX2m20OqB!A7!XQfY zOi-%`t9y^0{~+j4!u!Nw`bR=rHMIT;K2@_yNB^Q5`&1rUMbIkw)1rK^>`=#CPUuWH zneaBIAav!@4S4nejX`~Sj7a>UZre~v!l&}P^pb9^dP&!rd6BT_-#F?3DbiLQ{a8mo z(J=yJ4TNG_dNH;1QrWme!#ck7qTh&-VxQLgAJi>cq|3gjti~JpT|WDw{2_cp(ej5# zGfI}QMBgt7Uaa_bSm!IaSgfG-0zEORnhD*j^%!PlUkpyiL%?cQ5O!ntZM;a+Nslp) z{%v$^H*}!vO9|N*D+kFlv$c)aLWGewM&A!5mT(Fc*mk^FnN@Hx z>78P5`mvcSAMbHg40?%&hi2@{zQjDM4&z%J2ik^p(2<#Qm7dnr^EX;1Vf@wLNJ|Jb z)-%#tfmqUlRu0jmyIOzm9w*-Jjumff)w|<7x8i=D$LYRj<1Ow*p7HMDjpGpSiE{sL zW2D>bF}9lMGZv9+-KoIS{65MOy9so!dLRUkm5>990MP*?!Aq453f~vBJ&FJ@DYKm?d~sK zs{l?l4z-LyZ6i_du!!{BmQt!CMZ)U5g2G(6bmRwoUczTZ8%oy}8=)tFw5g%%EdX|y z>_``H4Pl$?#+rg_u47po-~>j83n(WSP)@GSEGy=A=H0+E(UYIZrK5D$r>!J0MR3&v zOSk9KRvl&m`jp65_uYnQ$YglQ%IuESxc~%r@%V$*w*D8D9fGVdWTD)ptiGRXy`LMp zpIh*t{^*1Hgokvc59$B;kp9v``ky?kKlHHhikJWPm)zhlxjP==pM69hc!YfWi0+n0 zb^m%6uqwmTkLq83l;l6AJNTIXi^l}xuk?TZm2l%%!asj4n0~8Y`CCIWb2mRH#M&x5 z^rb~Um(^C=WjD4>vF&SuP_)}16erkj*3JK1>(BqmTwIfEy?X@bF`>Z>jMXkPurE&n z;|!P1Y@23}wbjqI$tdWs!`6{zx5=U8au>dYh%bBb7Rt@e4!#t)qy;~Qk{vu1xS<8# z3w);qJK^dJ9;MT!)B82LCWaoFEiI?F-j-XF{EhX+gW*u%TcR7GRm4K8D5bZJM-0%F z=$RrXm)m?9lX7X*Jo>wNMf8CvS~d^vM^p%IuX5Wl;|2P&d1}4pP5Z{0DE29|eH!I8 z+8a$b%oeBjWratJakM?E%t5b3(3P|4&!cGOY`T6tO|sHi^VHktsU@2FGc9mgQ>SZc zj>b%bNgDm#H2Sa6PT?ftUma-<8~rrWbAc|M?m0`3MtHuYFIwoIqASzz8ffg()`pY7 zz>O=LK=($AHv07}@wL#0Tj+H=^+tL2*5my@r+Ln}K*Y$eS>nQ>pPA^)BD09EECe^kf80o=U|V^p7!A3a5`o!oVuG({)jO zsH6$1#K+OWIQrU5aWajw(Rdq8vC)5xW8*4kO`<0gXk8+zsY_r_Y8D>;#u_4&`gj|# z7`DA#qOjK_PJGoH5!aY7MmYdVUyY@CiA5#qiWpVCL4OxVS47YQarFBU8XE%$7yTvz zmAE>NerBNyW{Qh;#@i}4S>TP2;QCI+3lS4GXN5}u0N4^v@8uy}k7wvHmO9Z07^7&9 zzr0r`=_`&mnse*ul4=$sxIN5tIky2>p2)#W9ffgGOfWR0Qj&~(w#keLH z+9Xpd{4TT5bH{{M8}PvBGHEXJf6cZv#M>0rV296Kp~<0Q;qq&9z%9H7pA$kvRF;Ck7=dnCtqx&r40&0(_lW~Kw zZjEw#A-F6%eKw5OsKqmz@fRvNXkduGX`=fhXpBpmOy7x+1lcmp*2AjwoBqS<^yY+fzAOuTZwO)rrd^$y72AJu`bp6kVoSQZu)er}Sm|LnEM}s}_2Akd{V!Zj&8xw$x9{WV^q30V=+;5{S{UuT#gh)=UDAJ)c%=#WO&90UGy&n?;ND}hf%~Ja&PY!95$3^rSor1 zdZ*QZ;bNoZ1F;SvczYNG0hpndo!J*nCkX!#xgb2XEMrhoVqC9u-qfmWmxy2LjlB0T@Ab25Knt&7U zm0}jTd{Mb{D5j_ujdN9HOvtPpjrDZGt1y}V-bni<(>n&}-2$C!Dzkv|?Ydy?6rQjl zXgozNw;f^t3i@x$zB;EDR`+Fkbuu*!&{ff6w7&C#b+26-4=!nQS4l?tTDWKoPNj0V zG({~Qpy|`a0VMe^{^wxa?;EHIhxLV!Hlyv0@+UvAU8HQRf5O%TS=5B+8k5X@!Ud~W z6y%IaIXO*mFZb>#rP&s{^WZqh2sR}!2^wq4?R)lQX71Ue{?nw;mm=t!lju+T>BcG_KcuIIn!|*27r#`%RZQhElS^L3!D;2{zdwvWvaJ6K zUd7;5cu~@6%u{}!9P3J08eaJsNqWcSe@uV!yE5Y<=5h^QcU7%2q$6o0;Lg6Kw=BaC zly^rTqu47PT|LW_yX$W@VD-IeP8%mhf+K-7I_XQ(1124Fm{qw>+YX(u0VNLh>dUfr zV3IWK#awB$bqFpzu~cV8)3Do~FusJCG3!8eQ6F76kwzQn>(?C}$skNwPtTad7!cg% zcJa6LtZB|7@5L06hur?9iL+@^ocEgv}&^O-jfM-N@KdKV^&k3d;zrjG)1v%JUJxTHB4MjMUpg%amCHZJMDK--+s zgY5QB5dJ-1S)qiQlG^%hhSw~BqqM({Iwc?uHc_>W}RnxF2#b@ly;u1+U7`G2R z{1`)os@Chs$R^-e&I3f9;lxZ&6+X2pw8un^<7sm*ebrP6eodq(OvtE)X-r3nWP*sv zY%r&w5fisQoXy4u4Q-IkQ6R)f&0&tZxtJmZhCI|uf7(m$*LhsDm@k_O`P=Z36}f+$ z{`3_G@U#mri24SHO$mIVsoQ$#PxxJ@t?Ku)sdv1`j;Xr@jM)-8M`JmZ-x%*)rWEAo z0#fPkO5O+75t*Wt_oeiBuBNoBaHH#rN=g;^6R=`XaJc+Q7Cos+SF(bagjWYW`&i-(@nRC6GHOb>M+(U1i1i$xgR=p6klen|JaH? z9V}t-6>y0#z{J#ytFUbphVbbx6ks8=j2cT}Lt6}zU7+tGK-J7@wu#=*OSgd$4l3C~ z!Okih9U14D%&IawYn5brX_+fEYdM7X3;><7mg6I(7;HBY7lXFa=@H&@4+=@CNP{&N zCtjdW@#0LZD|*3HYApLiD8Ogmo>FQQV?!0UgdUswaz;CR*yB)>>#42}w zZH05-n1HgB!o1wJudR(^9n=U1aoapwZzH62qOEA{h5^8e02+aQ^RzAny|>vIgjQpq z8b4=|Cn`C_+e}$mfWDo!0)5G30R#bS@%`}gApF_jETXQk;EGc3=e5ZH81<~PMkSI>v4*uy?hmQBbpSCAYih&yOHv&T zHqUW-<(7mqslp#@p0=G(*G^6W{tK)QMBumkY%N+kecI-k3FRT9{qbJ-6;ldVNx?C# zG9ni^;CEeg>qzn1B3Ek8a_Mv^FQd0XF+N0>iBeREvwdupgw(7_gHj|E$z5Gm*qor} z0R=C&0Ll0$5z}h!f}kj5L4~_8Ra+7p3o%ADSSLA-6s2}bIu?&Dad{USfRh0yRtoql zi?Y4$xN}3Ly}K2ad=Iah7nX7Vrxi!ML_WeFU64-7zk%nM9|B8Zu3x8o{P0z)($Irx z3<^fS{?MQFFB8QCnvUg9^ofZH@6hKbic|bX_XV*R)MpLNAQg2^6?&}F*+>m@J7$F5 zxIud_0b48GqOKXlG)Iw)@)rVvZN7O8HepmM(>}5i3Bd+DY)RZN84sF641{qkBRxLy z#@AMPC`;CZG%dTmBZ-o3cL-!2oI?MK02kgd(tQjeS~hboUl8gDEjgqfkDx`&o(2_FAXtwAfJK}ygVpj zHYos*3x#w|aNLc4idur~qlJ#3VpxkZkkOai!IrrQF z1xp;l;oTH~X6NR_DInCn)(|PtFK>kG##ZhJbFnP4<-%4YRu3|-#iYq98SgM+_AwnJ zoD>%10rI<{Fpt$3kOa8P9md|>fTXLzi*)DsF-^Twz;J}zZ5n*c<3$0(YZ9@{g!$i; z(22Adwt}JMQs4NZUEf&6xKNUBD>qFd;(4I-4JlcX(is?Z{aEB!Wi+?n%q%2n^m)z` zE`Qa6b;6R6lQ4|d8-c>La2^;-{XnDvb3{MZJO*I!Aa6%Bb^Jv(ldu4xXzjT?yn6qRmZ32h-E{A_(j~5gos&iK$!u zjPROG`o`^M!Dnkqh6f8j)rKY*4ox*8%!7S<_OOKvP4w9jh`J`|VvVk<2OTUcW2=DW zG&R+1NQ?qW15E>fUoF-!7|~cE!p4LV z&;D=08_^tVl)`)iJZXy~bjfgtG(&`mr8sD)y6W59`R9MEa|Ek1-&LsyMG$>I)}b3= zZ2<8LSk04VyPHqyg946*%B%D}x7Mr|@~}oIs%PdRDI(M`!IfHgyXYETn^`fck+R52 zCAItWn<4Ud2ZK(~RLBgO3oY>W;k7UP*bm7KjfMe+S!L)~*4NQvea+U@g?budmI1dE zz`f_-w<8U|WBQUJ<)d(qlZ3@Rw(no^IM7m6Y{&V2t5^1W>!YqQ#t?yP>OC=>3euC z@3!SO@0Sq5mj;SNzWejg2S?wgJ5enoc<|jeSTO6F4t--)e?N$j$e8{HyU;|#+5Q`P z!onbsQAt?W3SY4OV^}0U8{VYGsZsqhbeSGFWXf%wS+Q_4G51f71&hYnBVXYJUzWW! z4zvQ#7O%Ro-0|#t^{aVcs?Ksk9uKe%&bfTu&V&2`fn5he&-|7{{7IEN0uMvkXtQ$} zG$8t((*Ygs7o(YDvZQx+vkM-HeJ&Ud`<$3=N+3oD6X}acETG1>x3^9UeYR{OG_{`b zslpta7?Ua_+QjfJIk8w9)u^e>-vDrtw+3QDzL;q6Tu4pB#V;hagBu-8fX)J4J<0W4mJvr-!D z7QYFc3@JI6F9+x^=uvS@kJ^LPSbT4zv$#m0NjE%teyFj|2=+(^uZFx4E$~$27qD{1 z7HnH9FNWm?B1tZSQJ>SHTd-ccl;O6)sSNBh%)|Vy(qf^Vh+hoDXRI7Bg$fGswOg_0 z!4k%!R+@Syc08qTnFMC8Uo>l_NnXbu%A%gGYD+i+TPDlkKO4{XNZ_%Wq^~1g3X`AV zI+tRv8eqgLFWTi{`SYqA?wHZunFTB`3dORZeQ*Qdh~BpyEBal1OAYZo4@=_^_kzlI z^g+8Ig3v?v!(qBqra>FOr`Q&WrrQu zpK?nxU@-5ncJS(xL;ztu2?*fU&h+#Ir9AnV@FeGD{j!b&M)65bem8#&o&D8%zvC(H zb<(-*X)Y3b+dRpUn%AG*2BR!@j-c&DfMmSdz)CELtF(8C#c2r(8=LRe!mr(^H14J4l3B5FVJ~nhIXIm3EUm?!|!*d)h z^4%xkTW#KMFHmFNsEVkHJr$A9K3?H^_LtA@dzL*BpM5fP#@;0I27TqQwamy?gZ^!c z7Z6c}&KYE+1(1I$ks?50rqF&A{s#?6@5>UB&L}i&FeDm@_b9A_8Zgba`4852WGK~+dg#wVHqw$lS7(ny< z^9CDYyz0pwh3@TTMpSt`{fE&r5fws2*vlfq>0(S@M;v3!%yg%+ok^>AdenWCF7Ck` zaG;NDp_$_pzda_LutgpdKCng6os%9vGlOtj&z_?2KqxeGfVGl2Y)!9tfiqEejJmY) zaX7{c`D@URP)TwfH5u4ONaO+x$Nl+1T9IeZM{Jfp@pWZ~3IEqt4!;aw={xJ8I6Rj% z9>=%I}_R|H{iLup`6cUvU@he$fai8E=~Q9dNMwwl)y9;@&jpvp3$TEOc^X1ZI={a z;}~6;PW5<$4v)h-Z1qHWgH}(hcX*P=;0@|M=E`A5nE?bhuaXg5LFIRqw``uVdEDlb z%>|pYE6tlPZB{quZ%N*4*%G#eDqO%#f&x&?fdx#}#hya+VSO2tv2{Ri=Tize9*A!O zg6$DlVbF;{2U}SvXBfeIr^p#$I635uaGWOjGq3|y)0|)+6umpbE?rBL~n)paAQ#>4+|{hy*XtYq~%-Yfd#Ez`iusIqc{&j%R7(xPTXa z-UlO?CpRaKKT>%b!GWx)uByW6cppf|#z3G$>el5_J(o*=!L2RAt~@5}36u{^B6cR} zz(yMUaZhr>@jRdX39JTs5)12}hOp;7aSoxroTsz<&|$CZN}Y6qW^@+Gc$@mRCk(}7 zdmey)=>O;dSjFPEB&;3<51yEw8&ahBLHXT;<4NtkjYa)E+p$Lx+j!{5D!oE->2Gzp zSUO#=qu&A71StD&v>)I5@IFtsz5g7Fj0!}NKPFGdlJNeM{a5m;{!D1|Js3qnzh%dKGgj$Fk)ei2+sWH(>#A1-{Ak z2nHQN$I&1A4!W5oy-e?_Dvw7yb7_FECs<=OMk72<(4UVIsKY=?EWlO{P+zniFprAB>x`93bXy(PCOyel zJD%o)E&#$yxsDASjD8IZ>&#g~rDAM&nn%*MN~9}Cx+i$%MgdJanAM5}2rVgyg6Q_( zA6y7~c02#82p-uLij`VSvI}4W7KIHOJ)^n$%PqOvZ<5j&5rLZKe;2y+Uky&#j%2N4 z$y_>+m$z^_`VtrZ^6CDMPM)=$K1o5xanQgcu;kjO-7Jd{<;`Mp<)a`}i~M#`&_*B9 z&>z$1pC5Y?DhcoSQw>jG+k_{vvgK(g3!yDnCZNj#i;3EV&AtBL{Q~FMw7o>@?wl3BH9wdi{Ic@`vvfU>P!RID$d--|6uSUA2A`ZVzYMQ~_Nc`W{r& zI4tUDkoXD<+x*}SiFd4_Yd&A^tZ-qcgiTnxdR^&pGF(<%VSdt?9d)_=SLA{IbHxcK zci`%{{7K1%5NhY7vRrZXWeHvwVBoLlB4dLepy#ZxhH7>i*YG|&jc+(Rhr)P2x*x?Oq+;P*|;vYqQJ+Lx?c=FrS=NhiPZuOK7AV3agrVqT){E;e|n6`Z_tVSaVVZN)?tuK?h>j%^*eQ462s~LXdbJiPkLvOB42^hTETnxq<3Iu2KX4T zVqFZzlAhK(*~*d~isKNFt)Z`00C~MYOtd?(a?zlPGXjPf+NAePfp-Tum?cCWO~3*o zxUHoyhK{CduOPoup&RwvBjZTJV}^#8vFFZi^Z1xh0g}LOCd8;wgy!q9y7T61dkihU zgs{8ER!F1C22TV$Dm|BBPYgFII~4lRWlvhJkYB&o9KQ)-gafxrBBXw|nYtjZi#^V| zklBK*n9O}|LHB^kzprZ!BTn4;R+^MRSWNKi1z|B@xfKZTv?a6YkDo+7?|@z&s_2d) zAAVo`B|lnj%KGpd{u3;rSewjtg-Z6NCGvD5pUhYTe&+DljIPX%JxsoW`5%JuW7Q!d zTx{8=60pVO(%bnW^?^~CDyYbPdhkX$!-SxYb(v^fCQdojs{s+R28fVV<6S?Twzwr*w^F$W}rpC}wuGG_Aw>_yn_!05|JF?0aJkE5R9Fx332v}mg z!&sXfh>AIgT@MTlsD>SkUN+M<&SPOM$8s08v^RoLM<61G{*A-xR}E`@M&GW=(EILl z`c`sFeCr~yu(nE%44oNztOHsnbY{ThI)tSW5b=S@F^opo3IaYbF(znY1g#HDiTQ61 zdRWhPT%q}hZrt2##lS+&_$*_YhY#yR!N7vbW8u3ikD2%EsXWH**;AsfS3`w4LJpJW zMuwros#GQhfdVoGj4{wz#%PBdV;gNcbz*N@_1hh+s-=g`T9_N4I?|I_U$BQ8-h^qXJ_ z9D-~cs2uu>Z=sq^IWOrOu_%g`e%l!QM*gHRn9|q5iHuz)`}OW@G1k3CjJ_EUeZXCS z1wo6X()sO;*i0lRbx49m{j`QpXW@|oAv0F^o7DKNWJW~=QPs$F0VL)A|QpG-Ol%i*TUW9ph?|WQN!*cpa zj}(^K^CxVUvOD-Z-K#bRYn$mGu_+ClLC3ODrDxhh%Tcb%$D338%VKCsPiSozl~n1H z{C@CTd9c(8G;_N=#1?NEvQRC=A9_NeOMeH=Mo~E-4B*%t7cgxb_G0I+#|+GOw#yJS zgeDkx9Ckl7pO}jsOwG96SOFGR9 zf3(?7H{=0gm5-!rY<2##`3LnH-6)g@&YIuEg7gY)g`r?NL^phryH?t;CS|Lz(v~9p z%_glroM+otx6gl;Wm+V-yekdqGRmoWJQl4vTxbhr&7I#TTUOcV@3D(QoSc?pbER$) z%IxSPAq#LqA?MULHBXq3nku>`#J7&2crZ1`6SgHj{Lp*97Sp%itoUDTb=$Xn+A|GG zv8~6n9jfQ}H*_TYv>1Ia@PU8ei%VE+Y2&3}Si{pcv^t0_At#VvOsZqMt?W9bqc2vb z0bv8|R6B6GV`!T(FFhiQP-Je#QxF!{fVLk?Tk5mi3j>Ym5V4*-^LNs!L+~hmpoxnR z2tdrWVVRA-d?6RxGL*&ZfZxHoNHJ~){M`Rvc~=@1#g(p4RdrXh*>qC`_XdsWEGRA{ zL}?^6TZ2Ycm2NR8j*gROl1y&Xt!CnAp=Jy;5|@cF$z-%?Nen7OGC1O>NNm^Op3IDi zi3_+Cv?eM9RD`FS_$J%)P=7vhj|==vQuVHdjY`=?~S;tWBw zCVq|3fFZWIT(beU9KhAx?$?DC^Mjp#+3<#CkaK%(`N0k9Yhkfn>yaN+d?dl0ODZxCRY(MVEt4#4sd)l=jU67BAk|Gu!Y)gJH+&pF3h{`Ax`a+fMHv zv2@(2mTnu00_-g?M2+jpk(SDlkke^n2!ydgX$4!MGyAK&Mw%|ZcIG0_KJ|9f>^(wz+ zzfW7Du{PAoZRKaAMZHvWwYJv*@vx}X@eOS!3&HDhm=yXt^4EbutI+;M&N@s9t?*N? z7NlB6n#NfrtxB3mZ*42+rQka%tY$~Hs?83T*37DU>GK1W(jtj^oWT%_-M zeUgu_*MgmxK8v*azBE||_=XtcQ&mo#am8Gvf9u8I#LF zXnc`U3hVp29s&y#;b^mw&f{?SdCF$Zm7X9r)N^EJPOFfcBMl;jI0{*p5AqJHt>p%$ zhBm8YmSdaX6a(u#@`#djS%$)Y{cXYIwX@MpuA8{RBqilc2Q_1n)zKfPL1E}RkKw1) ze*-XC@PAY8EyKP3dg2L&0 zuJ^~3`cq6|;tHUdM!F(IAzAtZw3mo|({hSP45#O$QvWHJp^7!tO!?6cCj+5R>{3-Di7UZ{9G{Q(pKph^{^FQ z0R+J40$A@uLNNf4(2UTe8sD57V0`m=^@ShFsLA)1aaf}{9WM~4WMy#z)J7iRiwd;l14F?pPmDpudzH;Mc3u2(G%r!_}aLnyZ8`x)^|((($I>2%tCWAqKsDR#9^$p*1&r34+@{p#qu(_fesh zNy1RU8&_I_eM8sa^%sm0ZPUF%n==Zb~1!0FkIY%m*xWgquNnc!~c>?IvvrABH?NkqfIH?}w zAWC7Q;C@@^z7&lN4@O?>!h=k8$88imM^Wm{!W|_8xC7JC0^!GyW1>+uK*W}SJ__aQ zc!I$(ypBjNEnC^34Yid7WMZxmc-eQ|+xClQCD>hOr}UNlAQ6tnaE8#dpt59=lmfws zIy@68J%dv`G+@!$16xDUhkkq4rig|Mg_c_oA3nZo4^%Q#W(mII#Y=X>-9o#1os@qM z7$JYf{7W8`kS5DOJ6LG4pK0Y$X9ImI><6!byP9OU>#u;PS~_S*SHw{icfmkf*q+0J z%g`)H%T%7-D2}}lv-b&aoI^X?6(GAJb_?aky@JH|xNzDHsr*#5*Mw}@IX6n5HG=72GWzALxZ<*(lBB*fNbM1pxr3%FbdGp-@$N{V)DX%Im!7Qv@#DeiBaMp zMqr@A100j$Eh=Z4Yat(fyF5E!&@tx(jGmtfCF6h^pp5}~IE%JPt zp&`BlG{G)m)xz+O>KRraxqLRUfC{3SsHmJh1t^bZ}b zvl!6JE&XAy!G@_iA;7eu*ljd`U}H8tT@aR`)(mG*H^l;vY;Q>d{IMvodSEhct=C`i2qZyqXYQZeg}x5^XbEyGa-U!kVz z@Kp=hedWR~J#-X&B&x1lyGr=tqGuyUo=p`(lE*Dm4;8b{f^m{c}l^wVd!PSID}nQrBUgjZWx;yK{m zzZDAM(+RVpD^&$UYm{@$A^wa2oG2=l8W&X`D|8uX0q;JjZ)jOFP{(Bvt%CG;-=ZiQ z6n43j0xJ#ZTck(bx_S=AT>x(9Br29l{xn1=4Z%oVy{}Pd$vFW!_217Q0QyBX13Fx^ zt)T?7c(s)94M?NDUpCvYh0* zjL&@lMpPBV#2&2+5EEsz#^Aa@pGE}QzpqY}EA{WSy~aY9jMB#(8WdHXNJ4>(1WLwE z$$PFX>(C}o(1wYj@DOeYq5ilxcOz#C%>IM zIBjq8r^&wL9aCDS7_!di-I}_28V%>k+mg2^y)SuuhBvo=N>WO8)+0G3DP88{$-hf? z+CH(hr_@c@l9!OtYbu+(@cF>hWvN`+veaHvWoq4oqLh9?`DsOIzr->ZOA(e!X{*!T zORGxzB<;`GzocBbpVn&{oZf31fweGwXZn}vZRsY9$&zHrwS1CJmw&VLnn2=3Ok@UG zMBX7g$d{yp=$SE079-1%Lm~}Wl)u23k}-pLL!khD$*CgvAtODGb*Ns z1Fj3}J&lUFt5K`(Fe-JoMy2k;`a>YcbmDwRpo+PL@HaV*{k|W^euw?K5RTo(s7MXR zF|~|}-5SDiA0zzsek$f-5X)Y``VHbDu(I6<*09%AYR0G5kald_f>rD_HN#%T`77AJ z%xYAvY87e0da0j^JiPx~q)qQ9qewq8dR7oQKPP~giPlViOZMCxJ1{naIS? zNn~D~^Bi+wP7-rvj+wbJC%JTyCy!~EozILeo?I%=o>Kbl?8%I|cna=GDZRWowe<96 zOX<R>UhIJ5NpoLsCKrI$Q8rRvRU@sekNsNNhYHqIu$8N9=PWx= zAvF6n8d|zP#6q!|bv62=|K#o3Y|Qb86W8IKf_E@6erHx8*y@57-ZEV%xdGy-Hdhbj zv6q@<9vpe;mzT>Rh3&1q@9eTDu`Ez^)Pfz5A&ADE2+!gqJ-+1SPQ_lj-p9L8X<1i6 zjn)(k=7{#PbSYNusF|gaHtlKqbgz=raPW}e7T1aBlh|3-SfsFnNCO+Y4h*<>r!^c^ zB8AX{OI;2~YupLf?HMr9wf6i-9&$!*rPLwaZTokF5+nqw*nk4*#oe~Hd%L|#5_f45 z+ho^?qPAsir4>FdpKYNPFXKeZ@?6`61q=3QlF69a;cWtgsJH z%Hj4`Hr35A#`Dm%aCK8ADWtRD_@r#I;134R>|s8Dj~~{cwHCmU1?zsX{19IuD#5ns>lXd!5>>o z!>bULV&%H`Y8qZtvR>z{DNX!bOK#dVF{Rq!!%P4^io)*-j_V|ZjdLB@4qVkACh1ny+~=oPv>_Fzl*Me?#nWXVlE zFNP@>RpJdD(PvG2K8pT=MS3$cL_`c4F%2OIVd+Qq{s-&Ng`-KTYf2fyz99}FqX}V@ zWPbW1PwM^4vv?|5p1F)Cja;Itk^5oA5Jn{8duirM^IKwCS{k^QD&JbYc5U{%+0&-k z-hJ==KYsA1jpoekY1P#qezfJ|nyuTm*Z#TglTZIrzvHhv8+QF|_ny6t`%tv z(BUITKW{#E{KUyqr_X%x<=_AD&$C~BeeRoY&tJHBsipPum8;jJwszn38{d6@^VaQ- z&L6tE@7%rDbHBF_#r1#v1QE0{35jC0F^a4bzc?W=dZKCMK#^fkQ=o%Z^O}Ibpx}^x z+EAT7ObCA@qW^$_g9Z;7YKV*)HvG{Mj~O3-;>o9?M~;daJ!b5<*r%U~dv^SUcvHf} z#OIRC$tkI6>6VPlNt2(Sl9i1qV*b==(+jM&8HF=nD4I3SGf|_@{9K>-xxVys z;fx=NDuR(qXtOC}7Sofj-pTg?@oMhh~J_xh)D16SV59k0Zcl?R= z?D1-J>h@g!W?sBeBF!#csbf*~)aJM<9ffYe! z)WDYdfahg^g~WepjF|YOo;X;1JF}T^{ZJVRdYu?catKR+`6c0`fxJpoAYy+NXT~8F z73sln$ukw$XGt0U8FD0)kRgwVQ3RYyfg{EI-D87e{#n?Z^@{DawPEY=U4(~UMMxCY z%E-t}6hp|&6twZFdA68*TmE?QS;B5dovB6#6QceEfBYr{Lui0Om|0_q-6Tf&eYV3sZu_MP$m=G70QvA}~dG_LwQJJs& oA|}fG(o0c!G*n4c-n^1|_676iMp^M2H3q*?anC#*J8mrbcci4ZO#lD@ literal 0 HcmV?d00001 diff --git a/IBMDOS/BIN/IBMDOS.INP b/IBMDOS/BIN/IBMDOS.INP new file mode 100644 index 0000000..7e6ab48 --- /dev/null +++ b/IBMDOS/BIN/IBMDOS.INP @@ -0,0 +1,5 @@ +ibmdos.tmp=header.obj,pcmif.obj,cio.obj,disk.obj,ioctl.obj,misc.obj,support.obj, +dosmem.obj,error.obj,process.obj,network.obj,int2f.obj,fdos.obj,cdevio.obj,fioctl.obj, +fcbs.obj,redir.obj,dirs.obj,buffers.obj,bdevio.obj,cmdline.obj,history.obj +[map, data[origin[0000]]] + \ No newline at end of file diff --git a/IBMDOS/BIN/IBMDOS.MAP b/IBMDOS/BIN/IBMDOS.MAP new file mode 100644 index 0000000..3c4e85e --- /dev/null +++ b/IBMDOS/BIN/IBMDOS.MAP @@ -0,0 +1,154 @@ +Map for file: IBMDOS.TMP + +Segments +-------- + +Length Start Stop Align Comb Name Class + +3830 (0000:0000-382F) PARA PUB PCM_HEADER CODE +2C03 (0000:3830-6432) BYTE PUB PCM_CODE CODE +3ADE (0000:6434-9F11) WORD PUB BDOS_CODE CODE +02CC (0000:9F12-A1DD) WORD PUB PCM_RODATA CODE +0399 (0000:A1DE-A576) BYTE PUB PCM_HISTORY CODE +01B5 (0000:A577-A72B) BYTE PUB PCM_ICODE CODE +0000 PARA PUB PCM_CODEND CODE +0000 BYTE PUB CODE CODE +03A2 (0000:0000-03A1) WORD PUB PCMODE_DATA DATA +000E (0000:03A2-03AF) WORD COM FDOS_DSEG DATA +0C50 (0000:03B0-0FFF) WORD PUB FIXED_DOS_DATA DATA +02B8 (0000:1000-12B7) WORD PUB PCMODE_CODE DATA +0014 (0000:12B8-12CB) WORD PUB GLOBAL_DATA DATA +0120 (0000:12CC-13EB) WORD PUB BDOS_DATA DATA +0000 PARA PUB PCMODE_DSIZE DATA + +Groups Segments +------ -------- + +PCMDATA PCMODE_DATA FDOS_DSEG FIXED_DOS_DATA PCMODE_CODE + GLOBAL_DATA BDOS_DATA PCMODE_DSIZE +PCMCODE PCM_HEADER PCM_CODE BDOS_CODE PCM_RODATA + PCM_HISTORY PCM_ICODE PCM_CODEND + +map for module: HEADER + +382A (0000:0000-3829) PCM_HEADER +0102 (0000:A1DE-A2DF) PCM_HISTORY +01B5 (0000:A577-A72B) PCM_ICODE +03A2 (0000:0000-03A1) PCMODE_DATA +000E (0000:03A2-03AF) FDOS_DSEG +0C50 (0000:03B0-0FFF) FIXED_DOS_DATA +02B8 (0000:1000-12B7) PCMODE_CODE +0004 (0000:12CC-12CF) BDOS_DATA + +map for module: PCMIF + +03F6 (0000:3830-3C25) PCM_CODE +00DC (0000:9F12-9FED) PCM_RODATA +000E (0000:03A2-03AF) FDOS_DSEG + +map for module: CIO + +0491 (0000:3C26-40B6) PCM_CODE +0004 (0000:9FEE-9FF1) PCM_RODATA +000E (0000:03A2-03AF) FDOS_DSEG +0001 (0000:12B8-12B8) GLOBAL_DATA + +map for module: DISK + +044C (0000:40B7-4502) PCM_CODE +000E (0000:03A2-03AF) FDOS_DSEG +0002 (0000:12BA-12BB) GLOBAL_DATA + +map for module: IOCTL + +0164 (0000:4503-4666) PCM_CODE +0032 (0000:9FF2-A023) PCM_RODATA +000E (0000:03A2-03AF) FDOS_DSEG + +map for module: MISC + +0687 (0000:4667-4CED) PCM_CODE +004D (0000:A024-A070) PCM_RODATA +000E (0000:03A2-03AF) FDOS_DSEG +0002 (0000:12BC-12BD) GLOBAL_DATA + +map for module: SUPPORT + +00C7 (0000:4CEE-4DB4) PCM_CODE +000E (0000:03A2-03AF) FDOS_DSEG + +map for module: DOSMEM + +0260 (0000:4DB5-5014) PCM_CODE +000E (0000:03A2-03AF) FDOS_DSEG + +map for module: ERROR + +01AE (0000:5015-51C2) PCM_CODE +00B4 (0000:A072-A125) PCM_RODATA +000E (0000:03A2-03AF) FDOS_DSEG + +map for module: PROCESS + +07B2 (0000:51C3-5974) PCM_CODE +000E (0000:03A2-03AF) FDOS_DSEG + +map for module: NETWORK + +0086 (0000:5975-59FA) PCM_CODE +000E (0000:03A2-03AF) FDOS_DSEG + +map for module: INT2F + +04EB (0000:59FB-5EE5) PCM_CODE +000E (0000:03A2-03AF) FDOS_DSEG +000E (0000:12BE-12CB) GLOBAL_DATA + +map for module: FDOS + +199A (0000:6434-7DCD) BDOS_CODE +0078 (0000:12D0-1347) BDOS_DATA + +map for module: CDEVIO + +02B7 (0000:7DCE-8084) BDOS_CODE + +map for module: FIOCTL + +0238 (0000:8085-82BC) BDOS_CODE + +map for module: FCBS + +0558 (0000:82BD-8814) BDOS_CODE + +map for module: REDIR + +06CB (0000:8815-8EDF) BDOS_CODE + +map for module: DIRS + +03EE (0000:8EE0-92CD) BDOS_CODE +0037 (0000:1348-137E) BDOS_DATA + +map for module: BUFFERS + +052C (0000:92CE-97F9) BDOS_CODE +0005 (0000:1380-1384) BDOS_DATA + +map for module: BDEVIO + +0717 (0000:97FA-9F10) BDOS_CODE +0065 (0000:1386-13EA) BDOS_DATA + +map for module: CMDLINE + +054D (0000:5EE6-6432) PCM_CODE +00B7 (0000:A126-A1DC) PCM_RODATA +000E (0000:03A2-03AF) FDOS_DSEG + +map for module: HISTORY + +0297 (0000:A2E0-A576) PCM_HISTORY +000E (0000:03A2-03AF) FDOS_DSEG + + \ No newline at end of file diff --git a/IBMDOS/BIN/IBMDOS.SYM b/IBMDOS/BIN/IBMDOS.SYM new file mode 100644 index 0000000..5a9daae --- /dev/null +++ b/IBMDOS/BIN/IBMDOS.SYM @@ -0,0 +1,179 @@ + +0000 VARIABLES 0000 DATA +03A2 FDOS_DSEG +0000 VARIABLES 0000 DATA +13F0 DATA_END 12CC HASHROOT +0000 LABELS 0000 CODE +3800 CODE_START 380A OS_VERSION 3822 PATCH_VERSION +3806 PCMODE_DSEG A730 CODE_END +0000 VARIABLES 0000 DATA +0FE4 ACTIVE_CNT 056D FILE_ATTRIB 0572 REMOTE_CALL +043E SEC_PATHNAME 0EFE FDOS_STUB 0EE0 HASHMAX 057E TERM_PSP +03B6 BIOSDATE 0D1C DAYS_IN_MONTH 0588 CRITICAL_SP +0AA2 RWMODE 0F02 SHARE_STUB 0AA0 INDOS_STACK 03B8 MINUTE +0AAD UCASETBL 0EBC @PRIVATE_DATA 05CE CURRENT_FILEPOS +0584 INT21REGS_PTR 05F0 PREV_INT21REGS_OFF 0AA4 INT2F_CMD +0FE4 IDLE_DATA 0AAC SWAP_INDOS 03BE PRI_PATHNAME +05F2 PREV_INT21REGS_SEG 0ECC HMAROOT 0580 INT24_ESBP 0FEA IDLE_VEC +057C EXIT_TYPE 0620 FCB_SEARCH_BUF 0CE3 DBCS_TBL 054B NAME_BUF +0AA3 IOEXERR 0920 NORMAL_STACK 07A0 ERROR_STACK +05AA CURRENT_IFN 043E LOAD_FILE 058A CURRENT_DDSC +0FEE INT28_DELAY 0FE6 IDLE_MAX 0AA8 FILE_MODE 03B0 MUSTBE03B0 +05A2 CURRENT_LDT 03BA HUNDREDTH 0FE8 IDLE_FLAGS +0FF0 INT28_RELOAD 0D12 DOS_VERSION +059E CURRENT_DHNDL 04BE SRCH_BUF 0ED6 LOCALMACHINEID +0EC4 @HIST_FLG 05F0 PREV_INT21REGS_PTR 03BE RELOC_BUF +059A CURRENT_DEVICE 0BB1 FILECHARSTBL +0B2F FILEUCASETBL 0AAA CLE_STATE 0AA1 ERR_DRV +0F3E WINDOWSHANDLECHECK 0AA6 INT2F_STACK +0584 INT21REGS_OFF 04F3 TEMP_LDT 0ED8 DMD_ADDRESS +0ECA CODESEG 0FC8 EXE_BUFFER 03BB SECOND 0586 INT21REGS_SEG +03B9 HOUR 0ED2 DMD_OWNER 0BE1 COLLATINGTBL +0374 EXE_LOADHIGH 0048 DEV_ROOT 0320 ERROR_FLAG +032E DMA_SEGMENT 0324 ERROR_CODE 0303 SHARING_FLAG +0010 FCB_LRU_COUNT 03A1 CHAR_COUNT 0351 MONTH 034A LOCUS +0334 RETCODE 01FB SAVBUF 0352 YEARSSINCE1980 0328 ERROR_DEV +0392 FCB_PATH2 0335 SYSTEM_RETCODE 0026 FUNC52_DATA +0089 DMD_UPPER_LINK 0358 INT28_FLAG 0300 COLUMN +02FF VERIFY_FLAG 0301 SWITCH_CHAR 005D SETVERPTR +0046 PHYS_DRV 034C RETRY_OFF 000E NETBIOS 0359 IOCTLRH +0357 INTERNAL_FLAG 0320 INTERNAL_DATA 0383 FCB_PATH +034E RETRY_SP 0304 NET_SET_COUNT 001A NET_RETRY 0337 BREAK_FLAG +0356 DAYOFWEEK 0327 ERROR_CLASS 0069 BOOTDRV 0040 FCB_PTR +033E MACHINE_ID 0342 LOAD_IMAGE 0372 LOAD_ENVSIZE +0322 ERROR_DRIVE 008C DMD_UPPER_ROOT 033C OWNING_PSP +0336 CURRENT_DSK 0334 USER_RETCODE 0346 LOAD_MAX +033A INT21AX 0332 BREAK_SP 0326 ERROR_ACTION 0305 NET_NAME +0370 LOAD_ENV 034B VALID_FLG 027B FDOS_BUF 002E CLK_DEVICE +0036 SECTOR_SIZE 001E BCB_ROOT 0348 LOAD_HANDLE +033A SWAP_ALWAYS 0323 ERROR_LOCUS 0032 CON_DEVICE +000F NAME_NUM 0302 MEM_STRATEGY 0344 LOAD_TOP 0340 LOAD_PSP +007C DEBLOCK_SEG 0026 DDSC_PTR 0354 DAYSSINCE1980 +0330 CURRENT_PSP 002A FILE_PTR 001C NET_DELAY 0321 INDOS_FLAG +032C DMA_OFFSET 0024 DMD_ROOT 0350 DAYOFMONTH 003C LDT_PTR 02FE CIO_STATE +005A JOIN_DRV 0375 FCB_PB 0048 NUL_DEVICE 0047 LAST_DRV 1010 EXEC_STUB +1008 LOCK_TABLES 113E HISTBUF1 1144 HISTBUF2 +1129 CRITICALSECTIONENABLE 112A SWSTARTUPINFO +10E5 INT2FBIOSHANDLER 12A8 INTL_XLAT 1192 XLAT_XLAT 1000 MUSTBE1000 +1232 COUNTRY_FILENAME 1296 DEFAULT_COUNTRY +1004 UNLOCK_BIOS 1000 ENDOFINSTANCEDATA 1294 CUR_CP +1140 HISTSIZ1 1146 HISTSIZ2 10E9 INT2FNEXT 1102 INVALID_STUB +1014 FUNC4B05_STUB 100C UNLOCK_TABLES +1292 COUNTRY_DATA 1000 LOCK_BIOS 1292 CUR_COUNTRY +11A0 NOYESCHARS +0000 NUMBERS +0D90 LAST_KEY_EXT 001C INFO1_LEN 0082 INFO2_LEN 0082 INFO4_LEN +0018 INFO5_LEN 0102 INFO6_LEN 0012 INFO7_LEN 0008 RELOC_CNT +0000 LABELS 0000 CODE +3830 CALL5_ENTRY 3B29 DO_INT24 3A65 INT25_ENTRY +3A61 INT26_ENTRY 3B18 INT27_ENTRY +3BFD INVALID_FUNCTION 3C03 RELOAD_REGISTERS 3987 INACTIVE +39B3 DOS_ENTRY 3A36 INT21_FUNC 3BE9 GET_DSEG 3936 INT21_EXIT 39A7 ACTIVE +384F INT20_ENTRY 3851 INT21_ENTRY 9F12 PCMODE_FT +0000 NUMBERS +006D PCMODE_FTL +0000 LABELS 0000 CODE +3C26 FUNC01 3C2A FUNC02 3C37 FUNC03 3C3D FUNC04 3C42 FUNC05 +3C6C FUNC06 3C7F FUNC07 3C87 FUNC08 3CA3 FUNC09 +3F10 DEVICE_WRITE 3CB7 FUNC0A 3CC0 FUNC0B +3E00 COOKED_WRITE 3CCE FUNC0C 3CFD BREAK_CHECK +3DD0 RAW_READ 3F0C DEVICE_READ 3DC1 CMDLINE_READ +40DF VALID_DRIVE 4104 FUNC10 4104 FUNC11 4104 FUNC21 +4104 FUNC12 4236 FUNC40 4104 FUNC22 4104 FUNC13 41DA FUNC41 +4167 FUNC32 4104 FUNC23 4104 FUNC14 43EA FUNC60 426B FUNC42 +4104 FUNC24 4104 FUNC15 4295 FUNC43 4104 FUNC16 42FE FUNC53 +4104 FUNC17 42BD FUNC45 4174 FUNC36 4104 FUNC27 42B2 FUNC46 +412C FUNC19 4104 FUNC28 4317 FUNC56 42EB FUNC47 4340 FUNC57 +41E4 FUNC39 4409 FUNC67 4482 FUNC68 4130 FUNC1A 4139 FUNC1B +41E4 FUNC3A 4139 FUNC1C 40B7 FUNC0D 41E4 FUNC3B 40CD FUNC0E +4373 FUNC5A 41F6 FUNC3C 4104 FUNC0F 420E FUNC3D 41F6 FUNC5B +4167 FUNC1F 42CD FUNC5C 42BD FUNC3E 41C9 FUNC2F 448E FUNC6C +4236 FUNC3F 41E4 FUNC4E 41E4 FUNC4F +451B FUNC44 4503 FUNC69 +47B4 FUNC30 47C9 FUNC33 4800 FUNC25 4678 FUNC52 4667 FUNC34 +4816 FUNC35 483C FUNC63 4838 FUNC54 4797 FUNC37 4B89 FUNC65 +4AA8 FUNC38 4873 FUNC29 4C77 FUNC66 495A FUNC2A 4980 FUNC2B +496D FUNC2C 4999 FUNC2D 4832 FUNC2E 467D FUNC5D +466A RETURN_DSBX_AS_ESBX 49BC READTIMEANDDATE +4D59 FCBFDOS_CRIT 4D3D RETURN_AX_CLC +4D01 SET_RETRY_RF 4CEE STRLEN 4D8E RETURN_BX 4D9B RETURN_CX +4D6F FDOS_NOCRIT 4DA8 RETURN_DX 4D03 SET_RETRY 4D82 RELOAD_ES +4D33 FDOS_AX_CRIT 4D28 FDOS_CRIT +4EED SET_OWNER 4DB5 FUNC48 4E4F FUNC58 4DE2 FUNC49 4EB7 FREE_ALL +4E1E FUNC4A 5004 CHECK_DMD_ID +5062 CHAR_ERROR 504A ERROR_RET 5015 FUNC59 503D ERROR_EXIT +505A FCBERROR_EXIT +54D3 FUNC00 52B0 FUNC31 52A3 FUNC50 52A8 FUNC51 52A8 FUNC62 +51EF FUNC26 51C3 FUNC55 5928 CHECK_EXE 52DE FUNC4B 54F1 FUNC4C +55A4 FUNC4D 5936 IMAGE_SIZE +59E2 FUNC5F_COMMON 5975 FUNC5E 59B1 FUNC5F +5A52 INT2F_ENTRY +0000 VARIABLES 0000 DATA +132C GLOBAL_PASSWORD 12D6 FDOS_HDS_ROOT 12E6 INFO_FCB +131C FDOS_PB 12D4 FDOS_HDS_BLK 12D8 FDOS_HDS_DRV +132A FDOS_RET 1316 FDOS_INFO +0000 LABELS 0000 CODE +7DB4 SHARE_DELAY 6E07 FDOS_MKDDSC +6B82 FDOS_GETDPB 682B FDOS_CLOSE 6FB5 FDOS_MOVE +6D61 FILE_UPDATE 6552 FDOS_MKDIR 7CD9 READTOD +7B7F LDS_SI_DMAPTR 65B4 FDOS_RMDIR 6CA6 FDOS_NEXT +6EFD FDOS_EXPAND 6BEA FDOS_SELECT +7A9F DISCARD_FILES 7A70 RELEASE_HANDLE 6DB9 FDOS_MKNEW +6BB8 FDOS_FLUSH 7108 FDOS_DATTIM 71B2 DBCS_LEAD +79EE VFY_DHNDL_PTR 6C7D FDOS_FIRST 6D53 FDOS_COMMIT +6B34 FDOS_CURDIR 7C77 MV_JOIN_ROOT 6514 FDOS_ERROR +68B5 FDOS_WRITE 6A25 FDOS_ED_FUNCTION 74F0 GET_PB2_DRIVE +68EE FDOS_UNLINK 7B8B COPY_ASCIIZ 6434 FDOS_ENTRY +7607 UNPARSE 79AB VERIFY_HANDLE 7B7A CURRENT_DSK2AL +6E18 BPB2DDSC 654D FDOS_ED_ACCESS 7B60 GET_XFTPTR 685E FDOS_READ +77B8 CHECK_DELIM 7AF0 FIND_DHNDL 6E9C FDOS_DDIO 78C6 FIND_XFN +7B92 CHECK_JOIN 720B REBUILD_LDT_ROOT 653E FDOS_ED_DRIVE +7D6B HASH_PWD 77FD TOUPPER 6C1D FDOS_EXEC 652D FDOS_RESTART +78DF ALLOC_DHNDL 6DDD FDOS_LOCK 6AEA FDOS_DUP 65FA FDOS_CHDIR +64BD LOCAL_DISK 78ED ALLOC_XFN 69BB FDOS_CHMOD 7B85 LES_DI_DMAPTR +77F5 CHECK_SLASH 75F7 HDSBLK 7AC7 IFN2DHNDL 6AF9 FDOS_FDUP +673D FDOS_CREAT 65DF UPDATE_DIR_FAT 77EC CHECK_DSLASH +7791 PARSE_ONE 7133 TIMESTAMP_DHNDL 67C2 FDOS_OPEN 6960 FDOS_LSEEK +8019 FIRST_DEV 7E81 WRITE_DEV 804C IOC6_DEV 8050 IOC7_DEV 7EB6 READ_DEV +7E67 DUP_DEV 7DCE OPEN_DEV 7E75 CLOSE_DEV +80A9 FDOS_IOCTL +82BD FDOS_EXIT 8301 FDOS_FCB +8957 ISLOCAL 8815 REDIR_DHNDL_OFFER 8D5B REDIR_BUILD_PATH +8891 REDIR_DRV_OFFER 8845 REDIR_MOVE_OFFER 8904 GET_LDT +883F REDIR_ASCIIZ_DEV_OFFER 887C REDIR_ASCIIZ_FILE_OFFER +8877 REDIR_ASCIIZ_OFFER 8919 GET_LDT_RAW +88A7 REDIR_SNEXT_OFFER +0000 VARIABLES 0000 DATA +137D CHDBLK 1379 DCNT 1377 DIRP 137B FINDDFCB_MASK +1357 DIRBUF +0000 LABELS 0000 CODE +8EE0 FILL_DIRBUF 928A ALLOCDIR 9259 HSHDSCRD +8F9B DISCARD_DIRBUF 8F3A FLUSH_DIRBUF 9005 SETENDDIR +917E FIXUP_HASHING 9022 FINDDFCB 901F FINDDFCBF 915A MKHSH +9025 GETDIR +960B UPDATE_DIR 92CE UPDATE_DDSC_FREE 946C FIXFAT +9414 ALLOCATE_CLUSTER 936C GETNBLK 9334 BUFFERS_CHECK +9595 LOCATE_BUFFER 9523 FATPTR 946A CHANGE_FAT_ENTRY +96D3 ZEROBLK 961B FLUSH_DRIVE 92FB DISCARD_DIRTY +93A7 ALLOC_CLUSTER 93AA ALLOC_CHAIN 9351 DELFAT +92FF DISCARD_ALL 9303 DISCARD_DIR 9382 GETBLK +9612 UPDATE_DAT 9616 UPDATE_FAT +0000 VARIABLES 0000 DATA +13A5 DOSFAT 1395 LASTCL 1388 LOGICAL_DRV 139F CLSIZE +13B4 FDRWFLG 139D NFATRECS 13B0 CUR_DMA_SEG 13AE CUR_DMA +138A PSECSIZ 1393 DATADD 138E FATADD 13CD REQ_HDR 13A1 SECPERCLU +1399 DIRADD 1389 PHYSICAL_DRV 13A3 DIRPERCLU 1391 DIRINROOT +1386 HDSADDR 13A8 PBLOCK 13A7 ADRIVE 13AC MULT_SEC 139B NFATS +0000 LABELS 0000 CODE +9EF3 CLUS2SEC 9CE1 SELECT_PHYSICAL_DRV 9E9E WRITE_BLOCK +9819 FDOSRW 9D06 SELECT_ADRIVE 9C59 DEVICE_DRIVER +97FA GET_DDSC 9C85 SELECT_LOGICAL_DRV 9C38 BLOCK_DEVICE_DRIVER +9EB2 READ_BLOCK 9E79 MARK_LDT_UNSURE 9BF9 DDIOIF 9BD4 BLOCKIF +6389 SPACE_OUT 6136 DEL_EOL 6116 PREV_W20 619F DEL_LINE 5EE6 READ_LINE +6339 CHAR_INFO 638D BS_OUT 6399 PUT_STRING 60C9 GOTO_BOL 62B4 SAVE_LINE +615E DELN_W10 60DD NEXT_CHAR A127 EDIT_SIZE +A303 SAVE_HISTORY A2E0 INIT_HISTORY A51D MATCH_WORD +A4E4 DEL_CUR_HISTORY_BUFFER A554 DEL_BOL A4D1 DEL_HISTORY_BUFFERS +A53C PREV_WORD A502 NEXT_WORD A378 MATCH_CMD A388 SEARCH_CMD A3E1 PREV_CMD +A405 NEXT_CMD A418 GOTO_EOL A565 DELN_WORD + \ No newline at end of file diff --git a/IBMDOS/BIN/IBMDOS.TMP b/IBMDOS/BIN/IBMDOS.TMP new file mode 100644 index 0000000000000000000000000000000000000000..c847996ac1257f77dcf050a3601263f31630f468 GIT binary patch literal 48128 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 literal 0 HcmV?d00001 diff --git a/IBMDOS/BIN/INT2F.OBJ b/IBMDOS/BIN/INT2F.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..6e0d22a725ea72c18aa228f6b83408749afb5804 GIT binary patch literal 3072 zcma)8Yi!%r6~33GBuetTj$`K`IWIM>6DPJ)H}fMkEs~ZJS&~WmTFS#pwrpsNF6bO8 zeW2(BSS@19akmBNg3Uji7RZk{!Mee~lojZlk!gS}i;WB&f(Gllx?P>QC_FT=3~Tjr>FFwjkRqs^JNGtL*VXPhR$W)Wv-4Qr&b?2U zzWotGHYuhl0_Ts2l1qnhXUo*A|mF+NP^n#!7fQrB1*1DxI_qrB7Q-W68=!Ps!0l7 z<5z-O&@Y5k$*%KWLa0P%B&-FnUFo62f%#|v)S^Ogi9aBOJEVjxXnEeaaFs)Qw=4sNLdvsFkvh~w zRLgHACA>Nu*hxnqmoK)fni7)2*p*8xA*tz zT=eK#i3I(S38k8=ivwch3R>0^42zK-Xghe9`~k^-0P}J%B<0MUVM;$Y438*A)hI0* zt)v_hIsr&hOcKl2)%JfFUTzU zG6|-CmP<{~8J?NHTeC+!XKlr3>)gy=th3F=Np9%+>;??hzKq1w7`_34Y2{#J^9|sa z*mn`iGW)%gOUtR{GQBIcT&fGH*UmUq{G&Q4@zYBO)%LYc3usUu*vYO)JAU>Pg88y~|j;98spoWbYu1$+e~REz(F zPmIJ-+5x28WL;S|72LXoxy?~>D?*fhkegJqD@I2rJzzM*MfIfguuz3pB zmo;W&v;#5s&`taa{uiEu&=%go#F(SZ0P`#68Z*iKjVWN`Y?4i}7g^{GJI5l9^ zx0ds8PjZV{3mN7+!f=mQn82|^c19*T7Pyi?blmN;A<$wx6C14$31Hc2Q25bh< z41K_IJFHIvb^vMty8-opJ%C2QUVuQVb1ixr`!Yvt^Vd_lEo(3R^Dd*|&ag4q%d>ab zJH}mvGBV$?E6KcfxaF{+j58U+L)#7-9?%cVbmrh2HSGuu$SCGD==4~H`jX+f)`-xh zbKZ9lI_-l|V$q_Jt%e_(wQpWxQ@W#XWE)Cvkk_Z{51e$;AVJ;-J4mM z!A!5$fIVc=ypnW9)uG!%Mze7!26qHPl#5sOH6P*nihVUlIG@?tZ&}H&V~d88ZAJ^z z?1TR6_JgrcMyimBNlm&`X3}1H3y|HCj>1f7qOdr*&ZG8V6u$9P%(Iws@b~QZMjtvh%wJ`b%!=c55kiBGLlAn} zc8Q((Yzd@GLe134Z-eYq^OQk)x@K&+Yi403)_gTt)s<_&@s+4=(AELOX5uUHrmOLP zd>K#l=KG<5mKMARwikbvZ8|)LX<6OGWmXYKItaux!1F-v1o51rWvyl#Ca$!hZ!V@j z^X_k|fYP#A)HZgeamKo)SN5-1I@eU5y!ZCl(Cx9TWsQxEWf?SED+B`E+t%0uTRz3I-WPjt^AMuv#2?^THo6O7bl>-PU5) zH%?MVE8vJ?0CF0#bMQ2OAECQwId=x*vjP|%c@CxBK(H7HRzUTt;Ni0#u#ps*Ub4pA zM7Ek+h|SzaYGGgt%_qnvvqocbgIhl8+^EI5e5R&0tXxhmRlP6X1J}iL-Z6Jg6aj@?H>i>TLhR@w2 literal 0 HcmV?d00001 diff --git a/IBMDOS/BIN/IOCTL.OBJ b/IBMDOS/BIN/IOCTL.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..c3ad9bf6ad584a5116185737f209b7f813c94c6e GIT binary patch literal 1536 zcmY+DYiJx*6vxk<*Y51>E4#@isU;@04Iws*UD8<5v^$wcGIX=M%uL2j1CGJ^piq#_ z1_Z%uaMZ4;MG&G$z@&Z^Nx=`bf)Fz#UlbqU*D8n_iHKhew20%mvyDZD-`@Y6bMJZF zGuw;+Z&Vb!bmvMh0GP5hJ#uEO|5Sc-zW-EVWO}|na^}&F)$aj#t!A4tr&Lspw`^HC z&#AI4-~WkMm1*?3s%2czqWI#{t>J!gLakUX-QHHzA<`WNRWYijG+EV5X|hzAkW1m# z&`kYhHK`jlO?CeZqKC@TCZ)ri7@BH#%CPK;IeTcQ$0KN`sl#|?g-U9ouD$mn@B%=T zC;O;|E)tO?yHo+hSn@EcDFBHl(YA`SL~MH#EEz(DXOk@Xwe3yuglpTktS* zRZBvKCqK1qS)KqY%+bk`fwrwHLjI(mi+F(roH9XI)b#QaFZkMKKMV zi1#w7H6oS|caa#5-O)^oriz7e^pZSj5s41)&>`|(3(==pPf2^fGqfL#GVg-@T0 zK0!7Ub@7JY;P+3X{X-6R(3RT}5&*4S60QnqXeBc+o`D5v_1j;O#(M`=zQMy(UZKB*;8qhhdsmVi9Bic*ha)E{wDzTzbPX(#Sq zK%U0;iw=ujr2R{d;9b_q()t*r0IDzt&)_qU&m2Ct;VpOxDMlb64yMg RkJwE2oA~WFj{I-_{{kcOpg{lt literal 0 HcmV?d00001 diff --git a/IBMDOS/BIN/MISC.OBJ b/IBMDOS/BIN/MISC.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..7da4eac7a3b0f0a474194db6e300aa3be42dd4e1 GIT binary patch literal 4352 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 Undefined Name + ; mov cl,netbios ; 00 -> Name Number + 0016 8B0E0000 E mov cx,word ptr netbios + 001A E80000 E call return_CX + f5E_success: + 001D 33C0 xor ax,ax ; return zero + 001F E90000 E jmp return_AX_CLC + + ; + ; Set the Network Name + ; + f5E01: + ; mov name_num,ch ; Get the Network and NetBios Nos. + ; mov netbios,cl ; and save in local variables + 0022 890E0000 E mov word ptr netbios,cx + 0026 FE060000 E inc net_set_count + 002A 1E06 push ds ! push es + 002C 1F07 pop ds ! pop es ; Copy the specified name + 002E 8BF2 mov si,dx ; to internal save area + 0030 BF0000 E mov di,offset net_name + 0033 B90F00 mov cx,15 ; Copy 15 byte name leave + 0036 F3A4 rep movsb ; Terminating 00 + 0038 061F push es ! pop ds + 003A EBE1 001D jmps f5E_success + + + ; ***************************** + ; *** DOS Function 5F *** + ; *** Network Control *** + ; ***************************** + ; + Public func5F + func5F: + PC-DOS RASM-86 1.4a Source: NETWORK.A86 Page 13 + + + 003C 3C07 cmp al,07h + 003E 7404 0044 je func5F_10 + 0040 3C08 cmp al,08h + 0042 7526 006A jne func5F_40 + func5F_10: + 0044 50 push ax + 0045 8AC2 mov al,dl + 0047 E80000 E call get_ldt_raw + 004A 58 pop ax + 004B 7215 0062 jc func5F_30 + 004D 26837F4501 cmp es:word ptr LDT_PDT[bx],1 + 0052 720E 0062 jb func5F_30 + 0054 26804F4440 or es:byte ptr LDT_FLAGS+1[bx],LFLG_PHYSICAL/100h + 0059 3C07 cmp al,07h + 005B 7405 0062 je func5F_30 + 005D 26806744BF and es:byte ptr LDT_FLAGS+1[bx],(not LFLG_PHYSICAL)/100h + func5F_30: + 0062 731A 007E jnc func5F_OK + 0064 B8F1FF mov ax,ED_DRIVE + 0067 E90000 E jmp error_exit + + func5F_40: + 006A B81E11 mov ax,I2F_REDIR_5F ; magic int 2F number + + Public func5F_common + func5F_common: + 006D 1E push ds + 006E FF360000 E push int21AX ; AX passed on the stack.. + 0072 06 push es + 0073 E80000 E call reload_ES ; get the segment registers + 0076 1F pop ds ; back to entry state + 0077 F9 stc ; assume it will fail + 0078 CD2F int 2fh ; pass it on to MSNET + 007A 1F pop ds ; throw away word on the stack + 007B 1F pop ds + 007C 7203 0081 jc func5F_error + func5F_OK: + 007E E90000 E jmp return_AX_CLC ; return the result + func5F_error: + 0081 F7D8 neg ax ; our error convention is negative.. + 0083 E90000 E jmp error_exit ; Error for all sub functions + + PCMODE_DATA DSEG WORD + + extrn net_name:byte + extrn net_set_count:byte + extrn name_num:byte + extrn netbios:byte + extrn int21AX:word + + end + + PC-DOS RASM-86 1.4a Source: NETWORK.A86 Page 14 + + + +End of assembly. Number of errors: 0. Use factor: 14% + + + \ No newline at end of file diff --git a/IBMDOS/BIN/NETWORK.OBJ b/IBMDOS/BIN/NETWORK.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..d2a7a7b38cb1cfedf2f5a2a67bc6208e566b8660 GIT binary patch literal 896 zcmb`EO=}ZT6o${qWWMs*sMT7fsURUBQBt*bk%iNlJ56Y2rp!#z(alg?*o`1*+_=zy zgJ>h-N<_NoLj3`*>c)y>>r!wlBDM&Eb|H%NdT+++A8>Im&%Ez@&SCE9sUX|LUv%7g z^Uh%aa5c}W%uG*KPo7zttWH&|rA}q$T;btc0FeZ~t0i^EAfo4M`h3#ReC^+rS!L;om0a zkUTP%-kZrXm2ZP8;4@ADDFII~ zssp4&RAR~qsK#zqz%nCNn-lO;?B+#G#@dL0A7iZ`AuN zuH%LzX!s~MY=5e%1*q`2tyu)qbBvmXAG+EiFKarQ5fYCjm>b$H3;XLgAOTRrj?z84 zQ7mjPLI3AVfENnvJniQIwg67Q+6K7Gcvk|Lkcx8u+a^ooVdsfd{QSNqcat^cT4`bR zH46uw(bBD(1UtD>&oRz3Q!Mo^8=EWR8(%5wvoTSapwj>n%NBpUIkmD@fkD14560Sw z=!lt&CQTe1Zzl%jwlJu+<*05d(XuHHuC}G9YpSq50*UKTEOrFe?fW}+_108~L=&Tw PDL!9if72cRFZ=%uk*?n% literal 0 HcmV?d00001 diff --git a/IBMDOS/BIN/NETWORK.SYM b/IBMDOS/BIN/NETWORK.SYM new file mode 100644 index 0000000..69b68b6 --- /dev/null +++ b/IBMDOS/BIN/NETWORK.SYM @@ -0,0 +1,83 @@ + 0000 VARIABLES +0000 DMD_ID 0006 DMD_IDLE_FLAGS 0003 DMD_LEN 0008 DMD_NAME +0001 DMD_PSP 0000 FDOS_DATA 0000 INT21AX 0000 NAME_NUM 0000 NETBIOS +0000 NET_NAME 0000 NET_SET_COUNT 0001 REG_AH 0000 REG_AL +0000 REG_AX 0003 REG_BH 0002 REG_BL 000C REG_BP 0002 REG_BX +0005 REG_CH 0004 REG_CL 0014 REG_CS 0004 REG_CX 0007 REG_DH +000A REG_DI 0006 REG_DL 000E REG_DS 0006 REG_DX 0010 REG_ES +0016 REG_FLAGS 0012 REG_IP 0008 REG_SI + +0000 NUMBERS +0004 ACT_ABORT 0002 ACT_DELAY 0006 ACT_IGNORE 0001 ACT_RETRY 0005 ACT_TERM +0007 ACT_URETRY 0003 ACT_USER 0001 CARRY_FLAG 0007 CLASS_APPLIC +0003 CLASS_AUTHOR 000C CLASS_EXISTS +0009 CLASS_FORMAT 0005 CLASS_HARDWARE +0004 CLASS_INTERNAL 000A CLASS_LOCKED 0008 CLASS_LOST +000B CLASS_MEDIA 0001 CLASS_RESOURCE +0006 CLASS_SYSTEM 0002 CLASS_TEMP 000D CLASS_UNKNOWN +0004 DCNTRL_COUNT 0000 DCNTRL_DSADD +0000 DCNTRL_DSOFF 0002 DCNTRL_DSSEG 0006 DCNTRL_LEN +0020 DHAT_BIN 0001 DHAT_CIN 0040 DHAT_CLEAN 0008 DHAT_CLK 0002 DHAT_COT +0080 DHAT_DEV 001F DHAT_DRVMSK 1000 DHAT_LOCAL +0800 DHAT_NETPRN 0004 DHAT_NUL 0040 DHAT_READY +8000 DHAT_REMOTE 4000 DHAT_TIMEOK 4000 DHM_COMMIT +0000 DHM_COMPAT 0010 DHM_DENY_ALL 0040 DHM_DENY_NONE +0030 DHM_DENY_READ 0020 DHM_DENY_WRITE 8000 DHM_FCB +0080 DHM_LOCAL 2000 DHM_NOCRIT 0000 DHM_RO 0002 DHM_RW 000F DHM_RWMSK +0070 DHM_SHAREMSK 0001 DHM_WO 0005 DHNDL_ATTR 0035 DHNDL_BLK +000B DHNDL_BLK1 0000 DHNDL_COUNT 000F DHNDL_DATE +0004 DHNDL_DATRB 001B DHNDL_DBLK 001E DHNDL_DCNTHI +001F DHNDL_DCNTLO 0007 DHNDL_DEVOFF +0007 DHNDL_DEVPTR 0009 DHNDL_DEVSEG 0028 DHNDL_EXT +0019 DHNDL_IDX 003B DHNDL_LEN 0002 DHNDL_MODE 0020 DHNDL_NAME 0015 DHNDL_POS +0017 DHNDL_POSHI 0015 DHNDL_POSLO 0031 DHNDL_PSP +002B DHNDL_SFT 0033 DHNDL_SHARE 0011 DHNDL_SIZE +0013 DHNDL_SIZEHI 0011 DHNDL_SIZELO 000D DHNDL_TIME +002F DHNDL_UID 0005 DHNDL_WATTR 0400 DIR_FLAG +0008 DMD_NAME_LEN FFFB ED_ACCESS FFF4 ED_ACC_CODE +FFAB ED_ASSIGN FFEA ED_BADCMD FFE9 ED_BADDATA FFE6 ED_BADMEDIA +FFE8 ED_BADRHLEN FFE7 ED_BADSEEK FFEC ED_BADUNIT FFF7 ED_BLOCK +FFA6 ED_COMPONENT FFF3 ED_DATA FFEF ED_DEVICE FFF0 ED_DIR +FFDE ED_DISKCHG FFF9 ED_DMD FFF1 ED_DRIVE FFF6 ED_ENVIRON FFB0 ED_EXISTS +FFAD ED_FAIL FFFE ED_FILE FFF5 ED_FORMAT FFFF ED_FUNCTION +FFE1 ED_GENFAIL FFFC ED_HANDLE FFFA ED_H_MATCH FFA6 ED_LASTERROR +FFDF ED_LOCKFAIL FFAE ED_MAKE FFF8 ED_MEMORY FFCE ED_NET +FFBF ED_NETACCESS FFB3 ED_NETCOMM FFA7 ED_NETFUNC FFB1 ED_NETLOG +FFB7 ED_NETPWD FFB5 ED_NETREQ FFB2 ED_NETSRVR FFB4 ED_NETTIME FFB6 ED_NETVER +FFA8 ED_NETWRITE FFDD ED_NOFCBS FFDC ED_NOLOCKS FFE4 ED_NOPAPER +FFEB ED_NOTREADY FFA9 ED_PARAM FFAA ED_PASSWORD +FFFD ED_PATH FFED ED_PROTECT FFE2 ED_RDFAIL FFE5 ED_RNF FFEE ED_ROOM +FFE0 ED_SHAREFAIL FFAC ED_STRUCT FFE3 ED_WRFAIL 0002 ERR_ABORT +0003 ERR_FAIL 0000 ERR_IGNORE 0001 ERR_RETRY 0000 FALSE 1105 I2F_CHDIR +1106 I2F_CLOSE 1107 I2F_COMMIT 1117 I2F_CREATE 1126 I2F_CTLP +1124 I2F_CTLP_ERR 1113 I2F_DEL 1120 I2F_FLUSH +110F I2F_GET_ATTR 110A I2F_LOCK 1121 I2F_LSEEK 1103 I2F_MKDIR +1116 I2F_OPEN 111D I2F_PCLOSE 1123 I2F_PPATH 1100 I2F_PRESCENCE +1122 I2F_PTERM 1108 I2F_READ 1125 I2F_REDIR_5D +111F I2F_REDIR_5E 111E I2F_REDIR_5F 1111 I2F_REN +1101 I2F_RMDIR 110E I2F_SET_ATTR 111B I2F_SFIRST 111C I2F_SNEXT +110C I2F_SPACE 110B I2F_UNLOCK 1109 I2F_WRITE 1118 I2F_XCREATE +1119 I2F_XSFIRST 0001 IDLE_COMMAND +FFFF IDLE_DETECT C000 IDLE_DISABLE +0002 IDLE_DOSFUNC 8000 IDLE_INIT 0004 IDLE_INT28 4000 IDLE_ON +004D IDM 005A IDZ 0200 INT_FLAG 0049 LDT_BLK 004D LDT_DRV +0043 LDT_FLAGS 0058 LDT_LEN 0000 LDT_NAME 0045 LDT_PDT 004B LDT_ROOT +004F LDT_ROOTLEN 2000 LFLG_JOINED +8000 LFLG_NETWRKD 4000 LFLG_PHYSICAL 1000 LFLG_SUBST +0002 LOC_BLOCK 0004 LOC_CHAR 0005 LOC_MEMORY 0003 LOC_NET +0001 LOC_UNKNOWN 000D MAX_FILELEN +0050 MAX_PATHLEN 0040 NO_CRIT_ERRORS 0800 OFLW_FLAG +0008 OK_FAIL 0020 OK_IGNORE 0010 OK_RETRY 0018 OK_RF 0030 OK_RI +0038 OK_RIF 0004 PROC_DEVIN 0001 PROC_IDLE 0002 PROC_INT28 0003 PROC_KEYIN +0080 SIGN_FLAG 00C0 STACK_SIZE 0001 TERM_BREAK 0002 TERM_ERROR +0000 TERM_NORMAL 0003 TERM_RESIDENT FFFF TRUE +0006 TRUE_VERSION 0040 ZERO_FLAG 0001 __RASM__ + +0000 LABELS +0000 ERROR_EXIT 000C F5E00 0022 F5E01 001D F5E_SUCCESS +0000 FUNC5E 003C FUNC5F 0044 FUNC5F_10 0062 FUNC5F_30 006A FUNC5F_40 +006D FUNC5F_COMMON 0081 FUNC5F_ERROR 007E FUNC5F_OK +0000 GET_LDT_RAW 0000 RELOAD_ES 0000 RETURN_AX_CLC +0000 RETURN_CX +_RI +0038 OK_RIF 0004 PROC_DEVIN 0001 PROC_IDLE 0002 PROC_INT28 0003 PROC_KEYIN \ No newline at end of file diff --git a/IBMDOS/BIN/PCMIF.OBJ b/IBMDOS/BIN/PCMIF.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..78ceb9a0c57c4929e285b15423a924086949d8a0 GIT binary patch literal 4352 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 literal 0 HcmV?d00001 diff --git a/IBMDOS/BIN/PROCESS.OBJ b/IBMDOS/BIN/PROCESS.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..342ee709714e0c9795aa367386df793239046898 GIT binary patch literal 3968 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 Osyh0}lU@CP`~SZK6-Fcg literal 0 HcmV?d00001 diff --git a/IBMDOS/BIN/SUPPORT.LST b/IBMDOS/BIN/SUPPORT.LST new file mode 100644 index 0000000..98d63a9 --- /dev/null +++ b/IBMDOS/BIN/SUPPORT.LST @@ -0,0 +1,875 @@ + PC-DOS RASM-86 1.4a Source: SUPPORT.A86 Page 1 + + += 0001 __RASM__ EQU 1 + + ; File : $SUPPORT.A86$ + ; + ; Description : + ; + ; Original Author : DIGITAL RESEARCH + ; + ; Last Edited By : $CALDERA$ + ; + ;-----------------------------------------------------------------------; + ; Copyright Work of Caldera, Inc. All Rights Reserved. + ; + ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, + ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. + ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES + ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF + ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO + ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE + ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE + ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, + ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, + ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, + ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF + ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT + ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND + ; CIVIL LIABILITY. + ;-----------------------------------------------------------------------; + ; + ; *** Current Edit History *** + ; *** End of Current Edit History *** + ; + ; $Log$ + ; SUPPORT.A86 1.11 93/11/29 13:39:28 + ; Don't rely on DS when return_ called + ; ENDLOG + ; + ; The following Support routines are provided for both the + ; handle and FCB functions which require critical error handler + ; support. + ; + ; 15 Jun 88 Modify the SYSDAT and SUPERVISOR variables to enable + ; the relocation of the BDOS into high memory + ; 5 Jan 89 Only set PCKBD mode if we own the default console + ; 9 Mar 89 Support a split PCMODE and SYSDAT Segments + ; 22 Sep 89 LDT support routine added + ; 29 Jan 90 Int 2A critical section support added to dpbdos_entry + ; 7 Mar 90 Convert to register preserved function calls + ; 4 May 90 DRDOS int3x handlers removed (they are pointed to IRET + ; in PCMODE_DATA by INIT.PCM) + ; 12 Dec 90 keep error server number inverted so local = 0, more compatible + + PC-DOS RASM-86 1.4a Source: SUPPORT.A86 Page 2 + + + ; += include pcmode.equ += ; File : $PCMODE.EQU$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += ; This file contains all the general purpose definitions += ; and equates used by the PCMODE Module. += ; += += FFFF TRUE equ 0FFFFh ; value of TRUE += 0000 FALSE equ 0 ; value of FALSE += += 0006 TRUE_VERSION equ 6 += += FFFF IDLE_DETECT equ TRUE ; Check for IDLE Process's += += if IDLE_DETECT += 0001 IDLE_COMMAND equ 0001h ; Command Processor Active += 0002 IDLE_DOSFUNC equ 0002h ; DOS Function Called += 0004 IDLE_INT28 equ 0004h ; INT 28 Called += += 4000 IDLE_ON equ 4000h ; ReSet when Idle Checking Enabled + PC-DOS RASM-86 1.4a Source: SUPPORT.A86 Page 3 + + += 8000 IDLE_INIT equ 8000h ; ReSet when $IDLE$ Loaded and Active += C000 IDLE_DISABLE equ IDLE_INIT + IDLE_ON += += 0001 PROC_IDLE equ 0001 ; Process is IDLE += 0002 PROC_INT28 equ 0002 ; INT28 Polling Loop += 0003 PROC_KEYIN equ 0003 ; Keyboard Input += 0004 PROC_DEVIN equ 0004 ; Device Input Routine += endif += += += 00C0 STACK_SIZE equ 192 ; Local Stack Size (Levels) += 0050 MAX_PATHLEN equ 80 ; Maximum Path length += 000D MAX_FILELEN equ 13 += += ; += ; DOS process termination Codes += ; += 0000 TERM_NORMAL equ 0 ; Normal Termination += 0001 TERM_BREAK equ 1 ; Termination by Control Break += 0002 TERM_ERROR equ 2 ; Termination by Critical Error += 0003 TERM_RESIDENT equ 3 ; Terminate and Stay Resident += += ; += ; Critical Error responses from the default INT 24 handler and += ; the DO_INT24 routine. += ; += 0000 ERR_IGNORE equ 0 ; Ignore Error += 0001 ERR_RETRY equ 1 ; Retry the Operation += 0002 ERR_ABORT equ 2 ; Terminate the Process += 0003 ERR_FAIL equ 3 ; Fail Function += ; += 0008 OK_FAIL equ 0000$1000b ; Fail is a Valid Response += 0010 OK_RETRY equ 0001$0000b ; Retry is a Valid Response += 0020 OK_IGNORE equ 0010$0000b ; Ignore is a valid Response += 0038 OK_RIF equ 0011$1000b ; All Responsese are Valid += 0030 OK_RI equ 0011$0000b ; Retry and Ignore are Valid += 0018 OK_RF equ 0001$1000b ; Retry and Fail are Valid += ; += 0040 NO_CRIT_ERRORS equ 0100$0000b ; critical error shouldn't be generated += ; warning - must match FDOS.A86 += ; + PC-DOS RASM-86 1.4a Source: SUPPORT.A86 Page 4 + + += eject += ; The following equates define the format in which the users registers += ; are saved on the stack. This format is also seen by an application += ; when a critical error occurs. += ; += CodeMacro POP$DOS ; Pop User Registers a la MS-DOS += db 058h ! db 05Bh ; pop AX ! pop BX += db 059h ! db 05Ah ; pop BX ! pop CX += db 05Eh ! db 05Fh ; pop SI ! pop DI += db 05Dh ; pop BP += db 01Fh ! db 007h ; pop DS ! pop ES += EndM += += CodeMacro PUSH$DOS ; Push User Registers += db 006h ! db 01Eh ; push ES ! push DS += db 055h ; push BP += db 057h ! db 056h ; push DI ! push SI += db 052h ! db 051h ; push DX ! push CX += db 053h ! db 050h ; push BX ! push AX += EndM += += 0000 reg_AX equ word ptr .00 += 0000 reg_AL equ byte ptr .00 += 0001 reg_AH equ byte ptr .01 += += 0002 reg_BX equ word ptr .02 += 0002 reg_BL equ byte ptr .02 += 0003 reg_BH equ byte ptr .03 += += 0004 reg_CX equ word ptr .04 += 0004 reg_CL equ byte ptr .04 += 0005 reg_CH equ byte ptr .05 += += 0006 reg_DX equ word ptr .06 += 0006 reg_DL equ byte ptr .06 += 0007 reg_DH equ byte ptr .07 += += 0008 reg_SI equ word ptr .08 += 000A reg_DI equ word ptr .10 += 000C reg_BP equ word ptr .12 += += 000E reg_DS equ word ptr .14 += 0010 reg_ES equ word ptr .16 += += 0012 reg_IP equ word ptr .18 += 0014 reg_CS equ word ptr .20 += 0016 reg_FLAGS equ word ptr .22 += += ; Processor Flags += 0001 CARRY_FLAG equ 0001h ; Carry Flag += 0040 ZERO_FLAG equ 0040h ; Zero Flag += 0080 SIGN_FLAG equ 0080h ; Sign Flag + PC-DOS RASM-86 1.4a Source: SUPPORT.A86 Page 5 + + += 0200 INT_FLAG equ 0200h ; Interrupt Flag += 0400 DIR_FLAG equ 0400h ; Direction Flag += 0800 OFLW_FLAG equ 0800h ; OverFlow Flag += += 0000 DMD_ID equ es:byte ptr .0 ; id code ('M' or 'Z') += 0001 DMD_PSP equ es:word ptr .1 ; owner of memory block += 0003 DMD_LEN equ es:word ptr .3 ; length of memory block += 0006 DMD_IDLE_FLAGS equ es:word ptr .6 ; idle flags live here += 0008 DMD_NAME equ es:byte ptr .8 ; ASCIIZ name field += 0008 DMD_NAME_LEN equ 8 ; 8 Bytes long += 004D IDM equ 'M' ; not last id code += 005A IDZ equ 'Z' ; last id code += += PCMCODE GROUP PCM_HEADER, PCM_CODE, BDOS_CODE, PCM_RODATA += PCMCODE GROUP PCM_HISTORY, PCM_ICODE, PCM_CODEND += += PCM_HEADER CSEG PARA += PCM_CODE CSEG BYTE += PCM_RODATA CSEG WORD += BDOS_CODE CSEG WORD += PCM_HISTORY CSEG BYTE += PCM_ICODE CSEG BYTE += PCM_CODEND CSEG PARA += += += PCMDATA GROUP PCMODE_DATA, FDOS_DSEG, FIXED_DOS_DATA += PCMDATA GROUP PCMODE_CODE, GLOBAL_DATA, BDOS_DATA, PCMODE_DSIZE += += PCMODE_DATA DSEG WORD ; DOS Data += FDOS_DSEG DSEG WORD COMMON ; FDOS Parameter Block +=0000 fdos_data rw 7 += FIXED_DOS_DATA CSEG WORD 'DATA' ; Fixed DOS Data Area += PCMODE_CODE CSEG WORD 'DATA' ; DATA relative CODE += GLOBAL_DATA DSEG WORD ; GLOBAL DOS DATA (Process Independant) += BDOS_DATA DSEG WORD ; BDOS Data Area += PCMODE_DSIZE DSEG PARA ; End of DOS Data Area + += include fdos.def += ; File : $FDOS.DEF$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES + PC-DOS RASM-86 1.4a Source: SUPPORT.A86 Page 6 + + += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += += 0048 FD_DISKINFO equ 48h += 0049 FD_FLUSH equ 49h += 004A FD_SELECT equ 4Ah += 004B FD_EXEC equ 4Bh += 004C FD_EXIT equ 4Ch += 004D FD_FCB equ 4Dh += 0050 FD_COMMIT equ 50H += 0051 FD_NEW equ 51h += 0052 FD_LOCK equ 52h += 0054 FD_DDIO equ 54h += 0055 FD_EXPAND equ 55h += 0058 FD_REOPEN equ 58h += += 0007 FDOS_MAXPARM equ 7 ; Maximum FDOS Parameter Length (WORDS) += += 0000 FD_FUNC equ fdos_data += += 0002 FD_DRIVE equ fdos_data + 2 += 0004 FD_DPB equ dword ptr fdos_data + 4 += 0004 FD_DPBOFF equ fdos_data + 4 += 0006 FD_DPBSEG equ fdos_data + 6 += 0008 FD_ADJUST equ fdos_data + 8 += += 0002 FD_NAME equ dword ptr fdos_data + 2 += 0002 FD_NAMEOFF equ fdos_data + 2 += 0004 FD_NAMESEG equ fdos_data + 4 += += 0006 FD_MODE equ fdos_data + 6 += += 0002 FD_HANDLE equ fdos_data + 2 += += 0004 FD_BUF equ dword ptr fdos_data + 4 + PC-DOS RASM-86 1.4a Source: SUPPORT.A86 Page 7 + + += 0004 FD_BUFOFF equ fdos_data + 4 += 0006 FD_BUFSEG equ fdos_data + 6 += += 0008 FD_COUNT equ fdos_data + 8 += += 0004 FD_OFFSET equ dword ptr fdos_data + 4 += += 0008 FD_METHOD equ fdos_data + 8 += += 0006 FD_FLAG equ fdos_data + 6 += += 0008 FD_ATTRIB equ fdos_data + 8 += += 0004 FD_PATH equ dword ptr fdos_data + 4 += 0004 FD_PATHOFF equ fdos_data + 4 += 0006 FD_PATHSEG equ fdos_data + 6 += += 0002 FD_ONAME equ dword ptr fdos_data + 2 += 0002 FD_ONAMEOFF equ fdos_data + 2 += 0004 FD_ONAMESEG equ fdos_data + 4 += += 000A FD_NNAME equ dword ptr fdos_data + 10 += 000A FD_NNAMEOFF equ fdos_data + 10 += 000C FD_NNAMESEG equ fdos_data + 12 += += 0004 FD_SFLAG equ fdos_data + 4 += 0006 FD_DATE equ fdos_data + 6 += 0008 FD_TIME equ fdos_data + 8 += += 0008 FD_LENGTH equ dword ptr fdos_data + 8 += 000C FD_LFLAG equ word ptr fdos_data + 12 += += 0004 FD_NEWHND equ fdos_data + 4 += += 0002 FD_FCBADR equ dword ptr fdos_data + 2 += 0002 FD_FCBOFF equ fdos_data + 2 += 0004 FD_FCBSEG equ fdos_data + 4 += += 0006 FD_FCBCNT equ fdos_data + 6 += 0008 FD_FCBFUNC equ fdos_data + 8 += += 0002 FD_PSPSEG equ fdos_data + 2 += += 0002 FD_BPBOFF equ fdos_data + 2 += 0004 FD_BPBSEG equ fdos_data + 4 += 0006 FD_DDSCOFF equ fdos_data + 6 += 0008 FD_DDSCSEG equ fdos_data + 8 += += 0004 FD_IOCTLFUNC equ fdos_data + 4 += 0006 FD_IOCTLSTAT equ fdos_data + 6 += += 0002 FD_NUMOPEN equ fdos_data + 2 + PC-DOS RASM-86 1.4a Source: SUPPORT.A86 Page 8 + + += += 0002 FD_DDIO_DRV_OP equ fdos_data + 2 += 0004 FD_DDIO_NSECTORS equ fdos_data + 4 += 0006 FD_DDIO_STARTLOW equ fdos_data + 6 += 0008 FD_DDIO_STARTHIGH equ fdos_data + 8 += 000A FD_DDIO_DMAOFF equ fdos_data + 10 += 000C FD_DDIO_DMASEG equ fdos_data + 12 += + += include i:mserror.equ += ; File : $MSERROR.EQU$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += += FFFF ED_FUNCTION equ -01 ; invalid function number += FFFE ED_FILE equ -02 ; file not found += FFFD ED_PATH equ -03 ; path not found += FFFC ED_HANDLE equ -04 ; too many open files += FFFB ED_ACCESS equ -05 ; file access denied += FFFA ED_H_MATCH equ -06 ; invalid handle number += FFF9 ED_DMD equ -07 ; memory descriptor destroyed += FFF8 ED_MEMORY equ -08 ; insufficient memory + PC-DOS RASM-86 1.4a Source: SUPPORT.A86 Page 9 + + += FFF7 ED_BLOCK equ -09 ; invalid memory block addr += FFF6 ED_ENVIRON equ -10 ; invalid environment += FFF5 ED_FORMAT equ -11 ; invalid format += FFF4 ED_ACC_CODE equ -12 ; invalid access code += FFF3 ED_DATA equ -13 ; invalid data += FFF1 ED_DRIVE equ -15 ; invalid drive specified += FFF0 ED_DIR equ -16 ; can't remove current dir += FFEF ED_DEVICE equ -17 ; not same device += FFEE ED_ROOM equ -18 ; no more files += += FFED ED_PROTECT equ -19 ; disk write protected += FFEC ED_BADUNIT equ -20 ; invalid drive specified += FFEB ED_NOTREADY equ -21 ; drive doesn't respond += FFEA ED_BADCMD equ -22 ; invalid command to driver += FFE9 ED_BADDATA equ -23 ; data CRC error += FFE8 ED_BADRHLEN equ -24 ; (shouldn't happen) += FFE7 ED_BADSEEK equ -25 ; can't seek to track += FFE6 ED_BADMEDIA equ -26 ; unrecognizable medium += FFE5 ED_RNF equ -27 ; record/sector not found += FFE4 ED_NOPAPER equ -28 ; printer error += FFE3 ED_WRFAIL equ -29 ; write failed += FFE2 ED_RDFAIL equ -30 ; read failed += FFE1 ED_GENFAIL equ -31 ; anything failed += FFE0 ED_SHAREFAIL equ -32 ; sharing conflict += FFDF ED_LOCKFAIL equ -33 ; locking conflict += FFDE ED_DISKCHG equ -34 ; invalid disk change += FFDD ED_NOFCBS equ -35 ; FCB table exhausted += FFDC ED_NOLOCKS equ -36 ; lock list items exhausted += FFCE ED_NET equ -50 ; Network Request Not Supported += += FFBF ED_NETACCESS equ -65 ; file access denied += += FFB7 ED_NETPWD equ -73 ; Server Password Error += FFB6 ED_NETVER equ -74 ; Incorrect Server version += FFB5 ED_NETREQ equ -75 ; No Local Network Resources += FFB4 ED_NETTIME equ -76 ; Network Time Out Error += FFB3 ED_NETCOMM equ -77 ; Network Communications Error += FFB2 ED_NETSRVR equ -78 ; No Server Network Resources += FFB1 ED_NETLOG equ -79 ; Server Not Logged In += += FFB0 ED_EXISTS equ -80 ; file already exists += FFAE ED_MAKE equ -82 ; Cannot Make (Files ??) += FFAD ED_FAIL equ -83 ; FAIL code returned from INT 24 += FFAC ED_STRUCT equ -84 ; Out of Structures += FFAB ED_ASSIGN equ -85 ; Already Assigned += FFAA ED_PASSWORD equ -86 ; Invalid Password += FFA9 ED_PARAM equ -87 ; Invalid Parameter += FFA8 ED_NETWRITE equ -88 ; Network write fault += FFA7 ED_NETFUNC equ -89 ; Function not supported on network += FFA6 ED_COMPONENT equ -90 ; system component not installed += FFA6 ED_LASTERROR equ -90 ; Last Error Number Used += + PC-DOS RASM-86 1.4a Source: SUPPORT.A86 Page 10 + + += += 0001 CLASS_RESOURCE equ 1 ; Out of Resource += 0002 CLASS_TEMP equ 2 ; Temporary Situation += 0003 CLASS_AUTHOR equ 3 ; Authorization Error += 0004 CLASS_INTERNAL equ 4 ; Internal System Software Error += 0005 CLASS_HARDWARE equ 5 ; Hardware Failure += 0006 CLASS_SYSTEM equ 6 ; Serious System Failure += 0007 CLASS_APPLIC equ 7 ; Application Program Error += 0008 CLASS_LOST equ 8 ; File/Item Not Found += 0009 CLASS_FORMAT equ 9 ; File/Item Illegal Format += 000A CLASS_LOCKED equ 10 ; File/Item Locked += 000B CLASS_MEDIA equ 11 ; Media Failure += 000C CLASS_EXISTS equ 12 ; Item Already Exists += 000D CLASS_UNKNOWN equ 13 ; Unknown Classification += += 0001 ACT_RETRY equ 1 ; Retry a few times then prompt user += 0002 ACT_DELAY equ 2 ; Delay then as ACT_RETRY += 0003 ACT_USER equ 3 ; Prompt user to re-enter data += 0004 ACT_ABORT equ 4 ; Clean Up then ABORT the process += 0005 ACT_TERM equ 5 ; Terminate immeadiately NO CLEAN UP += 0006 ACT_IGNORE equ 6 ; Ignore the Error += 0007 ACT_URETRY equ 7 ; Retry the error after user intervention += += 0001 LOC_UNKNOWN equ 1 ; Unknown error location += 0002 LOC_BLOCK equ 2 ; Block Device Failure += 0003 LOC_NET equ 3 ; Network Failure += 0004 LOC_CHAR equ 4 ; Related to Serial/Character devices += 0005 LOC_MEMORY equ 5 ; Failure related to Memory + += include i:doshndl.def += ; File : $DOSHNDL.DEF$ += ; += ; Description : += ; += ; Original Author : DIGITAL RESEARCH += ; += ; Last Edited By : $CALDERA$ += ; += ;-----------------------------------------------------------------------; += ; Copyright Work of Caldera, Inc. All Rights Reserved. += ; += ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, += ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. += ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES += ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF += ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO += ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE += ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE += ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, += ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, += ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, += ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF + PC-DOS RASM-86 1.4a Source: SUPPORT.A86 Page 11 + + += ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT += ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND += ; CIVIL LIABILITY. += ;-----------------------------------------------------------------------; += ; += ; *** Current Edit History *** += ; *** End of Current Edit History *** += ; += ; $Log$ += ; += ; ENDLOG += += 0000 DCNTRL_DSADD equ dword ptr 0000h += 0000 DCNTRL_DSOFF equ word ptr 0000h += 0002 DCNTRL_DSSEG equ word ptr 0002h += 0004 DCNTRL_COUNT equ word ptr 0004h += 0006 DCNTRL_LEN equ 6 += += 0000 DHNDL_COUNT equ word ptr 00h ; 00 - Usage Count += 0002 DHNDL_MODE equ word ptr 02h ; 02 - File Mode += += 8000 DHM_FCB equ 8000h ; marks as FCB += 4000 DHM_COMMIT equ 4000h ; auto-commit file += 2000 DHM_NOCRIT equ 2000h ; no critical errors += 0080 DHM_LOCAL equ 10000000b ; file is not inherited += 0070 DHM_SHAREMSK equ 01110000b ; sharing bits += 0000 DHM_COMPAT equ 00000000b += 0010 DHM_DENY_ALL equ 00010000b ; exclusive - deny all += 0020 DHM_DENY_WRITE equ 00100000b += 0030 DHM_DENY_READ equ 00110000b += 0040 DHM_DENY_NONE equ 01000000b += 000F DHM_RWMSK equ 00001111b ; read write bits += 0002 DHM_RW equ 00000010b ; file opened read/write += 0001 DHM_WO equ 00000001b ; file opened write only += 0000 DHM_RO equ 00000000b ; file opened read only += += ; += ; 01h to 03h To be Determined += ; += 0004 DHNDL_DATRB equ byte ptr 04h ; Disk attribute byte += 0005 DHNDL_ATTR equ byte ptr 05h ; Attribute Byte += 0005 DHNDL_WATTR equ word ptr 05h ; Attribute Word += += 8000 DHAT_REMOTE equ 8000h ; set if file remote += 4000 DHAT_TIMEOK equ 4000h ; set if timestamp up to date += 1000 DHAT_LOCAL equ 1000h ; file is not inherited += 0800 DHAT_NETPRN equ 0800h ; device is networked printer += 0080 DHAT_DEV equ 0080h ; device/file bit += 0040 DHAT_READY equ 0040h ; ready/not ready bit += 0040 DHAT_CLEAN equ 0040h ; this bit CLEAR if dirty += 0020 DHAT_BIN equ 0020h ; raw/cooked bit += 001F DHAT_DRVMSK equ 001Fh ; drive in bottom bits + PC-DOS RASM-86 1.4a Source: SUPPORT.A86 Page 12 + + += 0008 DHAT_CLK equ 0008h ; -reserved- += 0004 DHAT_NUL equ 0004h ; handle is null device += 0002 DHAT_COT equ 0002h ; handle is console output device += 0001 DHAT_CIN equ 0001h ; handle is console input device += += 0007 DHNDL_DEVPTR equ dword ptr 07h ; 07 - pointer to device += 0007 DHNDL_DEVOFF equ word ptr 07h ; 07 - offset of device += 0009 DHNDL_DEVSEG equ word ptr 09h ; 09 - segment of device += 000B DHNDL_BLK1 equ word ptr 0Bh ; 0B - first cluster in file += 000D DHNDL_TIME equ word ptr 0Dh ; 0D - file time stamp += 000F DHNDL_DATE equ word ptr 0Fh ; 0F - file date stamp += 0011 DHNDL_SIZE equ dword ptr 11h ; 11 - file length += 0011 DHNDL_SIZELO equ word ptr 11h += 0013 DHNDL_SIZEHI equ word ptr 13h += 0015 DHNDL_POS equ dword ptr 15h ; 15 - current file position += 0015 DHNDL_POSLO equ word ptr 15h += 0017 DHNDL_POSHI equ word ptr 17h += 0019 DHNDL_IDX equ word ptr 19h ; 19 - relative cluster within file of last + read += 001B DHNDL_DBLK equ word ptr 1Bh ; 1B - cluster # of dir entry += 001E DHNDL_DCNTHI equ byte ptr 1Eh ; 1E - dir offset # within cluster += 001F DHNDL_DCNTLO equ byte ptr 1Fh ; 1F - dir offset # within cluster += 0020 DHNDL_NAME equ byte ptr 20h ; 20 - File/Device Name += 0028 DHNDL_EXT equ byte ptr 28h ; 28 - File extension += 002B DHNDL_SFT equ dword ptr 2Bh ; 2B - pointer to previous SFT += 002F DHNDL_UID equ word ptr 2Fh ; 2F - Owning Machine ID += 0031 DHNDL_PSP equ word ptr 31h ; 31 - Owning PSP += 0033 DHNDL_SHARE equ word ptr 33h ; 33 - Offset of sharing record += 0035 DHNDL_BLK equ word ptr 35h ; 35 - absolute cluster of last read += ; 37 - dword reserved for IFS += 003B DHNDL_LEN equ 3Bh += += ; With DOS 3 structures _DBLK is a 16 bit += += += ; Logical Drive Table format += 0000 LDT_NAME equ byte ptr 00h ; 00 - Ascii Name field += 0043 LDT_FLAGS equ word ptr 43h ; 43 - Flag field += 0045 LDT_PDT equ dword ptr 45h ; 45 - PDT for this drive += 0049 LDT_BLK equ word ptr 49h ; 49 - directory sector += 004B LDT_ROOT equ word ptr 4bh ; 4B - virtual block root += 004D LDT_DRV equ byte ptr 4dh ; 4D - physical drive += 004F LDT_ROOTLEN equ word ptr 4fh ; 4F - Length of root portion += 0058 LDT_LEN equ 58h += += 8000 LFLG_NETWRKD equ 8000h += 4000 LFLG_PHYSICAL equ 4000h += 2000 LFLG_JOINED equ 2000h += 1000 LFLG_SUBST equ 1000h + + + PC-DOS RASM-86 1.4a Source: SUPPORT.A86 Page 13 + + + eject + PCM_CODE CSEG BYTE + extrn error_exit:near ; Standard Error Exit Routine + extrn fcberror_exit:near ; Special FCB function Error Exit + extrn fdos_entry:near + extrn get_dseg:near + + PC-DOS RASM-86 1.4a Source: SUPPORT.A86 Page 14 + + + eject + ; + ; STRLEN determines the length of the string passed in DS:SI + ; and returns the byte length in CX. + ; + Public strlen + strlen: + 0000 0657 push es ! push di + 0002 1E07 push ds ! pop es + 0004 8BFE mov di,si + 0006 B9FFFF mov cx,0FFFFh + 0009 2AC0 sub al,al + 000B F2AE repnz scasb + 000D 5F07 pop di ! pop es + 000F F7D1 not cx + 0011 49 dec cx + 0012 C3 ret + + PC-DOS RASM-86 1.4a Source: SUPPORT.A86 Page 15 + + + eject + ; + ; This routine sets the address to be returned to by the + ; FDOS when an error has occured and the RETRY request has been + ; made. The set_retry routine should be used as follows:- + ; + ; mov al,Valid Error Responses + ; call set_retry + ; Init All FDOS Parameters + ; call fdos_crit + ; + ; NB. For register model return with AX = dos_AL extended to 16 bit + + Public set_retry_RF + set_retry_RF: + 0013 B018 mov al,OK_RF ; Valid to RETRY or FAIL + ; jmp set_retry ; (the most common case) + + Public set_retry + set_retry: + 0015 A20000 E mov valid_flg,al ; Save Valid Error Reponses + 0018 8F060000 E pop retry_off ; Save the Routine Address + 001C 89260000 E mov retry_sp,sp ; and the Stack Pointer + 0020 8AC4 mov al,ah ; get function number + 0022 32E4 xor ah,ah ; make it a word + 0024 A30000 R mov FD_FUNC,ax ; save it for the FDOS + 0027 1E push ds + 0028 53 push bx + 0029 C51E0000 E lds bx,int21regs_ptr ; point to users registers + 002D 816716FEFF and reg_FLAGS[bx],not CARRY_FLAG + 0032 8A07 mov al,reg_AL[bx] ; clear CY assuming we will succeed + 0034 5B pop bx ; and reload AL with entry value + 0035 1F pop ds + 0036 FF260000 E jmp retry_off + + ; + ; The FDOS routine executes the CCP/M FDOS function using the + ; static FDOS parameter block defined in the Data Segment. + ; + Public fdos_crit + fdos_crit: + 003A E84400 0081 call fdos_nocrit + 003D 3DA6FF cmp ax,ED_LASTERROR ; Compare against last error code + 0040 731E 0060 jnb fdos_error ; if NOT below then is ERROR CODE + 0042 0BC0 or ax,ax ; Reset the Carry Flag and Return + 0044 C3 ret + + Public fdos_ax_crit + fdos_ax_crit: + 0045 E83900 0081 call fdos_nocrit + 0048 3DA6FF cmp ax,ED_LASTERROR ; Compare against last error code + 004B 7313 0060 jnb fdos_error ; if NOT below then is ERROR CODE + PC-DOS RASM-86 1.4a Source: SUPPORT.A86 Page 16 + + + 004D 0BC0 or ax,ax ; Reset the Carry Flag and Return + ; jmp return_AX_CLC ; Save the Return Code + + Public return_AX_CLC + return_AX_CLC: + ;------------- + ; On Entry: + ; AX to be returned to caller in AX + ; On Exit: + ; ES:DI trashed + ; + 004F 1E57 push ds ! push di + 0051 36C53E0000 E lds di,ss:int21regs_ptr + 0056 8905 mov reg_AX[di],ax ; return AX to caller + 0058 816516FEFF and reg_FLAGS[di],not CARRY_FLAG + 005D 5F1F pop di ! pop ds + 005F C3 ret + + + fdos_error: ; Process the Error + 0060 3B260000 E cmp sp,retry_sp ; Is the user expecting use to + 0064 7503 0069 jnz fdos_e10 ; return or use the default handler + 0066 E90000 E jmp error_exit ; If CALLed then return with the error + fdos_e10: ; to the calling routine. + 0069 F9 stc + 006A C3 ret + + Public fcbfdos_crit + fcbfdos_crit: + 006B E81300 0081 call fdos_nocrit + 006E 3DA6FF cmp ax,ED_LASTERROR ; Compare against last error code + 0071 7303 0076 jnb fcbfdos_error ; if NOT below then is ERROR CODE + 0073 0BC0 or ax,ax ; Reset the Carry Flag and Return + 0075 C3 ret + + fcbfdos_error: ; Process the Error + 0076 3B260000 E cmp sp,retry_sp ; Is the user expecting use to + 007A 7503 007F jnz fcbfdos_e10 ; return or use the default handler + 007C E90000 E jmp fcberror_exit ; If CALLed then return with the error + fcbfdos_e10: ; to the calling routine. + 007F F9 stc + 0080 C3 ret + + Public fdos_nocrit + fdos_nocrit: + 0081 BA0000 R mov dx,offset fdos_data ; point to fdos parameter block + 0084 1E06 push ds ! push es + 0086 565755 push si ! push di ! push bp + 0089 E80000 E call fdos_entry ; BDOS module entry point + 008C 0BC0 or ax,ax ; Set the Flags + 008E 5D5F5E pop bp ! pop di ! pop si + 0091 071F pop es ! pop ds + PC-DOS RASM-86 1.4a Source: SUPPORT.A86 Page 17 + + + 0093 C3 ret + + + Public reload_ES + reload_ES: + ; On Entry: + ; None + ; On Exit: + ; ES = callers ES + ; All regs preserved + ; + 0094 53 push bx + 0095 36C41E0000 E les bx,ss:int21regs_ptr + 009A 268E4710 mov es,es:reg_ES[bx] ; reload with callers ES + 009E 5B pop bx + 009F C3 ret + + + Public return_BX + return_BX: + ;--------- + ; On Entry: + ; BX to be returned to caller in BX + ; On Exit: + ; All regs preserved + ; + 00A0 1E53 push ds ! push bx + 00A2 36C5360000 E lds si,ss:int21regs_ptr + 00A7 895C02 mov reg_BX[si],bx ; return BX to caller + 00AA 5B1F pop bx ! pop ds + 00AC C3 ret + + Public return_CX + return_CX: + ;--------- + ; On Entry: + ; CX to be returned to caller in CX + ; On Exit: + ; All regs preserved + ; + 00AD 1E53 push ds ! push bx + 00AF 36C51E0000 E lds bx,ss:int21regs_ptr + 00B4 894F04 mov reg_CX[bx],cx ; return CX to caller + 00B7 5B1F pop bx ! pop ds + 00B9 C3 ret + + Public return_DX + return_DX: + ;--------- + ; On Entry: + ; DX to be returned to caller in DX + ; On Exit: + PC-DOS RASM-86 1.4a Source: SUPPORT.A86 Page 18 + + + ; All regs preserved + ; + 00BA 1E53 push ds ! push bx + 00BC 36C51E0000 E lds bx,ss:int21regs_ptr + 00C1 895706 mov reg_DX[bx],dx ; return DX to caller + 00C4 5B1F pop bx ! pop ds + 00C6 C3 ret + + PCMODE_DATA DSEG WORD + + + extrn current_psp:word + extrn DBCS_tbl:word ; double byte character set table + extrn int21regs_ptr:dword + extrn retry_off:word + extrn retry_sp:word + extrn valid_flg:byte + + + end + + +End of assembly. Number of errors: 0. Use factor: 16% +RD + + + extrn current_psp:word + \ No newline at end of file diff --git a/IBMDOS/BIN/SUPPORT.OBJ b/IBMDOS/BIN/SUPPORT.OBJ new file mode 100644 index 0000000000000000000000000000000000000000..bb65b6a5d651ca8186445ccb717d3cbb90538b19 GIT binary patch literal 1152 zcmcgqOKa3n6h1eZOp?h=A6DxFoa#dHL4{TstD=xeZl=NMWV}h!sZ}ouqToXC0pda| zbfHz$g@}lYqTogpx4J4!ifb4C0u@ID7lMc&y`G!c)?eTz`Ofz^=j7g8H$e}_o6Uel zyKk%q0A`0{gCmtqL%a5z+%z;iICk>F;K<(I2k!wi+KQN+a{`xYVPrdpbFLlPE01E+ z8AFY`p?{PbSa4}g{btn-LN4tYl7cB6zC;CyMyc&mX4UFJ)vl-3l$LtK?ehEh&sKZ$RLnB`iZF>u*N={1zP*BNE zM56$fMvM#vBe{(0QOT!_>&+8_sMQ6lH1Z+i`ZNNFaK>tt zY|gkfI{BTUwJKSB)C2vZC@fJBUBVDKK`f-!30){c6WyXD^1>|M$>Dun|90;=C`!?D zs_CIP%#Y3iDKQ$2vj(?Y+^IVOkYY$9jwGAp%PwN_hmD}~c~0mMo> zHUimmdPQ?vZ?IVIwq#UcsmdHwW#!51Rb%gIzu{v|c(~~Q)`eW`0C|8#ny}^C*@x*us zf5!Ra{DeNx4l4=nxAjh~XR2KeD+?9e;g~WtkQS)i408Vz6L~Buk2k`M>Y0fVSu;JJ ZhC3*K=PL<~m7!TYo=Y3j|K@+){~tzOHg*62 literal 0 HcmV?d00001 diff --git a/IBMDOS/BIN/SUPPORT.SYM b/IBMDOS/BIN/SUPPORT.SYM new file mode 100644 index 0000000..f684d09 --- /dev/null +++ b/IBMDOS/BIN/SUPPORT.SYM @@ -0,0 +1,93 @@ + 0000 VARIABLES +0000 CURRENT_PSP 0000 DBCS_TBL 0000 DMD_ID +0006 DMD_IDLE_FLAGS 0003 DMD_LEN 0008 DMD_NAME 0001 DMD_PSP +0000 FDOS_DATA 0008 FD_ADJUST 0008 FD_ATTRIB 0002 FD_BPBOFF 0004 FD_BPBSEG +0004 FD_BUF 0004 FD_BUFOFF 0006 FD_BUFSEG 0008 FD_COUNT 0006 FD_DATE +000A FD_DDIO_DMAOFF 000C FD_DDIO_DMASEG +0002 FD_DDIO_DRV_OP 0004 FD_DDIO_NSECTORS +0008 FD_DDIO_STARTHIGH 0006 FD_DDIO_STARTLOW 0006 FD_DDSCOFF +0008 FD_DDSCSEG 0004 FD_DPB 0004 FD_DPBOFF 0006 FD_DPBSEG 0002 FD_DRIVE +0002 FD_FCBADR 0006 FD_FCBCNT 0008 FD_FCBFUNC 0002 FD_FCBOFF 0004 FD_FCBSEG +0006 FD_FLAG 0000 FD_FUNC 0002 FD_HANDLE 0004 FD_IOCTLFUNC +0006 FD_IOCTLSTAT 0008 FD_LENGTH 000C FD_LFLAG 0008 FD_METHOD +0006 FD_MODE 0002 FD_NAME 0002 FD_NAMEOFF 0004 FD_NAMESEG 0004 FD_NEWHND +000A FD_NNAME 000A FD_NNAMEOFF 000C FD_NNAMESEG +0002 FD_NUMOPEN 0004 FD_OFFSET 0002 FD_ONAME 0002 FD_ONAMEOFF +0004 FD_ONAMESEG 0004 FD_PATH 0004 FD_PATHOFF 0006 FD_PATHSEG +0002 FD_PSPSEG 0004 FD_SFLAG 0008 FD_TIME 0000 INT21REGS_PTR +0001 REG_AH 0000 REG_AL 0000 REG_AX 0003 REG_BH 0002 REG_BL +000C REG_BP 0002 REG_BX 0005 REG_CH 0004 REG_CL 0014 REG_CS +0004 REG_CX 0007 REG_DH 000A REG_DI 0006 REG_DL 000E REG_DS +0006 REG_DX 0010 REG_ES 0016 REG_FLAGS 0012 REG_IP 0008 REG_SI +0000 RETRY_OFF 0000 RETRY_SP 0000 VALID_FLG + +0000 NUMBERS +0004 ACT_ABORT 0002 ACT_DELAY 0006 ACT_IGNORE 0001 ACT_RETRY 0005 ACT_TERM +0007 ACT_URETRY 0003 ACT_USER 0001 CARRY_FLAG 0007 CLASS_APPLIC +0003 CLASS_AUTHOR 000C CLASS_EXISTS +0009 CLASS_FORMAT 0005 CLASS_HARDWARE +0004 CLASS_INTERNAL 000A CLASS_LOCKED 0008 CLASS_LOST +000B CLASS_MEDIA 0001 CLASS_RESOURCE +0006 CLASS_SYSTEM 0002 CLASS_TEMP 000D CLASS_UNKNOWN +0004 DCNTRL_COUNT 0000 DCNTRL_DSADD +0000 DCNTRL_DSOFF 0002 DCNTRL_DSSEG 0006 DCNTRL_LEN +0020 DHAT_BIN 0001 DHAT_CIN 0040 DHAT_CLEAN 0008 DHAT_CLK 0002 DHAT_COT +0080 DHAT_DEV 001F DHAT_DRVMSK 1000 DHAT_LOCAL +0800 DHAT_NETPRN 0004 DHAT_NUL 0040 DHAT_READY +8000 DHAT_REMOTE 4000 DHAT_TIMEOK 4000 DHM_COMMIT +0000 DHM_COMPAT 0010 DHM_DENY_ALL 0040 DHM_DENY_NONE +0030 DHM_DENY_READ 0020 DHM_DENY_WRITE 8000 DHM_FCB +0080 DHM_LOCAL 2000 DHM_NOCRIT 0000 DHM_RO 0002 DHM_RW 000F DHM_RWMSK +0070 DHM_SHAREMSK 0001 DHM_WO 0005 DHNDL_ATTR 0035 DHNDL_BLK +000B DHNDL_BLK1 0000 DHNDL_COUNT 000F DHNDL_DATE +0004 DHNDL_DATRB 001B DHNDL_DBLK 001E DHNDL_DCNTHI +001F DHNDL_DCNTLO 0007 DHNDL_DEVOFF +0007 DHNDL_DEVPTR 0009 DHNDL_DEVSEG 0028 DHNDL_EXT +0019 DHNDL_IDX 003B DHNDL_LEN 0002 DHNDL_MODE 0020 DHNDL_NAME 0015 DHNDL_POS +0017 DHNDL_POSHI 0015 DHNDL_POSLO 0031 DHNDL_PSP +002B DHNDL_SFT 0033 DHNDL_SHARE 0011 DHNDL_SIZE +0013 DHNDL_SIZEHI 0011 DHNDL_SIZELO 000D DHNDL_TIME +002F DHNDL_UID 0005 DHNDL_WATTR 0400 DIR_FLAG +0008 DMD_NAME_LEN FFFB ED_ACCESS FFF4 ED_ACC_CODE +FFAB ED_ASSIGN FFEA ED_BADCMD FFE9 ED_BADDATA FFE6 ED_BADMEDIA +FFE8 ED_BADRHLEN FFE7 ED_BADSEEK FFEC ED_BADUNIT FFF7 ED_BLOCK +FFA6 ED_COMPONENT FFF3 ED_DATA FFEF ED_DEVICE FFF0 ED_DIR +FFDE ED_DISKCHG FFF9 ED_DMD FFF1 ED_DRIVE FFF6 ED_ENVIRON FFB0 ED_EXISTS +FFAD ED_FAIL FFFE ED_FILE FFF5 ED_FORMAT FFFF ED_FUNCTION +FFE1 ED_GENFAIL FFFC ED_HANDLE FFFA ED_H_MATCH FFA6 ED_LASTERROR +FFDF ED_LOCKFAIL FFAE ED_MAKE FFF8 ED_MEMORY FFCE ED_NET +FFBF ED_NETACCESS FFB3 ED_NETCOMM FFA7 ED_NETFUNC FFB1 ED_NETLOG +FFB7 ED_NETPWD FFB5 ED_NETREQ FFB2 ED_NETSRVR FFB4 ED_NETTIME FFB6 ED_NETVER +FFA8 ED_NETWRITE FFDD ED_NOFCBS FFDC ED_NOLOCKS FFE4 ED_NOPAPER +FFEB ED_NOTREADY FFA9 ED_PARAM FFAA ED_PASSWORD +FFFD ED_PATH FFED ED_PROTECT FFE2 ED_RDFAIL FFE5 ED_RNF FFEE ED_ROOM +FFE0 ED_SHAREFAIL FFAC ED_STRUCT FFE3 ED_WRFAIL 0002 ERR_ABORT +0003 ERR_FAIL 0000 ERR_IGNORE 0001 ERR_RETRY 0000 FALSE +0007 FDOS_MAXPARM 0050 FD_COMMIT 0054 FD_DDIO +0048 FD_DISKINFO 004B FD_EXEC 004C FD_EXIT 0055 FD_EXPAND +004D FD_FCB 0049 FD_FLUSH 0052 FD_LOCK 0051 FD_NEW 0058 FD_REOPEN +004A FD_SELECT 0001 IDLE_COMMAND FFFF IDLE_DETECT +C000 IDLE_DISABLE 0002 IDLE_DOSFUNC 8000 IDLE_INIT +0004 IDLE_INT28 4000 IDLE_ON 004D IDM 005A IDZ 0200 INT_FLAG +0049 LDT_BLK 004D LDT_DRV 0043 LDT_FLAGS 0058 LDT_LEN 0000 LDT_NAME +0045 LDT_PDT 004B LDT_ROOT 004F LDT_ROOTLEN +2000 LFLG_JOINED 8000 LFLG_NETWRKD +4000 LFLG_PHYSICAL 1000 LFLG_SUBST 0002 LOC_BLOCK 0004 LOC_CHAR +0005 LOC_MEMORY 0003 LOC_NET 0001 LOC_UNKNOWN +000D MAX_FILELEN 0050 MAX_PATHLEN +0040 NO_CRIT_ERRORS 0800 OFLW_FLAG 0008 OK_FAIL 0020 OK_IGNORE +0010 OK_RETRY 0018 OK_RF 0030 OK_RI 0038 OK_RIF 0004 PROC_DEVIN +0001 PROC_IDLE 0002 PROC_INT28 0003 PROC_KEYIN 0080 SIGN_FLAG 00C0 STACK_SIZE +0001 TERM_BREAK 0002 TERM_ERROR 0000 TERM_NORMAL +0003 TERM_RESIDENT FFFF TRUE 0006 TRUE_VERSION +0040 ZERO_FLAG 0001 __RASM__ + +0000 LABELS +0000 ERROR_EXIT 0000 FCBERROR_EXIT 006B FCBFDOS_CRIT +007F FCBFDOS_E10 0076 FCBFDOS_ERROR +0045 FDOS_AX_CRIT 003A FDOS_CRIT 0069 FDOS_E10 0000 FDOS_ENTRY +0060 FDOS_ERROR 0081 FDOS_NOCRIT 0000 GET_DSEG 0094 RELOAD_ES +004F RETURN_AX_CLC 00A0 RETURN_BX 00AD RETURN_CX 00BA RETURN_DX +0015 SET_RETRY 0013 SET_RETRY_RF 0000 STRLEN +IGN_FLAG 00C0 STACK_SIZE +0001 TERM_BREAK 0002 TERM_ERROR 0000 TERM_NORMAL \ No newline at end of file diff --git a/IBMDOS/BUFFERS.A86 b/IBMDOS/BUFFERS.A86 new file mode 100644 index 0000000..ee92437 --- /dev/null +++ b/IBMDOS/BUFFERS.A86 @@ -0,0 +1,1300 @@ +title 'BUFFERS - buffer handling routines' +; File : $BUFFERS.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; BUFFERS.A86 1.13 94/11/30 16:26:08 +; added support for using multiple FAT copies on reads if one fails +; BUFFERS.A86 1.12 93/08/06 16:19:11 +; make geblk public +; BUFFERS.A86 1.8 93/07/07 21:06:25 +; Smirnoff'd +; BUFFERS.A86 1.6 93/03/16 22:30:29 +; UNDELETE support changes +; BUFFERS.A86 1.5 93/03/05 18:00:26 +; Fix bug clearing cluster of new sub directory +; ENDLOG + +; Date Who Modification +; --------- --- --------------------------------------- +; 9 Sep 91 Initial version created for VLADIVAR +; 3 mar 93 correct zeroblk bug + + NOLIST + eject ! include i:fdos.equ + eject ! include bdos.equ + eject ! include i:doshndl.def + eject + LIST + +eject +PCMODE_DATA dseg + + extrn current_ddsc:dword +if DELWATCH + extrn fdos_stub:dword +endif + +BDOS_DATA dseg word + +fatrec rw 1 ; current FAT record + +fatbytl rb 1 ; low byte of split FAT entry +fatbyth rb 1 ; high byte of split FAT entry +split_fat rb 1 ; 0/FFh to indicate split entry + +eject + extrn adrive:byte + EXTRN chdblk:WORD + EXTRN clsize:WORD + EXTRN cur_dma:WORD + EXTRN cur_dma_seg:WORD + extrn dosfat:WORD + EXTRN fatadd:WORD + extrn lastcl:word + EXTRN mult_sec:WORD + EXTRN nfatrecs:WORD + EXTRN nfats:WORD + extrn pblock:dword + extrn physical_drv:byte + extrn psecsiz:word + extrn rwmode:byte ; data/directory/FAT, read/write + extrn secperclu:word + extrn bcb_root:dword ; PCMODE disk buffer root + extrn deblock_seg:word + +BDOS_CODE cseg + + extrn clus2sec:near + extrn discard_dirbuf:near + extrn fdos_error:near + extrn flush_dirbuf:near + extrn hshdscrd:near + extrn read_block:near + extrn select_adrive:near ; select drive AL + extrn write_block:near + + public alloc_cluster ; allocate data block + public alloc_chain ; allocate a chain + public buffers_check ; check if buffers exist for this drive + PUBLIC delfat ; release data blocks + PUBLIC discard_all ; discard all buffers on ADRIVE + public discard_dir ; discard directory buffers on ADRIVE + public discard_dirty ; discard directory buffers on ADRIVE + PUBLIC fixfat ; set value of FAT entry + public flush_drive ; flush buffers to disk + public locate_buffer ; locate a buffer + PUBLIC update_dat ; flush write pending buffers + public update_ddsc_free ; count free blocks on drive + PUBLIC update_dir ; update directory entry + PUBLIC update_fat ; write out modified FAT records + public zeroblk ; zero cluster (MKDIR) +if DELWATCH + public allocate_cluster ; allocate free cluster on adrive + public change_fat_entry ; write a new value into the FAT +endif + + + + +update_ddsc_free: +;---------------- +; make sure DDSC_FREE is up to date +; a by-product of this is to checksum the FAT, so we can spot changes +; of removable media + push es + les bx,ss:current_ddsc + mov cx,es:DDSC_FREE[bx] ; get current free space + jcxz update_ddsc_free30 ; if none recount to make sure + inc cx ; is count uninitialised ? (=FFFF) + jz update_ddsc_free30 ; if so better count the free space +update_ddsc_free10: + pop es + ret + +update_ddsc_free30: +; rebuild our free space count + xor ax,ax ; assume no free space yet + lea di,DDSC_BLOCK[bx] ; ES:DI -> DDSC_BLOCK + stosw ; DDSC_BLOCK = 0 + stosw ; DDSC_FREE = 0 + inc ax ; skip reserved block #'s 0 and 1 +update_ddsc_free40: + inc ax ; move to next data block # + cmp ax,lastcl ; are we beyond end of disk + ja update_ddsc_free10 ; stop if all free blocks counted + push ax ; save current index + call getblk ; get contents of FAT entry, update ZF + pop ax ; restore current FAT index + jnz update_ddsc_free40 ; try next block if not free + inc es:DDSC_FREE[bx] ; one more free block + jmps update_ddsc_free40 ; try next block + + + +discard_dirty: +;------------- +; This gets called after a write-protect error is returned + + mov ah,BF_DIRTY ; discard dirty FAT, dir & data + jmps discard_buffers + +discard_all: +;----------- + mov ah,BF_ISFAT+BF_ISDIR+BF_ISDAT + jmps discard_buffers ; discard all the buffers + +discard_dir: +;----------- + mov ah,BF_ISDIR ; dir only, leave data and FAT +; jmps discard_buffers + +discard_buffers: +;--------------- +; entry: adrive = drive to discard +; AH = flags for type to discard i.e. BF_ISFAT, etc. + + mov al,adrive ; get the work drive + call discard_dirbuf ; discard 32-byte directory buffer + call hshdscrd ; discard hashing info for drive + les si,bcb_root ; get first buffer +discard_buffers10: + cmp al,es:BCB_DRV[si] ; does the drive match? + jne discard_buffers20 ; try next one if not + test ah,es:BCB_FLAGS[si] ; does the type match? + jz discard_buffers20 ; try next one if not + mov es:BCB_DRV[si],0FFh ; else discard the buffer + mov es:BCB_FLAGS[si],0 +discard_buffers20: +if DOS5 + mov si,es:BCB_NEXT[si] ; get next buffer address + cmp si,word ptr bcb_root +else + les si,es:BCB_NEXT[si] ; get next buffer address + cmp si,0ffffh +endif + jne discard_buffers10 ; and repeat until all done +discard_buffers30: + push ds ! pop es ; restore ES and return + ret + + +;------------- +buffers_check: +;------------- +; entry: AL = drive to check (preserved) +; AH = flags +; exit: ZF = 1 if all buffers clean on this drive + + push ds ; we use DS here cause it's quicker... + lds si,ss:bcb_root ; start with most recently used +buffers_check10: + cmp al,BCB_DRV[si] ; check if for different drive + jne buffers_check20 ; skip if not our problem + test ah,BCB_FLAGS[si] ; test if its one we are looking for + jnz buffers_check30 ; return with non-zero condition +buffers_check20: +if DOS5 + mov si,BCB_NEXT[si] ; get next buffer address + cmp si,ss:word ptr bcb_root +else + lds si,BCB_NEXT[si] ; get next buffer address + cmp si,0ffffh +endif + jne buffers_check10 ; loop back if more to do + xor dx,dx ; set ZF = 1 +buffers_check30: + pop ds ; restore DS after BCBs done + ret + + +eject + +; entry: AX = first block to release +; exit: AX and following released + +delfat: ; release chain of clusters +;------ + cmp ax,2 ; is block number too small? + jb delfat10 ; yes, then stop it + cmp ax,lastcl ; is block number too large? + ja delfat10 ; yes, then stop it + push ax ; else save the number + call getblk ; get the next link + xchg ax,cx ; CX = link + pop ax ; AX = this block + sub bx,bx ; set it to 0000 + push cx ; save the link for next pass + call fixfat ; release the block + pop ax ; AX = next block or end + jmps delfat ; try again until all released +delfat10: ; all blocks in chain freed + ret + + +; On Entry: +; AX = block to read +; On Exit: +; AX = next FAT block index +; + Public getnblk + +getnblk: ;UWORD getnblk(blk); +;------- +; + push ax + call getblk ; get current setting + pop bx + jz getnblk10 ; return if something there + ret +getnblk10: + mov ax,dosfat ; if unallocated then allocate it + push ax + xchg ax,bx ; AX = blk, BX = i + call fixfat + pop ax + mov dx,ax ; DX = end of chain + xor cx,cx ; no blocks follow this one + ret + +; On Entry: +; AX = block to read +; On Exit: +; AX = contents +; ZF = 1 if AX == 0000h (disk full) + + Public getblk + +;------ +getblk: +;------ + push es ! push bx + call fatptr ; get address of block AX in buffer + mov ax,es:[bx] ; get the word from FAT + jnz getblk10 ; skip if on odd address (must be 12 bit) + cmp dosfat,FAT12 ; else check if 16 or 12 bit + je getblk20 ; skip if even 12 bit + pop bx ! pop es + test ax,ax ; update ZF + ret + +getblk10: + shr ax,1 ; shift top 12 bits down + shr ax,1 + shr ax,1 + shr ax,1 +getblk20: + and ax,0FFFh ; leave bottom 12 bits only + pop bx ! pop es + ret + + + +alloc_cluster: +;------------- +; On Entry: +; AX = previous cluster (hint for desired start) +; On Exit: +; AX = start of chain +; CY set on failure +; + mov cx,1 +; jmp alloc_chain + +alloc_chain: +;----------- +; On Entry: +; AX = previous cluster (hint for desired start) +; CX = # clusters wanted +; On Exit: +; AX = start of chain, 0 on failure +; CY set on failure +; +; We want to allocate a chain of CX clusters, AX was previous cluster +; We return with CY clear and AX = 1st cluster in chain on success, +; CY set on failure +; +; When allocating a new chain we first ask SSTOR how much physical space is +; present on the disk. Until SSTOR reports at least 2 clusters free we +; repeatedly call DELWATCH to purge files and recover space. If DELWATCH is +; unable to free space we return "disk full". +; +; When allocating a block we normally are normally given a target block to +; start searching from. We allow DELWATCH to alter this value when it frees +; space to optimise the search. +; + push ax ! push cx ; save entry parameters + call update_ddsc_free ; make sure DDSC_FREE is correct +if DELWATCH +alloc_chain10: + pop dx ! push dx ; DX = clusters wanted + les bx,ss:current_ddsc + mov cx,es:DDSC_FREE[bx] ; CX = clusters available + mov al,adrive ; AL = current drive + cmp cx,dx ; do we have enough room in the FAT ? + jb alloc_chain20 ; if not ask DELWATCH to purge + mov ah,SSTOR_SPACE ; does Superstore have room for data? + callf ss:fdos_stub ; call stub routine + test cx,cx ; are we out of space ? + jnz alloc_chain40 ; no, go ahead and allocate the chain + mov es:DDSC_FREE[bx],cx ; SSTOR says there's none, lets agree + call update_fat ; flush FAT to bring SSTOR up to date + jmps alloc_chain10 ; go round again and ask DELWATCH to + ; free up some more space + ; we loop until either SSTOR says OK + ; or DELWATCH frees all it can +alloc_chain20: + mov ah,DELW_FREECLU ; ask DELWATCH to purge a file + callf ss:fdos_stub ; call stub routine + cmp cx,es:DDSC_FREE[bx] ; can DELWATCH free up any space ? + jne alloc_chain10 ; yes, go and try again +alloc_chain30: + pop cx ! pop ax ; failure, restore stack + jmps alloc_chain80 ; and exit in failure + +alloc_chain40: +endif + pop cx ! pop ax ; restore entry parameters + push cx ; save # required + call allocate_cluster ; try to allocate 1st cluster + pop cx ; recover # required + test ax,ax ; could we ? + jz alloc_chain80 + dec cx ; one less to allocate + + push ax ; save head of chain + jcxz alloc_chain60 +alloc_chain50: + push cx + + push ax ; save current end of chain + call allocate_cluster ; allocate another cluster + pop bx ; BX = end of chain + + test ax,ax ; could we allocate anything ? + jz alloc_chain70 ; no, bail out and free partial chain + + xchg ax,bx ; AX = previous cluster, link cluster + push bx ; BX to end of the chain + call fixfat + pop ax ; AX = new end of chain + + pop cx + loop alloc_chain50 +alloc_chain60: + pop ax ; return the start of the chain as it's + clc ; long enough now... + ret + +alloc_chain70: +; We haven't enough free clusters - lets free what we allocated so far + pop cx ; discard count + pop ax ; AX = start of chain + call delfat ; release the chain +alloc_chain80: + xor ax,ax + stc ; we couldn't manage it + ret + +allocate_cluster: +;---------------- +; On Entry: +; AX = cluster to start from (AX = none known) +; On Exit: +; AX = cluster allocated +; + test ax,ax ; previous block known? + jnz alloc_cl10 ; skip if it is + push ds + lds bx,ss:current_ddsc + mov ax,ds:DDSC_BLOCK[bx] ; else continue from last allocated block + pop ds +alloc_cl10: + mov bx,lastcl ; highest block number on current disk + cmp ax,bx ; is it within disk size? + jb alloc_cl20 ; skip if it is + sub ax,ax ; start at the beginning + +alloc_cl20: + mov si,ax ; remember start of search + test ax,ax ; is this the 1st block? + jnz alloc_cl30 ; no + inc ax ; start at beginning +alloc_cl30: ; main loop: + inc ax ; skip to block after current + push ax ! push si ; quick save + call getblk ; get the content of this block + pop si ! pop ax + jz alloc_cl50 ; return if free + cmp ax,bx ; are we at the end yet? + jb alloc_cl30 ; no, try next block + xor ax,ax ; wrap to start of disk + mov bx,si ; remember starting position last time + test bx,bx ; have we been all the way round ? + jnz alloc_cl20 ; no, lets search from start + push ds + lds bx,ss:current_ddsc + mov ds:DDSC_FREE[bx],ax ; we definitely have none left + pop ds + ret ; return (0); + +alloc_cl50: + push ds ; block # AX is available + lds bx,ss:current_ddsc + mov ds:DDSC_BLOCK[bx],ax ; remember for next time + pop ds + + push ax + mov bx,dosfat ; mark this block as end of file + call fixfat ; for convenience + pop ax + + test ax,ax ; update ZF from AX + ret ; return block number + + + + + +if DELWATCH + +; Update a FAT entry with a new value + +change_fat_entry: +;---------------- +; On Entry: +; AX = block number to change +; DX = new value +; On Exit: +; None +; + mov bx,dx +; jmps fixfat +endif + +; entry: AX = block number to change +; BX = new value +; exit: DS,ES = sysdat + +;------ +fixfat: +;------ + push bx ; save new value + push ax + call update_ddsc_free ; make sure DDSC_FREE is correct + pop ax + cmp dosfat,FAT16 ; check if 16-bit FAT + jne fixfat30 ; skip if 12 bit FAT + call fatptr ; ES:BX -> FAT word to modify + pop ax ; restore new value + xor dx,dx ; get a zero (no change of space) + test ax,ax ; are we setting to 0 or non-zero? + xchg ax,es:[bx] ; set the word in the buffer + jnz fixfat10 ; skip if releasing block + test ax,ax ; check if word was 0 before + jz fixfat20 ; skip if setting 0 to 0 + inc dx ; DX = 0001h, one free cluster more + jmps fixfat15 +fixfat10: ; allocating or fixing block + test ax,ax ; check if word was 0 before + jnz fixfat20 ; skip if setting non-0 to non-0 + dec dx ; one free cluster less now +fixfat15: ; DX = change in free space (-1,1) + les si,current_ddsc + add es:DDSC_FREE[si],dx ; update free space count +fixfat20: + les si,bcb_root ; ES:SI -> buffer control block + or es:BCB_FLAGS[si],BF_DIRTY + ; mark the buffer as dirty + push ds ! pop es ; ES back to local DS + ret + + + ; We're dealing with a 12-bit FAT... + +fixfat30: ; changing 12-bit FAT entry + call fatptr ; get address of block AX in ES:BX + pop cx ; get new value + mov dx,es:[bx] ; get old value + jz fixfat40 ; skip if even word + mov ax,0FFF0h ; set mask for new value + add cx,cx ; else shift new value into top bits + add cx,cx + add cx,cx + add cx,cx + jmps fixfat50 ; set the new word +fixfat40: + mov ax,00FFFh ; set mask for new value + and cx,ax +fixfat50: ; AX = mask, CX = new, DX = old + mov si,0 ; assume space doesn't change + jnz fixfat60 ; skip if new value is zero + test dx,ax ; test if old value was zero as well + jz fixfat70 ; yes, no change in free space + inc si ; else one more block available + jmps fixfat70 +fixfat60: ; new value is non-zero + test dx,ax ; is old value non-zero as well? + jnz fixfat70 ; yes, no change in free space + dec si ; else one block less free now +fixfat70: + not ax ; flip the mask bits around + and dx,ax ; zero out old value + or dx,cx ; combine old & new value + mov es:[bx],dx ; update the FAT + xchg ax,si ; AX = free space change (-1, 0 , 1) + les si,current_ddsc + add es:DDSC_FREE[si],ax ; update free space count + les si,bcb_root ; get buffer control block + or es:BCB_FLAGS[si],BF_DIRTY + ; mark the buffer as dirty + cmp split_fat,0 ; is 12-bit entry split across sectors + je fixfat80 ; need some magic if so + ; handle a split FAT update + mov dx,fatrec ; lower sector number + inc dx ; get the upper sector + call locate_fat ; find the buffer + or es:BCB_FLAGS[si],BF_DIRTY + ; mark buffer as write pending + mov al,fatbyth ; get the high byte + mov es:BCB_DATA[si],al ; store the high byte at the beginning + mov dx,fatrec ; get the previous sector + call locate_fat ; read into memory + or es:BCB_FLAGS[si],BF_DIRTY + ; mark buffer as write pending + mov bx,psecsiz + dec bx ; BX = sector size - 1 + mov al,fatbytl ; get the low byte + mov es:BCB_DATA[si+bx],al + +fixfat80: + push ds ! pop es ; ES back to local DS + ret + + +; On Entry: +; AX = cluster number +; On Exit: +; AX preserved +; ES:BX -> address of word +; BCBSEG = segment of FAT FCB +; ZF = 1 if word on even address +; SPLIT_FAT = 0FFh if xing sector boundary +; +; CX = entries left in sector (if FAT16 - performance optimisation) +; + + Public fatptr +fatptr: +;------ + push ax ; save block number + mov bx,ax + sub dx,dx ; AX/DX = cluster # + cmp dosfat,FAT16 ; is it 16 bit FAT? + je fatptr10 + shr ax,1 ; shift for 1 1/2 byte, else 2 byte +fatptr10: + add ax,bx ; AX = offset into FAT + adc dx,0 ; AX/DX = 32 bit offset + mov cx,psecsiz ; CX = sector size + div cx ; AX = sector offset + dec cx ; CX = sector size - 1 + push dx ; DX = offset within FAT sector + push cx + add ax,fatadd ; make it absolute sector address + mov fatrec,ax ; save FAT sector for FIXFAT + xchg ax,dx ; DX = FAT sector + call locate_fat ; locate the sector + pop cx ; CX = sector size - 1 + pop bx ; restore offset within FAT sector + pop ax ; restore cluster # + sub cx,bx ; CX = bytes left in sector - 1 + lea bx,BCB_DATA[si+bx] ; ES:BX -> buffer data + cmp dosfat,FAT16 ; is it 16 bit media + jne fatptr20 ; skip if 12 bit media + shr cx,1 ; CX = extra entries left in sector + cmp ax,ax ; always set ZF = 1 + ret ; return ES:BX -> word in FAT + +fatptr20: ; it's a 12 bit FAT, is it a split FAT? + mov split_fat,0 ; assume no boundary crossing + jcxz fatptr30 ; end of sector, it's a split FAT + test al,1 ; ZF = 1 if even cluster + ret ; return ES:BX -> word in FAT buffer + +fatptr30: ; block split across two sectors + push ax + mov split_fat,0FFh ; yes, the difficult case + mov al,es:[bx] ; get the low byte from 1st sector + mov fatbytl,al ; save it for later + mov dx,fatrec ; get the FAT record is + inc dx ; get 2nd sector + call locate_fat ; read the 2nd sector + sub bx,bx + lea bx,BCB_DATA[si+bx] ; ES:BX -> buffer data + mov al,es:[bx] ; get 1st byte from next sector + mov fatbyth,al ; save the high byte + push ds ; ES = local DS + pop es + mov bx,offset fatbytl ; ES:BX -> + pop ax + test al,1 ; set non-zero condition, odd word + ret + + +if DOS5 + +; entry: DX = sector number to read +; exit: ES:SI = BCB + +locate_fat: +;---------- + mov ah,0 ; set sector address overflow = 0 + mov cx,0ff00h+BF_ISFAT ; request a FAT buffer w/ preread +locate_buffer: +;------------- +; On Entry: +; AH:DX = sector to locate +; adrive = driver +; CH = 0FFh if preread required +; CL = buffer type +; On Exit: +; ES:SI -> BCB_ +; + + mov al,adrive ; get our drive number + les si,bcb_root ; get it from the right buffer list +locate10: + cmp dx,es:BCB_REC[si] ; does our sector address match? + jne locate20 ; skip if it doesn't + cmp ah,es:BCB_REC2[si] ; does record address overflow match? + jne locate20 ; skip if not + cmp al,es:BCB_DRV[si] ; does the drive match? + je locate30 ; found if it all matches +locate20: ; MRU buffer doesn't match + mov si,es:BCB_NEXT[si] ; try the next + cmp si,word ptr bcb_root ; while there are more buffers + jne locate10 + + push ax ! push cx ! push dx ; save all registers + mov si,es:BCB_PREV[si] ; recycle least recently used buffer + call flush_buffer ; write buffer to disk + pop dx ! pop cx ! pop ax ; restore all registers + + mov es:BCB_DRV[si],al ; fill in the BCB: drive + mov es:BCB_REC[si],dx ; record low,middle + mov es:BCB_REC2[si],ah ; record high + mov es:BCB_FLAGS[si],cl ; mark as clean, ISFAT,ISDIR or ISDAT + test ch,ch ; is preread required? + jz locate30 ; skip if it isn't + call fill_buffer ; read it from disk +locate30: + cmp si,word ptr bcb_root ; are we already at the head ? + jne locate40 ; if not move ourself there + ret +locate40: + mov bx,es:BCB_NEXT[si] ; BX = next buffer + mov di,es:BCB_PREV[si] ; DI = previous buffer + mov es:BCB_NEXT[di],bx ; unlink buffer from the + mov es:BCB_PREV[bx],di ; chain + mov bx,si + xchg bx,word ptr bcb_root ; become the new head, BX = old head + mov es:BCB_NEXT[si],bx ; old chain follow us + mov di,si + xchg di,es:BCB_PREV[bx] ; back link to our buffer, DI = LRU buffer + mov es:BCB_PREV[si],di ; link ourselves to LRU buffer + mov es:BCB_NEXT[di],si ; forward link to our buffer + ret + + +; Flush all dirty FAT buffers for drive AL +; entry: AL = drive to flush (0-15) +; exit: CY = 0 if no error +; ax,bx,cx,dx,es preserved + +flush_fat: +;--------- +; entry: AL = drive for FAT flush + + mov ah,BF_ISFAT ; flush all dirty FAT buffers + jmps flush_drive ; shared code for all flushes + +;---------- +update_dir: +;---------- + call flush_dirbuf ; flush local dirbuf to buffers +;--------- +flush_dir: +;--------- + mov ah,BF_ISDIR ; write out dirty directories + jmps flush_adrive ; update the disk + + +;---------- +update_dat: +;---------- + mov ah,BF_ISDAT ; write out dirty data + jmps flush_adrive ; update the disk + +;---------- +update_fat: ;write out modified FAT buffers +;---------- + mov ah,BF_ISFAT ; flush all dirty FAT buffers +; jmp flush_adrive ; update the disk if dirty + +flush_adrive: +;------------ + mov al,adrive ; AL = currently selected drive +; jmp flush_drive + +; Write out all dirty data buffers for a given drive +; entry: AL = drive to be flushed +; AH = mask of buffer types to be flushed +; exit: AX,DX preserved +; Note: sector buffers will be written in the +; sequence in which they appear on disk (low to high) + +flush_drive: +;----------- + push es + push si +flush_drive10: + les si,bcb_root ; start with the first buffer + mov bx,0FFFFh ; assume no buffer found +flush_drive20: + test es:BCB_FLAGS[si],BF_DIRTY + ; has buffer been written to? + jz flush_drive40 ; no, do the next one + test es:BCB_FLAGS[si],ah ; is it one of these buffers? + jz flush_drive40 ; no, do the next one + cmp al,es:BCB_DRV[si] ; does the drive match? + jne flush_drive40 ; skip if wrong drive + ; we've found a buffer to flush + cmp bx,0FFFFh ; first buffer ever found in list? + jz flush_drive30 ; yes, save as new best candidate + ; else check if < previous lowest addr + mov dx,es:BCB_REC[si] + sub dx,ds:BCB_REC[bx] + mov dl,es:BCB_REC2[si] ; compare the disk addresss + sbb dl,ds:BCB_REC2[bx] + jnb flush_drive40 ; CY = 0 if new BCB higher +flush_drive30: ; else ES = best BCB so far + mov bx,si ; save it for later +flush_drive40: + mov si,es:BCB_NEXT[si] ; get next buffer address + cmp si,ss:word ptr bcb_root + jne flush_drive20 + cmp bx,0FFFFh ; did we find a dirty buffer? + jz flush_drive50 ; no, all buffers cleaned + mov si,bx ; ES:SI -> BCB to flush + call flush_buffer ; write sector to disk + jmps flush_drive10 ; check if more dirty buffers +flush_drive50: + pop si + pop es + ret + +else +; entry: DX = sector number to read +; exit: ES:SI = BCB + +locate_fat: +;---------- + mov ah,0 ; set sector address overflow = 0 + mov cx,0ff00h+BF_ISFAT ; request a FAT buffer w/ preread +locate_buffer: +;------------- +; On Entry: +; AH:DX = sector to locate +; adrive = driver +; CH = 0FFh if preread required +; CL = buffer type +; On Exit: +; ES:SI -> BCB_ +; + + + mov al,adrive ; get our drive number + les si,bcb_root ; get it from the right buffer list + mov bx,0FFFFh ; no previous buffers yet +locate1: + cmp dx,es:BCB_REC[si] ; does our sector address match? + jne locate2 ; skip if it doesn't + cmp ah,es:BCB_REC2[si] ; does record address overflow match? + jne locate2 ; skip if not + cmp al,es:BCB_DRV[si] ; does the drive match? + je locate6 ; found if it all matches +locate2: ; MRU buffer doesn't match + cmp es:BCB_LINK_OFF[si],0FFFFh + je locate3 ; are there more buffers? + push es ! pop ds + mov bx,si ; remember previous buffer + les si,es:BCB_NEXT[si] ; move on to next buffer + jmps locate1 + +locate3: ; we found the LRU buffer + push ax ! push cx ! push dx ; save all registers + + call pick_cheapest ; determine cheapest buffer + ; ES:SI -> cheapest buffer + ; DS:BX -> previous link + test es:BCB_FLAGS[si],BF_DIRTY + jz locate5 ; skip if buffer not dirty + + mov al,es:BCB_DRV[si] ; get the buffer's drive + mov ah,es:BCB_FLAGS[si] ; flush all buffers of same type + and ah,BF_ISFAT+BF_ISDIR+BF_ISDAT + push ss ! pop ds + call flush_drive ; gives us burst mode behaviour + ; but might re-arrange buffers + call find_prev ; find preceding BCB for re-link + ; so DS:BX -> BCB_LINK == ES:SI +locate5: + pop dx ! pop cx ! pop ax ; restore all registers + mov es:BCB_DRV[si],al ; fill in the BCB: drive + mov es:BCB_REC[si],dx ; record low,middle + mov es:BCB_REC2[si],ah ; record high + + mov es:BCB_FLAGS[si],cl ; mark as clean, ISFAT,ISDIR or ISDAT + test ch,ch ; is preread required? + jz locate6 ; skip if it isn't + + push es ! push si + push ds ! push bx ; save the previous buffer segment + push ss ! pop ds ; for unlinking our buffer + + call fill_buffer ; read it from disk, don't return + ; on physical errors + pop bx ! pop ds + pop si ! pop es +locate6: + cmp bx,0FFFFh ; are we the MRU buffer + jz locate9 ; yes, leave it at the head +locate8: ; arrive here if found as not 1st + mov ax,es:BCB_LINK_OFF[si] + mov BCB_LINK_OFF[bx],ax + mov ax,es:BCB_LINK_SEG[si] + mov BCB_LINK_SEG[bx],ax ; unlink this buffer + + ; we now want to attach the + push ss ! pop ds ; BCB at ES:BX to the root + mov ax,ds:word ptr bcb_root + mov es:BCB_LINK_OFF[si],ax + mov ax,ds:word ptr bcb_root+2 + mov es:BCB_LINK_SEG[si],ax + mov ds:word ptr bcb_root,si ; insert the new entry + mov ds:word ptr bcb_root+2,es +locate9: + push ss ! pop ds ; DS back to normal + ret + + +pick_cheapest: ; find cheapest replacement sector +;------------- +; entry: ES:SI = least recently used BCB +; DS:BX = previous buffer +; exit: ES, BX unmodified if LRU buffer marked as cheap +; or no other cheap buffer found +; -or- +; ES:SI, DS:BX modified to cheapest buffer and previous buffer + + test es:BCB_FLAGS[si],BF_DIRTY + ; is this buffer very expensive? + jz pck_chp5 ; return if it is cheapest "cheap" buffer + ; else is cheapest "expensive" buffer + ; find the cheapest "cheap" buffer + les si,ss:bcb_root ; as we start at the root with + mov ax,0FFFFh ; no previous buffer +pck_chp1: ; check if buffer at DS is cheap + test es:BCB_FLAGS[si],BF_ISFAT+BF_ISDIR+BF_DIRTY + ; check the "not cheap" flag + jnz pck_chp2 ; skip if expensive buffer + mov ds,dx + mov bx,ax ; remember previous buffer +pck_chp2: + mov dx,es ; remember this buffer + mov ax,si ; when we move onto next one + les si,es:BCB_NEXT[si] ; get next buffer + cmp si,0FFFFh ; end of the line ? + jne pck_chp1 ; go again if still buffers +pck_chp3: ; done all buffers + cmp bx,0FFFFh ; did we find the root ? + jne pck_chp4 + les si,ss:bcb_root ; return ES:SI -> root + ret + +pck_chp4: + les si,ds:BCB_NEXT[bx] ; ES:SI = cheapest buffer +pck_chp5: ; ES:SI = cheapest buffer + ret ; DS:BX = previous + + +find_prev: +;--------- +; entry: ES:SI = BCB to find previous buffer for +; exit: DS:BX = predecessor, BX = FFFF if first +; + mov ax,es + mov dx,si ; AX:DX -> buffer we want to find link for + mov bx,0FFFFh ; assume it's the first buffer + les si,ss:bcb_root ; we start at the root with +find_prv1: + mov cx,es + cmp dx,si ; does offset match ? + jne find_prv2 + cmp ax,cx ; does segment match ? + je find_prv3 ; yes, return this one then +find_prv2: + mov ds,cx ; remember previous link + mov bx,si + les si,es:BCB_NEXT[si] ; else have a go at the next one + jmps find_prv1 ; and repeat until match +find_prv3: + ret + +; Flush all dirty FAT buffers for drive AL +; entry: AL = drive to flush (0-15) +; exit: CY = 0 if no error +; ax,bx,cx,dx,es preserved + +flush_fat: +;--------- +; entry: AL = drive for FAT flush + + mov ah,BF_ISFAT ; flush all dirty FAT buffers + jmps flush_drive ; shared code for all flushes + +;---------- +update_dir: +;---------- + call flush_dirbuf ; flush local dirbuf to buffers +;--------- +flush_dir: +;--------- + mov ah,BF_ISDIR ; write out dirty directories + jmps flush_adrive ; update the disk + + +;---------- +update_dat: +;---------- + mov ah,BF_ISDAT ; write out dirty data + jmps flush_adrive ; update the disk + +;---------- +update_fat: ;write out modified FAT buffers +;---------- + mov ah,BF_ISFAT ; flush all dirty FAT buffers +; jmp flush_adrive ; update the disk if dirty + +flush_adrive: +;------------ + mov al,adrive ; AL = currently selected drive +; jmp flush_drive + +; Write out all dirty data buffers for a given drive +; entry: AL = drive to be flushed +; AH = mask of buffer types to be flushed +; exit: AX,DX preserved +; Note: sector buffers will be written in the +; sequence in which they appear on disk (low to high) + +flush_drive: +;----------- + push ds + push es + push bx ; save registers + push si +flush_dr0: + les si,ss:bcb_root ; start with the first buffer + mov bx,0FFFFh ; assume no buffer found +flush_dr1: + test es:BCB_FLAGS[si],BF_DIRTY + ; has buffer been written to? + jz flush_dr3 ; no, do the next one + test es:BCB_FLAGS[si],ah ; is it one of these buffers? + jz flush_dr3 ; no, do the next one + cmp al,es:BCB_DRV[si] ; does the drive match? + jne flush_dr3 ; skip if wrong drive + ; we've found a buffer to flush + cmp bx,0FFFFh ; first buffer ever found in list? + jz flush_dr2 ; yes, save as new best candidate + ; else check if < previous lowest addr + mov dl,es:BCB_REC2[si] ; compare the disk addresss + sub dl,ds:BCB_REC2[bx] + mov dx,es:BCB_REC[si] + sbb dx,ds:BCB_REC[bx] + jnb flush_dr3 ; CY = 0 if old BCB lower +flush_dr2: ; else ES = best BCB so far + push es + pop ds + mov bx,si ; save it for later +flush_dr3: + les si,es:BCB_NEXT[si] ; get next buffer address + cmp si,0ffffh + jne flush_dr1 +flush_dr4: ; DS:BX = best BCB + cmp bx,0FFFFh ; did we find a dirty buffer? + jz flush_dr5 ; no, all buffers cleaned + mov si,bx ; ES:SI -> BCB to flush + push ds ! pop es + push ss ! pop ds + call flush_buffer ; write sector to disk + jmps flush_dr0 ; check if more dirty buffers +flush_dr5: + pop si + pop bx + pop es + pop ds ; restore registers + ret + +endif + +flush_buffer: +;------------ +; entry: ES:SI = address of BCB +; exit: buffer flushed if BCB_FLAGS & BF_DIRTY + +; note: preserves AX,BX,CX,DX,ES + + test es:BCB_FLAGS[si],BF_DIRTY + ; is the buffer dirty? + jz flush_buf9 ; skip update if not modified +flush_buf1: + push es ! push si + push ax ! push bx ; else save all registers + push cx ! push dx + mov al,es:BCB_DRV[si] ; get the buffer drive + cmp al,adrive ; same as the selected drive? + je flush_buf2 ; skip if already selected + push es ; save the BCB + push si + push ds ! pop es ; ES = SYSDAT + call select_adrive ; select drive AL, ZF = 1 if logged in + pop si + pop es ; recover BCB + jc flush_buf5 ; don't flush to bad drive +flush_buf2: + mov cx,nfats ; else FAT sectors written CX times + mov al,0000$0011b ; mark as FAT write + test es:BCB_FLAGS[si],BF_ISFAT + jnz flush_buf3 ; go ahead + mov cx,1 ; directory/data written once only + mov al,0000$0101b ; mark as directory write + test es:BCB_FLAGS[si],BF_ISDIR + jnz flush_buf3 ; if not dir, must be data + mov al,0000$0111b ; mark as data buffer write +flush_buf3: ; CX = # of times to write sector + mov rwmode,al + sub ax,ax ; offset for write = 0 +flush_buf4: ; loop back to here for other copies + push ax + push cx ; save loop variables + call setup_rwx ; compute disk address + call write_buff ; write the sector + pop cx + pop ax + add ax,nfatrecs ; move to next FAT copy + loop flush_buf4 ; repeat for all FAT copies +flush_buf5: + and es:BCB_FLAGS[si],not BF_DIRTY + ; mark it as no longer dirty + mov al,physical_drv ; work drive for BDOS function + cmp al,adrive ; drive from last IO_SELDSK + je flush_buf6 ; skip if flush to work drive + ; else reselect BDOS drive after flush + push ds ! pop es ; ES = SYSDAT + call select_adrive ; reselect the work drive +flush_buf6: + pop dx ! pop cx ; restore all registers + pop bx ! pop ax + pop si ! pop es +flush_buf9: ; all done, CY = 0 if O.K. + ret + + +;------- +zeroblk: ; AX = blk +;------- + xor bx,bx ; Start at begining of cluster + call clus2sec ; translate to sector address + xchg ax,dx ; DX = low 16 bits of address + mov ah,al ; AH:DX = 24 bit sector address + mov cx,secperclu ; CX == sectors/cluster +zeroblk10: ; repeat for all sectors in cluster + push ax + push cx + push dx + mov cx,BF_ISDIR ; locate directory sector w/o preread + call locate_buffer ; this will find the cheapest buffer + or es:BCB_FLAGS[si],BF_DIRTY + lea di,BCB_DATA[si] ; ES:DI -> disk buffer + mov cx,psecsiz ; CX = byte count for REP STOSB + xor ax,ax + rep stosb ; zero the whole data buffer + pop dx + pop cx + pop ax + add dx,1 ; onto the next block + adc ah,0 + loop zeroblk10 ; repeat for all sectors in cluster + jmp flush_dir + + + + +fill_buffer: +;----------- +; On Entry: +; ES:SI = address of BCB to be filled +; On Exit: +; ES:SI preserved +; data read into buffer +; + test es:BCB_FLAGS[si],BF_ISFAT + ; are we reading a FAT sector? + jz fill_buf1 ; skip if directory/data + mov al,es:BCB_DRV[si] ; get the drive + call flush_fat ; write out all dirty buffers + mov al,0000$0010b ; reading from FAT area + jmps fill_buf3 ; go ahead +fill_buf1: + mov al,0000$0100b ; else mark as directory + test es:BCB_FLAGS[si],BF_ISDIR; test if directory read + jnz fill_buf3 ; go ahead +fill_buf2: ; neither FAT nor directory => data + mov al,0000$0110b ; mark read as data buffer read +fill_buf3: + mov rwmode,al + push cx + xor cx,cx + cmp al,0000$0010b + jne fill_buf4 + mov cx,nfats + dec cx +fill_buf4: + mov es:BCB_DRV[si],0FFh ; discard in case of error + sub ax,ax ; no offset for 2nd copy yet +fill_buf5: + push ax + call setup_rwx ; compute disk address + call read_buff ; read the sector + pop ax + jns fill_buf6 +; we can end here only if CX was non-zero above and we failed to read a +; FAT copy while there is still another one we could use + add ax,nfatrecs + dec cx + jmps fill_buf5 +fill_buf6: + pop cx + mov al,adrive ; restore the drive + mov es:BCB_DRV[si],al ; set the drive # + ret + +read_buff: +;--------- + push es + push si ; save BCB_ + push cur_dma_seg + push cur_dma ; save DMA address + push cx + mov cx,ss:deblock_seg + jcxz read_buff10 + mov cur_dma_seg,cx + mov cur_dma,0 ; xfer via deblocking buffer +read_buff10: + pop cx + call read_block + pop cur_dma ; restore DMA address + pop cur_dma_seg + js read_buff20 ; can happen only on FAT read + mov cx,ss:deblock_seg ; if deblocked, copy data + jcxz read_buff20 + les di,dword ptr cur_dma ; point to destination + mov cx,psecsiz ; CX = sector size + shr cx,1 ; CX = words per sector + push ds + mov ds,ss:deblock_seg + xor si,si ; DS:SI = source + rep movsw ; copy the data + pop ds +read_buff20: ; SF still indicating error here + pop si ; recover BCB_ + pop es + ret + +write_buff: +;---------- + push es + push si + push cur_dma_seg + push cur_dma + mov cx,ss:deblock_seg ; if deblocking we have to + jcxz write_buff10 ; copy the data first + push ds ; save SYSDAT + les si,dword ptr cur_dma ; ES:SI -> source + push es ; save source seg + mov es,cx + xor di,di ; ES:DI -> deblocking buffer + mov cur_dma_seg,es + mov cur_dma,di ; do xfer via deblocking buffer + mov cx,psecsiz ; CX = sector size + shr cx,1 ; CX = words per sector + pop ds ; DS:SI -> source + rep movsw ; copy to deblocking buffer + pop ds ; restore SYSDAT +write_buff10: + call write_block + pop cur_dma + pop cur_dma_seg + pop si + pop es + ret + +setup_rwx: +;--------- +; entry: AX = sector offset (multiple FAT writes) +; ES:SI = BCB, BCB_REC filled in +; exit: all values set up for RWXIOSIF + + mov cur_dma_seg,es ; segment = BCB_SEGMENT + lea dx,BCB_DATA[si] + mov cur_dma,dx ; offset + xor dx,dx + add ax,es:BCB_REC[si] + adc dl,es:BCB_REC2[si] + mov word ptr pblock,ax ; xfer starts at this block + mov word ptr pblock+WORD,dx + mov mult_sec,1 ; single sector transfer + ret + + END diff --git a/IBMDOS/CDEVIO.A86 b/IBMDOS/CDEVIO.A86 new file mode 100644 index 0000000..b949d54 --- /dev/null +++ b/IBMDOS/CDEVIO.A86 @@ -0,0 +1,523 @@ +title 'F_DOS Character device I/O' +; File : $CDEVIO.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; $Log: $ +; CDEVIO.A86 1.18 94/12/21 11:16:29 +; Changed dev_dup to refuse from duplicating remote devices rather +; than refuse from duplicating FCBs +; Made open_dev return IFN rather than XFN for FCB opens +; Made open_dev put the current time/date into DHNDL_TIME/DHNDL_DATE +; CDEVIO.A86 1.16 94/10/07 09:00:18 +; Added patch 004 as source fix. Changed request header length for character +; device to 16h. Used RH4_CDEV_LEN instead of RH4_LEN. +; CDEVIO.A86 1.15 93/12/10 00:09:17 +; Move non-inherited bit to correct place in file handle +; CDEVIO.A86 1.14 93/11/26 16:17:14 +; Update char_error so ES:SI -> device driver header itself; +; ENDLOG + + eject ! include i:psp.def + eject ! include i:modfunc.def + eject ! include i:fdos.equ + eject ! include i:mserror.equ + eject ! include i:doshndl.def + eject ! include i:driver.equ + eject ! include rh.equ + +BDOS_DATA dseg + + extrn fdos_buf:byte ; caveat: in PCMODE data segment + extrn fdos_pb:word + extrn fdos_ret:word + +; +; Critical Error responses from the default INT 24 handler and +; the DO_INT24 routine. +; +ERR_IGNORE equ 0 ; Ignore Error +ERR_RETRY equ 1 ; Retry the Operation +ERR_ABORT equ 2 ; Terminate the Process +ERR_FAIL equ 3 ; Fail Function + +BDOS_CODE cseg + + public open_dev + public close_dev + public dup_dev + public read_dev + public write_dev + public first_dev + public ioc6_dev + public ioc7_dev + + extrn cooked_write:near ; write to cooked console + extrn read_line:near ; read edited line + extrn break_check:near ; look for CTRL C + extrn char_error:near ; generate Int 24 + + extrn current_dsk2al:near ; get default drive in AL + extrn device_driver:near + extrn alloc_dhndl:near ; find free DHNDL_ structure + extrn alloc_xfn:near + extrn les_di_dmaptr:near + extrn release_handle:near + extrn get_xftptr:near + extrn timestamp_dhndl:near + + +; Character device functions +; ========================== + +open_dev: +;-------- +; Entry: ES:BX -> character device header + +; Note: We own the MXdisk here, fdos_pb -> parameter data + + push es ! push bx ; save device driver address + call alloc_xfn ; DI = XFN + push di ; save XFN + call alloc_dhndl ; ES:BX -> DHNDL, AX = IFN + pop dx ; DX = XFN + xchg ax,si ; SI = IFN + xor ax,ax + lea di,DHNDL_DATRB[bx] ; point at start of area to fill + mov cx,DHNDL_UID-DHNDL_DATRB + rep stosb + mov es:DHNDL_SHARE[bx],ax ; also zap share word + pop es:DHNDL_DEVOFF[bx] + pop es:DHNDL_DEVSEG[bx] ; save device driver address + + push si ! push dx ; save IFN/XFN + + mov es:DHNDL_COUNT[bx],1 + push ds + mov ax,fdos_pb+6 ; AX = open mode + mov cx,DHAT_DEV+DHAT_CLEAN+DHAT_TIMEOK + lds si,es:DHNDL_DEVPTR[bx] ; DS:SI -> device driver + or cl,ds:byte ptr DH_ATTRIB[si] + ; get attrib from device driver + test al,DHM_LOCAL ; is it private ? + jz open_dev10 + and al,not DHM_LOCAL ; clear inherit bit + or ch,DHAT_LOCAL/256 ; rememmber it's local +open_dev10: + mov es:DHNDL_MODE[bx],ax + mov es:DHNDL_WATTR[bx],cx + lea si,DH_NAME[si] ; copy the device name + lea di,DHNDL_NAME[bx] ; from the device header + mov cx,8/WORD + rep movsw + mov al,' ' + mov cl,3 ; space the file extension + rep stosb + pop ds + + pop dx ! pop ax ; AX = IFN, DX = XFN + + push es + call get_xftptr ; ES:DI -> PSP_XFTPTR for current_psp + jc open_dev20 ; no PSP, skip updating XFN + add di,dx ; ES:DI -> entry in PSP + stosb ; update entry in PSP + xchg ax,dx +open_dev20: + pop es + + mov fdos_ret,ax ; save XFN (IFN for FCB open) to return + call timestamp_dhndl + or es:DHNDL_ATTR[bx],DHAT_READY +; jmp open_dup_dev + +open_dup_dev: +;------------ +; On Entry: +; ES:BX = DHNDL_ +; On Exit: +; None +; + mov al,CMD_DEVICE_OPEN +; jmp open_close_dev ; call device open routine + +open_close_dev: +;-------------- +; entry: ES:BX = DHNDL_ +; AL = cmd_type (CMD_DEVICE_OPEN/CMD_DEVICE_CLOSE) +; + push ds ! push es + push bx ! push si + lds si,es:DHNDL_DEVPTR[bx] ; DS:SI -> device driver + test ds:DH_ATTRIB[si],DA_REMOVE + jz ocdev1 ; does the device support OPEN/CLOSE/RM + sub sp,RH13_LEN-2*word ; make space on stack for RH_ + push ax ; RH_CMD = AL + mov ax,RH13_LEN + push ax ; RH_LEN = RH13_LEN + push ss ! pop es + mov bx,sp ; ES:BX -> RH_ + call device_driver ; call the device driver + add sp,RH13_LEN ; recover stack space +ocdev1: + pop si ! pop bx + pop es ! pop ds + ret + +dup_dev: +;------- +; On Entry: +; ES:BX -> DHNDL_ +; On Exit: +; None +; AX trashed +; + mov ax,es:DHNDL_WATTR[bx] + test al,DHAT_DEV + jz dup_dev10 ; skip if disk file + test ax,DHAT_REMOTE ; or remote + jz open_dup_dev +dup_dev10: + ret + + +close_dev: ; close character device handle +;--------- +; entry: FDOS_PB+2 = user file handle +; ES:BX = file handle +; NOTE: This is called with the MXdisk owned + + mov al,CMD_DEVICE_CLOSE + call open_close_dev ; call device close routine + call release_handle ; release the XFN + dec es:DHNDL_COUNT[bx] ; one less XFN refers to this IFN + ret + + +write_dev: ; write to character device handle +;--------- +; entry: ES:BX -> DHNDL_ structure +; + + mov cl,CMD_OUTPUT ; OUTPUT driver function + or es:DHNDL_ATTR[bx],DHAT_READY + mov al,es:DHNDL_ATTR[bx] ; get file info + and al,DHAT_BIN+DHAT_NUL+DHAT_CIN+DHAT_COT + cmp al,DHAT_CIN+DHAT_COT ; is it cooked console? + jne inst_io ; no, device driver i/o + mov si,2[bp] ; SI -> parameter block + mov cx,ds:8[si] ; CX = string length + jcxz write_dev20 ; exit if nothing to write + les di,ds:4[si] ; ES:DI -> string to print + mov al,'Z'-40h ; we have to stop at ^Z + repne scasb ; scan for ^Z character + jne write_dev10 ; skip if ^Z not found + inc cx ; include ^Z in count of chars to skip + sub ds:8[si],cx ; subtract from total count +write_dev10: + mov bx,ds:2[si] ; BX = handle number + mov cx,ds:8[si] ; CX = string length + mov si,ds:4[si] ; ES:SI -> string to print + call cooked_write ; write w/ tab expansion & ^C checking +write_dev20: + sub bx,bx ; no errors + ret ; return the result + + + +read_dev: ; read to character device handle +;-------- +; entry: ES:BX -> DHNDL_ structure + + mov al,es:DHNDL_ATTR[bx] ; get the file info + mov ah,al ; save ioctl info + and al,DHAT_BIN+DHAT_CIN+DHAT_COT + cmp al,DHAT_CIN+DHAT_COT ; is it cooked console? + jne rddev1 ; skip if binary or not console + jmp read_con ; read from console handle + ; return the result +rddev1: + test ah,DHAT_READY ; previous EOF ? + jnz rddev2 ; yes we return now + mov di,2[bp] ; DI -> parameter block + mov ds:word ptr 8[di],0 ; zero bytes xfered + ret +rddev2: + mov cl,CMD_INPUT +inst_io: +; ES:BX = DHNDL_, CL = command + sub sp,RH4_CDEV_LEN ; make RH_ on stack + mov di,bx ; save address DHNDL_ in DI + mov bx,sp ; SS:BX -> request header + + mov ds:RH_CMD[bx],cl + mov ds:RH_LEN[bx],RH4_CDEV_LEN + mov ds:RH_STATUS[bx],0 ; status OK in case of zero chars + mov si,2[bp] ; DS:SI -> parameter block + lea si,4[si] ; point at buffer offset + lodsw ; get buffer offset +; Normalising the address has been unnecessary so far +; push ax +; and ax,15 ; normalise the address +; pop cx +; shr cx,1 ! shr cx,1 +; shr cx,1 ! shr cx,1 + mov ds:RH4_BUFOFF[bx],ax ; set buffer offset in request header + lodsw ; get buffer segment +; add ax,cx ; add in normalised offset/16 + mov ds:RH4_BUFSEG[bx],ax ; get buffer segment in request header + lodsw ; get byte count + xchg ax,cx ; byte count in CX + +; Parameter block created on stack at SS:BX and initialised for xfer +; ES:DI -> DHNDL_, CX = total number of bytes to xfer + +inst_io20: + mov ds:RH4_COUNT[bx],cx ; try and do this many + test es:DHNDL_ATTR[di],DHAT_BIN+DHAT_NUL + ; are we in binary mode ? + jcxz inst_io30 ; return on zero length xfer + jnz inst_io25 ; binary, skip calling PCMODE + mov ds:RH4_COUNT[bx],1 ; do one char at a time + call break_check ; call the break check routine + cmp ds:RH_CMD[bx],CMD_OUTPUT ; which way are we going + jne inst_io25 + call inst_io_getchar ; AL = 1st char in the buffer + cmp al,1Ah ; EOF - don't send it or anything after + je inst_io30 ; and exit without xfering any +inst_io25: + push ds ! push es ! push di ! push cx + lds si,es:DHNDL_DEVPTR[di] ; DS:SI -> device driver + push ss ! pop es ; ES:BX -> RH_ + call device_driver ; execute the command + pop cx ! pop di ! pop es ! pop ds + jns inst_io_continue ; if no errors carry on + push es + les si,es:DHNDL_DEVPTR[di] ; ES:SI -> device driver + call char_error ; this will handle the Int 24 + pop es + cmp al,ERR_RETRY ; what should we do ? + je inst_io20 ; retry the operation + ja inst_io30 ; fail - return error + mov ds:RH_STATUS[bx],RHS_DONE + jmps inst_io_ignore ; ignore - fiddle status and +inst_io_continue: ; say we did it all + mov dx,ds:RH4_COUNT[bx] ; how many did we xfer ? + test dx,dx ; if we haven't done any + jz inst_io30 ; we are stuck so exit now +inst_io_ignore: + call inst_io_getchar ; AL = 1st char in the buffer + add ds:RH4_BUFOFF[bx],dx ; it may not enough so adjust offset + sub cx,dx ; and number still to do + cmp ds:RH_CMD[bx],CMD_INPUT ; which way are we going - if input + jne inst_io20 ; we need to check for CR/EOF + test es:DHNDL_ATTR[di],DHAT_BIN+DHAT_NUL + jnz inst_io30 ; if BIN then exit now + cmp al,13 ; is it a CR character ? + je inst_io30 ; yes, we stop now + cmp al,1Ah ; is it the EOF character ? + jne inst_io20 ; yes, we aren't ready + and es:DHNDL_ATTR[di],not DHAT_READY +inst_io30: + mov di,2[bp] ; DI -> parameter block + sub ds:8[di],cx ; subtract # not xfered from byte count + + mov ax,ds:RH_STATUS[bx] ; get result for later + sub bx,bx ; assume no errors + test ax,ax ; test error bit (8000h) + jns rddev_no_err ; skip if ERROR set + mov bl,al ; AL is error code + neg bx ; make it negative code + add bx,ED_PROTECT ; normalize for extended errors +rddev_no_err: + add sp,RH4_CDEV_LEN ; free up RH_ on stack + ret ; return BX + +inst_io_getchar: + push ds + lds si,ds:RH4_BUFFER[bx] ; point to the users buffer + lodsb ; get 1st char in the buffer + pop ds + ret + + +read_con: ; handle read from cooked console +;-------- +; entry: AH = DHNDL_ATTR +; ES:BX -> DHNDL_ +; 2[BP] -> F_DOS parameter block +; exit: BX = return value + + xor cx,cx ; assume we've already had EOF + test ah,DHAT_READY ; now see if we have + jnz con_dev_not_eof + jmp con_dev_exit ; yes, just return zero chars read +con_dev_not_eof: + push es + push bx ; save DHNDL_ +con_dev_loop: + mov bx,word ptr fdos_buf ; get # of bytes already used + xor ax,ax + xchg al,bh ; get # bytes in the buffer + inc ax ! inc ax ; also count the CR/LF + sub ax,bx ; have we any bytes left in the buffer? + ja con_dev_cont ; yes, return them + ; no, we need a fresh input line + mov fdos_buf,128 ; read up to 128 characters + mov si,2[bp] ; SI -> parameter block + mov bx,ds:2[si] ; BX = input handle + push ds ! pop es + mov dx,offset fdos_buf ; ES:DX -> console buffer + mov cx,bx ; output to same handle as input + push bx + push bp + call read_line ; read edited line + pop bp + mov bl,fdos_buf+1 ; # byte we have read + mov bh,0 ; BX = # of characters read + mov word ptr fdos_buf+2[bx],0A0Dh; append carriage return/line feed + mov fdos_buf,0 ; start reading at beginning + lea si,fdos_buf+3[bx] ; Echo the LF character to the + pop bx ; Same Output handle + mov cx,1 ; Only One Character + call cooked_write + jmps con_dev_loop + +con_dev_cont: ; BX = buffer offset + mov di,2[bp] ; DI -> parameter block + mov cx,ds:8[di] ; CX = # of bytes to read + cmp cx,ax ; reading more than available? + jbe con_dev_ok ; no, read as much as you want + mov cx,ax ; else take all that there is +con_dev_ok: + add fdos_buf,cl ; update buffer index for next time + les di,ds:4[di] ; ES:DI -> buffer to read into + lea si,fdos_buf+2[bx] ; DS:SI -> function 10 buffer + push cx ; save count + rep movsb ; read all the data + pop cx ; restore count + mov al,1Ah ; now we look for EOF mark... + push ds ! pop es + lea di,fdos_buf+2[bx] ; ES:DI -> function 10 buffer + mov si,cx ; keep count safe + repne scasb + xchg cx,si ; restore count + pop bx ; recover DHNDL_ + pop es + jne con_dev_exit ; if no EOF, skip to exit + sub cx,si ; subtract any after EOF mark + dec cx ; and the EOF mark itself + and es:DHNDL_ATTR[bx],not DHAT_READY +con_dev_exit: + mov di,2[bp] ; DI -> parameter block + mov ds:8[di],cx ; set # of characters read + sub bx,bx ; good return code + ret + + + + +eject + +first_dev: ; F_DOS FIRST call on device performed +;--------- ; Called with MXDisk +; On Entry: +; ES:BX -> device header +; On Exit: +; dma_buffer initialised with device name +; + mov dx,es ; DX:BX -> device header + call les_di_dmaptr ; ES:DI -> DMA buffer + mov al,0FFh ; invalidate search state for NEXT + mov cx,21 + rep stosb + mov al,40h ; mark it as a device + stosb + sub ax,ax + mov cx,4 + rep stosw ; zero time, date, file size + + lea si,10[bx] + push ds + mov ds,dx ; DS:SI -> name in device header + mov cx,4 + rep movsw ; copy device name across + pop ds + + mov cx,8 +frstdev1: ; scan off trailing spaces + cmp es:byte ptr 0-1[di],' ' + jne frstdev2 + dec di + loop frstdev1 +frstdev2: + mov al,0 + stosb ; add a trailing NUL + ret + + +eject + +ioc6_dev: ; IOCTL(6) - input status for device +;-------- +; entry: ES:BX -> DHNDL_ + + mov al,CMD_INPUT_NOWAIT + jmps ioc67d ; call the device driver + + +ioc7_dev: ; IOCTL(7) - output status for device +;-------- +; entry: ES:BX -> DHNDL_ + + mov al,CMD_OUTPUT_STATUS ; OUTPUT STATUS +ioc67d: ; common code for I/O STATUS + push ds + sub sp,RH5_LEN-2*word ; allocate request header on stack + push ax ; RH_CMD = AL + mov ax,RH5_LEN + push ax ; RH_LEN = RH5_LEN + lds si,es:DHNDL_DEVPTR[bx] ; DS:SI -> device driver + push ss ! pop es + mov bx,sp ; ES:BX -> RH_ + mov es:RH5_CHAR[bx],0 ; zero the char + call device_driver ; do the CALLF's to the device driver + xor dl,dl ; assume not ready + mov dh,es:RH5_CHAR[bx] ; possible peeked character + add sp,RH5_LEN ; recover stack space + pop ds + test ax,RHS_ERROR+RHS_BUSY ; test if BUSY bit set in status + jnz ioc67d_ret ; device not ready if error or busy + dec dl ; return ready DL = FF +ioc67d_ret: + mov si,2[bp] ; SI -> user's parameter block + mov ds:6[si],dx ; update returned status + sub bx,bx ; no error occurred + ret ; for now + + end ; of CDEVIO.A86 diff --git a/IBMDOS/CHAR.DEF b/IBMDOS/CHAR.DEF new file mode 100644 index 0000000..82723db --- /dev/null +++ b/IBMDOS/CHAR.DEF @@ -0,0 +1,74 @@ +; File : $CHAR.DEF$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +;************************************************; +;* *; +;* Character Definitions *; +;* *; +;************************************************; + +CTLA equ 'A' - '@' +CTLB equ 'B' - '@' +CTLC equ 'C' - '@' +CTLD equ 'D' - '@' +CTLE equ 'E' - '@' +CTLF equ 'F' - '@' +CTLG equ 'G' - '@' +BELL equ 'G' - '@' +CTLH equ 'H' - '@' +CTLI equ 'I' - '@' +TAB equ 'I' - '@' +CTLJ equ 'J' - '@' +LF equ 'J' - '@' +CTLK equ 'K' - '@' +CTLM equ 'M' - '@' +CR equ 'M' - '@' +CTLP equ 'P' - '@' +CTLQ equ 'Q' - '@' +CTLR equ 'R' - '@' +CTLS equ 'S' - '@' +CTLT equ 'T' - '@' +CTLU equ 'U' - '@' +CTLV equ 'V' - '@' +CTLW equ 'W' - '@' +CTLX equ 'X' - '@' +CTLY equ 'Y' - '@' +CTLZ equ 'Z' - '@' +ESC equ '[' - '@' +CTLBS equ '\' - '@' +CTLUB equ '_' - '@' +CTLUP equ '^' - '@' +DEL equ 07Fh +RUBOUT equ DEL + +CTL equ '^' diff --git a/IBMDOS/CIO.A86 b/IBMDOS/CIO.A86 new file mode 100644 index 0000000..a758711 --- /dev/null +++ b/IBMDOS/CIO.A86 @@ -0,0 +1,1068 @@ +; File : $CIO.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; $Log: $ +; CIO.A86 1.20 94/12/01 10:05:21 +; Made cooked_write and is_device aware of FCB writes; +; CIO.A86 1.19 94/06/28 12:21:07 +; Fix last_key_ext bug +; CIO.A86 1.18 94/05/12 14:06:22 +; The routine cooked_status now sets a flag last_key_ext if the keycode is 0. +; On entry, it checks this flag to see if the last one was 0, and if so does +; not do the checks for the control keys. In this way, Alt-R and Alt-Q can +; be distinguished from Ctrl-S and Ctrl-P. +; CIO.A86 1.17 93/12/21 17:58:15 +; Preserve BX round clock read +; Update char_error so DS:SI -> device driver header itself +; CIO.A86 1.10 93/05/06 19:28:03 +; Move int 23/28 support to CIO. +; Read the clock in idle_dev, not int 28 loop. +; CIO.A86 1.9 93/05/05 23:30:44 +; int 2A/84 is now only generated on input-and-wait functions +; CIO.A86 1.8 93/03/25 15:05:56 +; tweak console block output +; ENDLOG +; +; This module contains all the Character I/O functions used by PCMODE +; +; 12 Nov 87 Disable Control-Break when the Console Output mode is RAW +; 24 Feb 88 Display Control characters correctly. ie "^X" +; 23 May 88 Support ^S to Pause screen output. +; 25 May 88 Support Control-P for Cooked_Write and remove Kanji Character +; check. +; 26 May 88 Check for CTLC on CON_DEV when character input is redirected. +; Correctly detect EOF on redirected input. +; 17 Aug 88 Call PRN device with Open/Close on ^P +; 30 Aug 88 Jump to correct exit when Open/Close is not supported by a +; device driver for ^P. +; 14 Sep 88 Break checking should only be carried out when the INDOS_FLAG +; is 1. (Novell and Cntrl-C). +; 03 Sep 88 Return the character output by INT21/04,05,06 in AL. +; 10 Nov 88 Preserve ES when calling any Device Driver (Revalation DEVDRVR) +; 15 Dec 88 Check STDERR for Control-C if it is a Device. +; 15 Mar 89 Check for CTLC during Cooked Write. +; 16 Mar 89 Explicitly allow INT 28 during char reads (SmartNotes bug) +; 25 Apr 89 Execute break_check after getting the console status INT21/0B +; 2 May 89 Save Device driver STRAT and INT address's on the stack +; 10 May 89 Now check keyboard more often during cooked write +; 25 May 89 Move INT28 flag to PCMIF.PCM +; 6 Sep 89 Enter/Exit critical region round device request +; 26 Oct 89 saving some bytes again... +; 25 Jan 90 Insert IDLE Detection Code +; 29 Jan 90 Int 2A critical section support added to device_callf +; 7 Mar 90 Convert to register preserved function calls +; 27 Mar 90 cooked_write checks STD_OUT for ctl-s ctl-p etc (STD_IN may +; have been redirected) +; 29 Mar 90 preserve BX round device_callf (3+Share CLOCK$ bug) +; 12 Jun 90 get_doshndl parameter BX not AX +; 15 Oct 90 Added support for Return Interim Character flag (see PSP_RIC). +; 26 Oct 90 handle PSP=0 (ie. FCB device I/O) +; 1 mar 91 break_check now goes to con_device, not STDERR +; 17 jun 91 ij fix to cooked_out to avoid status checks if STDOUT redirected + + include pcmode.equ + include i:driver.equ + include i:reqhdr.equ + include i:msdos.equ + include i:fdos.equ + include i:psp.def + include i:mserror.equ + include i:char.def + include i:redir.equ + include i:doshndl.def + +CIO_CTLP equ 0000$0001b ; Printer Echo State +CIO_HANDLE equ 0000$0010b ; use handle rather than Int 29 +CIO_RAW equ 0000$0100b ; no "cooked_status" checks + +CHECK_EVERY equ 80 ; check keyboard every "n" characters + +PCM_CODE CSEG BYTE + extrn char_error:near + extrn device_driver:near + extrn dos_entry:near + extrn get_dseg:near + extrn ifn2dhndl:near + extrn int21_entry:near + extrn int21_func:near + extrn read_line:near + extrn ReadTimeAndDate:near + extrn reload_registers:near + +; ***************************** +; *** DOS Function 01 *** +; *** Keybd Input W/Echo *** +; ***************************** +; + Public func01 +func01: +; +; Entry: +; AH == 01h +; Exit: +; AL == char +; + call func08 ; Read 1 character from Standard Input + ; and check for Control-C + xchg ax,dx ; echo using common code + +; ***************************** +; *** DOS Function 02 *** +; *** Display Output *** +; ***************************** +; + Public func02 +func02: +; +; Entry: +; AH == 02h +; DL == char to display +; + push dx ; char on stack + push ss ! pop es + mov si,sp ; ES:DX -> character + mov cx,1 + call stdout_cooked_write ; write character + pop ax ; recover char + ret + +; ***************************** +; *** DOS Function 03 *** +; *** Auxiliary Input *** +; ***************************** +; + Public func03 +func03: +; +; Entry: +; AH == 03h +; Exit: +; AL == Char +; + mov bx,STDAUX ; Read 1 character from Standard AUX +f03_10: + jmp raw_read + +; ***************************** +; *** DOS Function 04 *** +; *** Auxiliary Output *** +; ***************************** +; + Public func04 +func04: +; +; Entry: +; AH == 04h +; DL == Character to output +; + mov bx,STDAUX ; write the character passed in DL + jmps f456common ; to the STDAUX Handle + +; ***************************** +; *** DOS Function 05 *** +; *** Printer Output *** +; ***************************** +; + Public func05 +func05: +; +; Entry: +; AH == 05h +; DL == character to output to printer +; + mov bx,STDPRN ; write the character passed in DL +; jmp f456common ; to the STDPRN Handle + +f456common: + xchg ax,dx ; character in AL +; jmp hndl_write + +hndl_write: +;---------- +; On Entry: +; AL = character to write +; BX = handle +; On Exit: +; AL preserved +; + call is_device ; Does this handle refer to a device + jc hndl_w10 + test es:DH_ATTRIB[si],DA_SPECIAL + jz hndl_w10 ; Fast Console Output Using Int 29? + int 29h ; This device supports FAST console + ret ; output so write this using Int29 + +hndl_w10: + push ax ; character on stack + mov dx,sp ; SS:DX -> char + mov cx,1 ; do a single character + jc hndl_w20 ; was it a file ? + call device_write ; send to device driver + jmps hndl_w30 +hndl_w20: + push ss ! pop es ; ES:DX -> character + mov ah,MS_X_WRITE ; otherwise call the FDOS to do all + call dos_entry ; the hard work +hndl_w30: + pop ax + ret + + +; ***************************** +; *** DOS Function 06 *** +; *** Direct Console I/O *** +; ***************************** +; + Public func06 +func06: +; +; Entry: +; AH == 06h +; DL == 0FFh or Output char +; Exit: +; AL == Input char, if DL was 0FFh on input +; + mov bx,STDOUT ; Assume output DL to console + cmp dl,0FFH ; or is it input ? + jne f456common + dec bx +; mov bx,STDIN ; is there a character ready + call char_check ; to be input + jz func07 + mov ax,RHS_IC ; set AL=0 and also set ZF on + jmps funcICexit ; exit as incomplete char + + +; ***************************** +; *** DOS Function 07 *** +; *** Raw Input w/o echo *** +; ***************************** +; + Public func07 +func07: +; +; Entry: +; AH == 07h +; Exit: +; AL == character +; + mov bx,STDIN + call raw_read ; extra status call made + jmps funcICexit ; set incomplete char + +; ***************************** +; *** DOS Function 08 *** +; *** Input w/o echo *** +; ***************************** +; + Public func08 +func08: +; +; Entry: +; AH == 08h +; Exit: +; AL == character +; + mov bx,STDIN ; Read 1 character from Standard Input + call cooked_read +funcICexit: +; exit point for incomplete character support +; On Entry: +; AL = character +; AH = request header status (RHS_IC as on return from device driver) +; On Exit: +; AL = character +; dos_FLAGS ZF set if incomplete character +; + les di,int21regs_ptr ; point to callers registers + and es:reg_FLAGS[di],not ZERO_FLAG ; clear ZF + test ah,RHS_IC/256 ; is it an incomplete char ? + jz funcIC10 ; no - exit + or es:reg_FLAGS[di],ZERO_FLAG ; yes - set ZF +funcIC10: + ret + +; ***************************** +; *** DOS Function 09 *** +; *** Print String *** +; ***************************** +; + Public func09 +func09: +; +; Entry: +; AH == 09h +; DS:DX == address of character string +; + + mov al,'$' ; it's terminated with a '$' + mov di,dx ; locate the end of the string + mov cx,0FFFFh ; and calculate its length + repnz scasb + not cx + dec cx ; CX is the character count + mov si,dx + call stdout_cooked_write ; ES:SI -> character buffer + mov al,'$' + ret + + +; ***************************** +; *** DOS Function 0A *** +; *** Read String *** +; ***************************** +; + Public func0A +func0A: +; +; Entry: +; AH == 0Ah +; DS:DX == pointer to input buffer +; + mov bx,STDIN ; Read the editted line from STDIN + mov cx,STDOUT ; and display the results on STDOUT + jmp read_line ; Read the Line + +; ***************************** +; *** DOS Function 0B *** +; *** Console Status *** +; ***************************** +; + Public func0B +func0B: +; +; Entry: +; AH == 0Bh +; Exit: +; AL == 0FFh if char available +; == 00h otherwise +; + mov bx,STDIN + call cooked_status ; Get the current handle status + mov al,0FFh ; Assume that the handle is ready + jz f0B_exit ; and return 0FFh in AL + mov al,00 ; Not Ready +f0B_exit: + jmps funcICexit ; exit thru incomplete char support + + + +; ***************************** +; *** DOS Function 0C *** +; *** Flush and Execute *** +; ***************************** +; + Public func0C +func0C: +; +; Entry: +; AH == 0Ch +; AL == function to execute: 1,6,7,8 or A +; Exit: +; AL = 0 if function in AL is invalid +; + push ax ; save sub-function + mov bx,STDIN ; Is this Standard Input Handle a + call is_device ; file or device. Do not flush the + jc f0C_20 ; buffer contents for a FILE +f0C_10: + call hndl_instat ; check if any characters are left + jnz f0C_20 ; and quit when buffer empty + call raw_read ; read the character + jmps f0C_10 ; loop till the buffer is empty + +f0C_20: + pop ax + cmp al,01h ! je al_ok ; is legal for this command + cmp al,0ah ! je al_ok + cmp al,06h ! jb al_nogo + cmp al,08h ! ja al_nogo + +al_ok: ; Valid function so now execute + call reload_registers ; all register reloaded as per entry + mov ah,al ; Get the requested sub-function in AH + jmp int21_func ; execute the function + +al_nogo: ; Illegal command to execute + xor ax,ax ; from this function so return error + ret + +eject +; +; BREAK_CHECK checks for a CNTRL-C and is called by functions 01h to +; 0Ch. Or by the entry code if the break flag is non zero. +; + Public break_check +break_check: + cmp indos_flag,01 ; Skip the check if we are + jnz break_c15 ; already in the emulator + push ax + push es + push si + les si,con_device + call device_instat ; get the input status + pop si + pop es + jnz break_c10 ; No Character Ready + cmp al,CTLC ; Is the character a Control-C + jz break_c20 ; Yes +break_c10: + pop ax +break_c15: + ret + +break_c20: ; The User has Typed Control-C so flush + mov bx,0FFFFh ; input buffer (FFFF=con_device) + call char_get +go_int23: + push cs ! pop es ; ES:DX -> Character Buffer + mov si,offset cntrl_c_msg ; Message Offset + mov cx,length cntrl_c_msg ; Message Length + call stdout_cooked_write ; write the ^C String to console +; +; Prepare to execute an Interrupt 23 (Break Check) and process +; the return values. If the called routine returns with an IRET +; or with a RETF and the carry flag reset continue the function +; otherwise Abort. +; + mov es,current_psp ; Get the Entry SS and SP + mov ax,PSP_USERSP ; Get the Users Stack Pointer + add ax,18 - 2 ; Compensate for the User Registers + mov break_sp,ax ; and save for RETF check + cli + dec indos_flag ; Exit the PCDOS emulator + mov ss,PSP_USERSS ; Switch to the Users Stack + mov sp,PSP_USERSP ; and Restore the registers + + POP$DOS ; Update the registers then + ; set the flags and return + ; to the user + clc ; Default to continue function + int 23h ; Call the Break Handler + cli ; Check the Flag State + jnc do23_10 ; If CARRY then Abort this process + call get_dseg ; Get our data segment + mov exit_type,TERM_BREAK ; Force EXIT_TYPE to TERM_BREAK + mov ax,4C00h ; "Good-Bye Cruel World" + jmps do23_20 + do23_10: + push ds ; Otherwise restart the aborted func + call get_dseg + cmp sp,break_sp + pop ds ; Restore the the USER DS correct + jz do23_30 ; Did we Use a RETF or Not +do23_20: + add sp,2 ; Yes so correct the stack pointer +do23_30: ; and restart the aborted function + jmp int21_entry ; re-start the function call + + + +eject +; +; cooked_status is called on input or output and looks for live keys ^C,^P,^S. +; If any of these are found they are dealt with. +; If ^P is encountered it is swallowed. +; If ^C is encountered we always do an Int23. +; If ^S is pressed we swallow it, and the next character (checking for ^C, but +; not for ^P), then say a character is ready. +; Note that this can lead to status calls (func0B) hanging inside the OS, +; or the return of ^S characters from input calls (func01), but this is +; intentional. +; + +cooked_status: +;------------- +; check input +; On Entry: +; BX = handle to check +; On Exit: +; ZF set if character available +; AL = character +; AH = RHS_IC +; + call break_check ; check for a ^C on console + call char_check ; is there a character ready + jnz cooked_s50 ; no so keep scanning + + cmp last_key_ext,0 ; was last char an zero ? + mov last_key_ext,0 ; (clear flag for next time) + jne cooked_s40 ; skip ^P,^S,^C checks if so + + cmp al,CTLP ; has the user typed ^P + jne cooked_s10 ; flush the buffer and + xor cio_state,CIO_CTLP ; toggle ^P flag + call char_get ; flush the character from buffer + call open_or_close_prn ; open/close printer device + test ax,ax ; ZF clear, ie. no char available + jmps cooked_s50 + +cooked_s10: + cmp al,CTLC + jnz cooked_s30 ; has the user typed ^C + call char_get ; so get the RAW character +cooked_s20: + jmp go_int23 ; and terminate the function + +cooked_s30: + cmp al,CTLS ; pause if the user has typed + jnz cooked_s40 ; a ^S + call char_get ; remove ^S and resume when + call raw_read_wait ; the next character is typed + cmp al,CTLC + je cooked_s20 ; has the user typed ^C +cooked_s40: + cmp al,0 + jne cooked_s45 + mov last_key_ext,1 +cooked_s45: + cmp ax,ax ; ZF set, ie. char available +cooked_s50: + ret + +eject +; +; The COOKED, CMDLINE and RAW Read functions are basically the same +; except in their treatment of 'live' characters ^C,^P, and ^S. +; COOKED will look for and act upon all three live characters. +; CMDLINE will look for and act upon ^C and ^P, but ^S will be returned +; so we can use it as a line editing key. +; RAW will not check for any live keys. +; + public cmdline_read, raw_read ; for CMDLINE.PCM + +cmdline_read_wait: ; Waiting for a device to become + call idle_dev ; ready. So call IDLE routines to + ; put the processor to sleep. +cmdline_read: + call break_check ; check for a ^C on console + call char_check ; is there a character ready + jnz cmdline_read_wait ; no so keep scanning + cmp al,CTLS ; if the user has typed ^S + jne cooked_read ; we have to do a raw read +; jmps raw_read ; else we do a cooked read + +raw_read_wait: ; Waiting for a device to become + call idle_dev ; ready. So call IDLE routines to + ; put the processor to sleep. +raw_read: + call char_check ; Is there a character Ready + jnz raw_read_wait ; loop until character available + jmps char_get + +cooked_read_wait: ; Waiting for a device to become + call idle_dev ; ready. So call IDLE routines to + ; put the processor to sleep. +cooked_read: + call break_check ; check for a ^C on console + call cooked_status ; check for a ^S,^P,^C on handle BX + jnz cooked_read_wait ; wait until char is available +; jmps char_get ; else get the character + +char_get: + push es ! push ax ; Input one character and + mov dx,sp ; return it in AL + call is_device ; Does this handle refer to a device + mov cx,1 + jc char_get30 ; if it's a device then + call device_read ; use device_read +char_get20: + pop ax ! pop es + ret + +char_get30: +; We are redirected, so call to the FDOS to get a character + push ss ! pop es ; EX:DX -> character to read + mov ah,MS_X_READ ; call the FDOS to do all + call dos_entry ; the hard work + jmps char_get20 + +eject + +stdout_cooked_write: + mov bx,STDOUT ; output to the console device +; jmp cooked_write + +; +; The COOKED_WRITE routine will expand TABS etc in the string +; passed passed by the calling routine. +; +; On Entry: +; ES:SI Buffer Address +; CX Character Count +; BX Output Handle +; On Exit: +; AL = last char written +; + Public cooked_write +cooked_write: + push es + push bx + mov ah,cio_state ; get CIO_CTLP status + or ah,CIO_RAW+CIO_HANDLE ; assume we will want raw handle output + mov al,bl + test byte ptr remote_call+1,DHM_FCB/100h + jnz cook_w03 + mov es,current_psp ; get our PSP + cmp bx,PSP_XFNMAX ; range check our handle + jae cook_w05 + les di,PSP_XFTPTR + mov al,es:byte ptr [bx+di] ; AL = Internal File Handle +cook_w03: + call ifn2dhndl ; ES:BX -> DHNDL_ + jc cook_w05 ; skip if bad handle + mov dx,es:DHNDL_WATTR[bx] ; get handle attributes + and dx,DHAT_DEV+DHAT_CIN+DHAT_COT+DHAT_BIN+DHAT_REMOTE + cmp dx,DHAT_DEV+DHAT_CIN+DHAT_COT+DHAT_BIN + je cook_w04 ; accept binary console device + cmp dx,DHAT_DEV+DHAT_CIN+DHAT_COT + jne cook_w05 ; skip if not cooked console device + and ah,not CIO_RAW ; we want cooked output +cook_w04: + les bx,es:DHNDL_DEVPTR[bx] ; its the console - but is it FAST ? + test es:DH_ATTRIB[bx],DA_SPECIAL + jz cook_w05 ; skip if not + and ah,not CIO_HANDLE ; don't use handle functions +cook_w05: + pop bx + pop es + jcxz cook_w80 +cook_w10: + lods es:al ; Read the next character + cmp al,DEL ! je cook_w60 ; DEL is a NON Printing Character + cmp al,' ' ! jae cook_w50 ; Space and Above are Normal + cmp al,LF ! je cook_w60 ; Just print LineFeeds + cmp al,ESC ! je cook_w60 ; Just print Escape + cmp al,BELL! je cook_w60 ; Just ring the Bell + cmp al,CR ! jne cook_w20 ; CR zeros the column number + mov column,0 + mov char_count,1 ; check for ^S etc NOW + jmps cook_w60 +cook_w20: + cmp al,CTLH ! jne cook_w30 ; BackSpace decrements the + dec column ; column count by one + jmps cook_w60 +cook_w30: + cmp al,TAB ! jne cook_w60 ; is it a TAB ? +cook_w40: + mov al,' ' ; spaces + call cooked_out ; output a space char + inc column + test column,7 ; are we at a TAB stop yet ? + jnz cook_w40 + jmps cook_w70 +cook_w50: + inc column ; Update the column count and +cook_w60: + call cooked_out ; output the character +cook_w70: + loop cook_w10 ; onto the next character +cook_w80: + ret + +cooked_out: +; On Entry: +; AH = handle status +; AL = character +; BX = handle +; On Exit: +; AX, BX, CX, ES:SI preserved +; + dec char_count ; time to check keyboard input ? + jz cooked_o10 ; no, skip status check + test ah,CIO_HANDLE+CIO_CTLP ; is it complicated ? + jnz cooked_o10 + int 29h ; This device supports FAST console + ret + +cooked_o10: + push es + push ax + push cx + push si + call hndl_write ; display the character + test ah,CIO_CTLP ; Check for Printer Echo + jz cooked_o20 ; Off so No Echo + push bx ; Save Output Handle + mov bx,STDPRN ; and output the same data to the + call hndl_write ; to the Printer Handle + pop bx +cooked_o20: + test ah,CIO_RAW ; is it a cooked console ? + jnz cooked_o30 ; skip check if not + call cooked_status ; look for keyboard input + mov char_count,CHECK_EVERY ; look again in a while +cooked_o30: + pop si + pop cx + pop ax + pop es + ret + +eject +; IDLE_DEV is called when the PCMODE is waiting for a character. +; This routine must determine if the request is for a device or not +; and call the IDLE interface for device requests to the system can be +; put to sleep until a character is ready. +; +; On Entry:- BX Handle Number +; +idle_dev: + push bx ; preserve handle + mov ax,8400h + int 2ah ; Server hook for idle + dec clock_count + jnz idle_dev10 ; Zero if NO skip delay and execute + call ReadTimeAndDate ; for PC BIOS's who must read every day +idle_dev10: +if IDLE_DETECT + test idle_flags,IDLE_DISABLE ; Has Idle Checking been enabled + jnz idle_dev40 ; Skip if NO + push es ! push si + call is_device ; The requested handle a file or device + jc idle_dev30 ; File Access skip IDLE + mov ax,PROC_KEYIN ; Assume this is the REAL Console + test es:DH_ATTRIB[si],DA_ISCIN; Test Attribute Bits + jnz idle_dev20 ; Yes this is Default Console Device + mov ax,PROC_DEVIN ; Input from Another Device +idle_dev20: + callf idle_vec ; Call the IDLE Handler +idle_dev30: + pop si ! pop es +idle_dev40: +endif + pop bx ; recover handle + ret + +eject +; The following routine reads CX bytes from the device whose address +; is held in the DWORD pointer passed by DS:SI. A Request Header +; is built on the stack and the command is executed. +; +; On Entry: +; ES:SI DWORD Pointer to Device Header +; SS:DX Buffer Address +; CX Character Count +; +; On Exit: +; AX Request Header Status +; Zero No Error +; + Public device_read +device_read: + mov al,CMD_INPUT ; we want input + jmps device_common ; now use common code + +eject +; The following routine writes CX bytes to the device whose address +; is held in the DWORD pointer passed by DS:SI. A Request Header +; is built on the stack and the command is executed. +; +; On Entry: +; ES:SI DWORD Pointer to Device Header +; SS:DX Buffer Address +; CX Character Count +; +; On Exit: +; AX Request Header Status +; Zero No Error +; + Public device_write +device_write: + mov al,CMD_OUTPUT ; we want output +device_common: + push bx + sub sp,RH4_LEN ; reserve space on the stack + mov bx,sp ; request header offset + mov ss:RH_LEN,RH4_LEN ; request header length + mov ss:RH4_BUFOFF,dx ; buffer offset + mov ss:RH4_BUFSEG,ss ; buffer segment +device_common10: + mov ss:RH4_COUNT,cx ; character count + call device_req ; execute command + jns device_common20 ; if no errors return to the caller + sub cx,ss:RH4_COUNT ; CX = chars remaining + push ax ; save the error code + call char_error ; ask int 24 what to do + cmp al,ERR_RETRY ; should we retry the operation ? + pop ax ; recover the error code + ja device_common20 ; Fail/Abort return error + mov al,ss:RH_CMD ; reload the command + je device_common10 ; Retry, re-issue the device request + mov ax,RHS_DONE ; Ignore, pretend no errors +device_common20: + add sp,RH4_LEN ; restore the stack to its normal + test ax,RHS_ERROR ; state and return the status. + pop bx + ret + + +char_check: +; On Entry: +; BX = handle to check +; On Exit: +; ZF set if character ready +; AL = character (if device handle) +; AH = RIC status +; + push bx ; Save the current handle status +if IDLE_DETECT + test idle_flags,IDLE_DISABLE ; Has Idle Checking been enabled + jnz char_check10 ; Skip if NO + dec int28_delay ; Has the INT28 Loop count reached + jnz char_check10 ; Zero if NO skip delay and execute + mov ax,int28_reload ; INT28. Otherwise DELAY/DISPATCH + mov int28_delay,ax + mov ax,PROC_INT28 ; Process is IDLE + callf idle_vec ; Call the IDLE Handler +char_check10: +endif + cmp indos_flag,1 ; Only execute an INT 28 + jnz char_check20 ; when the INDOS flag is 1 + cmp int28_flag,TRUE ; Only generate INT 28s for the + jnz char_check20 ; selected functions + + push remote_call + push machine_id + mov es,current_psp ; Get the PSP + push PSP_USERSP ; Save the SS:SP pointer to + push PSP_USERSS ; the register image + +if IDLE_DETECT ; Set IDLE_INT28 so $IDLE$ knows + or idle_flags,IDLE_INT28 ; that we are nolonger inside DOS +endif + int 28h ; Execute an INT 28 for SideKick and + ; the PRINT utility. INDOS flag is 1 + +if IDLE_DETECT ; Reset IDLE_INT28 so $IDLE$ knows + and idle_flags,not IDLE_INT28; that we are back DOS +endif + mov int28_flag,TRUE ; Restore INT28_FLAG + mov es,current_psp ; Get the PSP + pop PSP_USERSS ; Restore the SS:SP pointer to + pop PSP_USERSP ; the register image + pop machine_id + pop remote_call +char_check20: + pop bx +; jmp hndl_instat ; Check Input Status. ZERO == Ready + +; +; +hndl_instat: + call is_device ; Does this handle refer to a device + jnc device_instat + mov ax,(MS_X_IOCTL shl 8)+6 ; Get the file status + call dos_entry ; for the specified handle + cmp al,0FFh ; and return ZERO until the EOF + ret + +; The following routine executes the Non Destructive Input +; command to the device whose address passed in ES:SI. +; +; On Entry: +; ES:SI DWORD Pointer to Device Header +; +; On Exit: +; Zero Character Ready +; AH Top Byte Request Header Status +; AL Next Character if ZERO +; + +device_instat: + push bx + sub sp,RH5_LEN ; Reserve Space on the Stack + mov bx,sp ; Request Header Offset + mov ss:RH_LEN,RH5_LEN ; Set Request Header Length + mov al,CMD_INPUT_NOWAIT ; Command Number + call device_req ; Execute the Command + mov al,ss:RH5_CHAR ; Assume a character is ready + add sp,RH5_LEN ; Restore the Stack to its normal + test ax,RHS_BUSY ; state and return the status. + pop bx ; Zero if a Character is ready + ret + +; The following routine handles the low level device interface to +; the character device drivers. All the generic Request Header +; initialization is carried out here. +; +; On Entry: +; AL Command +; ES:SI Device Header +; SS:BX Current Request Header +; +; On Exit: +; AX Request Header Status +; + +device_req: +;---------- + mov ss:RH_CMD,al ; save the command + push ds + push es + push es ! pop ds ; DS:SI -> device driver + mov es,ss:current_psp ; es = current PSP + mov al,es:PSP_RIC ; al = Return Interim Character flag + mov ss:RH4_RIC,al ; Return Interim Char flag + push ss ! pop es ; ES:BX -> RH_ + call device_driver + pop es + pop ds + ret + +eject +; +; IS_DEVICE checks the internal handle structures to determine +; if the handle referenced in BX is a file or device. Invalid +; handles all map to the default console device. +; +; On Entry: +; BX Handle Number +; +; On Exit: +; CY set if handle is for a file +; CY clear if handle is for device at ES:SI +; +is_device: + push ax + push bx ; Convert the Standard Handle number + mov ax,bx ; get XFN in AL +; mov cx,current_psp ; into an internal handle number +; jcxz is_dev10 ; no PSP, we have IFN already +; mov es,cx + test byte ptr remote_call+1,DHM_FCB/100h; if FCB initiated access + jnz is_dev10 ; we have IFN already + mov es,current_psp + cmp bx,es:PSP_XFNMAX ; Check if the handle is in range for + jae is_dev_bad ; this PSP. + les si,es:PSP_XFTPTR + mov al,es:byte ptr [bx+si] ; AL = Internal File Handle +is_dev10: + call ifn2dhndl ; ES:BX -> DHNDL_ + jc is_dev_bad + mov ax,es:DHNDL_WATTR[bx] ; get file attributes + and ax,DHAT_REMOTE+DHAT_DEV + cmp ax,DHAT_DEV ; is it a local device ? + stc ; assume it's a file + jne is_dev30 + les si,es:DHNDL_DEVPTR[bx] ; its a device +is_dev20: + clc +is_dev30: + pop bx + pop ax + ret + +is_dev_bad: + les si,con_device ; bad handles map to console + jmps is_dev20 + +open_or_close_prn: +;----------------- +; called when CIO_CTLP toggled - call prn device with Open or Close as appropriate +; + push ds ! push ax ! push bx + mov ax,CTLP + push ax ; ^P on stack + mov cx,current_psp ; look in PSP + jcxz oc_prn30 ; no PSP, forget it + mov es,cx + cmp bx,PSP_XFNMAX ; Check if the handle is in range for + jae oc_prn30 ; this PSP. + les si,es:PSP_XFTPTR ; for the internal handle number + mov al,es:byte ptr STDPRN[si] + cmp al,0FFh ; AL = Internal File Handle + je oc_prn30 ; skip if invalid Handle Number + call ifn2dhndl ; ES:BX -> doshndl + jc oc_prn30 + test es:DHNDL_WATTR[bx],DHAT_NETPRN + jz oc_prn10 + mov ax,I2F_CTLP ; turn on the network printer + int 2fh ; with a magic INT 2F call + jnc oc_prn10 + and cio_state,not CIO_CTLP ; make sure Printer Echo is off + mov ax,I2F_CTLP_ERR + int 2fh + jmps oc_prn30 +oc_prn10: + mov ax,es:DHNDL_WATTR[bx] ; get file attributes + and ax,DHAT_REMOTE+DHAT_DEV + cmp ax,DHAT_DEV ; is it a local device ? + jne oc_prn30 + mov al,CMD_DEVICE_OPEN ; assume we've just opened + test cio_state,CIO_CTLP ; Check for Printer Echo + jnz oc_prn20 ; yes, skip next bit + mov al,CMD_DEVICE_CLOSE ; no, we must close +oc_prn20: + les si,es:DHNDL_DEVPTR[bx] ; get the device driver address + test es:DH_ATTRIB[si],DA_REMOVE + jz oc_prn30 ; no, skip call if not supported + sub sp,RH13_LEN ; Reserve Space on the Stack + mov bx,sp ; and point to it + mov ss:RH_LEN,RH13_LEN ; Set Request Header Length + mov ss:RH_CMD,al ; Command Number + call device_driver ; issue the command + add sp,RH13_LEN ; Restore the Stack to its normal +oc_prn30: + pop ax ; discard ^P from stack + pop bx ! pop ax ! pop ds + ret + + +PCM_RODATA CSEG WORD + +cntrl_c_msg db '^C', CR, LF ; Control-Break Message + +GLOBAL_DATA dseg + +clock_count db 0 + +PCMODE_DATA DSEG WORD + + extrn break_sp:word ; For Control-Break handler + extrn char_count:byte + extrn cio_state:byte ; Character I/O State + extrn column:byte ; Console Cursor Location + extrn con_device:dword ; Current Console Device + extrn current_psp:word ; Current PSP Address + extrn exit_type:byte + extrn last_key_ext:byte + extrn indos_flag:byte ; INDOS Count + extrn int21regs_ptr:dword ; pointer to callers registers + extrn machine_id:word + extrn remote_call:word +if IDLE_DETECT + extrn idle_flags:word ; IDLE State Flags + extrn idle_vec:dword ; IDLE routine Vector + extrn int28_delay:word + extrn int28_reload:word + extrn int28_flag:byte +endif + + end diff --git a/IBMDOS/CMDLINE.A86 b/IBMDOS/CMDLINE.A86 new file mode 100644 index 0000000..469b814 --- /dev/null +++ b/IBMDOS/CMDLINE.A86 @@ -0,0 +1,1111 @@ +; File : $CMDLINE.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; CMDLINE.A86 1.8 93/03/25 15:06:03 +; tweak console block output +; ENDLOG +; +; DOSPLUS Command Line Editor Routines +; + + include pcmode.equ + include i:msdos.equ + include i:char.def + include i:cmdline.equ + include i:reqhdr.equ + include i:driver.equ + + +PCM_CODE CSEG BYTE + public read_line, edit_size + + extrn dbcs_lead:near + extrn cmdline_read:near + extrn raw_read:near + extrn cooked_write:near + extrn get_dseg:near + extrn device_driver:near + +; WARNING - the following routines are to support history buffers +; As these are optional we muset NEVER call these routines unless +; the HISTORY_ON bit is set in @hist_flag. + + extrn init_history:near + extrn save_history:near + extrn prev_cmd:near + extrn next_cmd:near + extrn match_cmd:near + extrn search_cmd:near + extrn match_word:near + extrn del_cur_history_buffer:near + extrn del_history_buffers:near + extrn goto_eol:near + extrn next_word:near + extrn prev_word:near + extrn del_bol:near + extrn deln_word:near + +; The following are public for HISTORY.PCM + public next_char, save_line + public space_out, bs_out, put_string + public goto_bol + public del_eol, del_line + public char_info + public prev_w20 + public deln_w10 + + +; READ_LINE will read an editted line from the handle passed in BX +; into a buffer with the following format:- +; +; BYTE Maximum String Length +; BYTE Current String Length +; BYTE(s) String Buffer +; +; On Entry:- +; BX Input Handle +; CX Output Handle +; ES:DX Buffer Address +; +; On Exit:- +; String input by user +; +; The following conventions apply for the READ_LINE function +; +; ES Buffer segment +; SI Current cursor location in buffer (Index) +; DX Last Character in Buffer (Index) +; +DISABLE equ 80h ; Disable when advanced editing is off. +DISABLE_MASK equ 8000h +ESC_CODE equ 01h ; Scan code must be preceeded by escape byte. +NESC_CODE equ 00h ; No lead zero needed. + +read_line: + push bp ; Save the Stack Frame Pointer + mov bp,sp ; Intialise it to the top of the + sub sp,RL_LENGTH ; READ_LINE control block and reserve + ; control block + mov RL_INPUT,bx ; Initialize the INPUT Handle + mov RL_OUTPUT,cx ; the OUTPUT Handle + inc dx ! inc dx ; Skip max and Returned Length + mov RL_BUFOFF,dx ; and save the buffer offset + mov RL_BUFSEG,es ; and segment + xor ax,ax ; now we zero + mov RL_SAVPOS,ax ; both position in it + mov RL_SAVMAX,ax ; and it's size + mov al,column + mov RL_INICOL,ax ; save initial column + mov ax,cle_state ; use to set initial editing state + and ax,not (RLF_MATCH+RLF_DIRTY+RLF_RECALLED) + mov RL_FLAGS,ax ; save in flags + test ax,RLF_ENHANCED + jz read_line10 + call init_history ; setup the history buffers + jmps read_line20 +read_line10: + and RL_FLAGS,not RLF_INS ; clear insert mode +read_line20: + mov di,dx ; di -> buffer + xor bx,bx + or bl,es:byte ptr -2[di] ; Get the Maximum number of chars + mov RL_MAXLEN,bx ; and save for later + jnz read_line30 ; make sure some chars are requested + jmps ret_string10 ; if no chars just return + +ret_string: + pop ax ; Remove local return address + mov ax,RL_FLAGS ; get command line editor state + mov cle_state,ax ; save state for next time + mov di,RL_BUFOFF ; Get the buffer Offset + mov es:byte ptr -1[di],dl ; Return the number of characters + push dx ; Save length of entry + add di,dx ; Point to the end of the buffer + mov al,CR + stosb ; Save CR + call write_char ; Print a CR and return to the user + pop dx + test RL_FLAGS,RLF_ENHANCED ; Do not add to history if in + jz ret_string10 ; compatibility mode + call save_history ; Save state of history buffer +ret_string10: + mov sp,bp ; Remove READ_LINE control Block + pop bp ; Restore BP and return to the caller + ret + + +read_line30: + xor si,si ; Currently at start of buffer + mov dx,si ; with an empty buffer. + + xor bx,bx + or bl,es:byte ptr -1[di] ; Check if the buffer contains any + jz read_line40 ; data which is terminated by a CR + cmp es:byte ptr [bx+di],CR + jnz read_line40 + mov dx,bx +read_line40: + call save_line ; Update Save Buffer variables + mov dx,si +; +; This is out main command loop - we get a character and try to match it +; with a command in our edit_table. If History is on we look at commands +; with the DISABLED bit set ie. enhanced commands. +; It a match isn't found we insert the character in the buffer, and optionally +; try to match with previous lines in the history buffer. +; +read_line_loop: + and RL_FLAGS,not RLF_KANJI ; initial flags + call get_char ; read the first character (AH Esc Flg) + + mov cx,edit_size ; now scan the control table looking + mov bx,offset edit_table ; for a match +read_ll_next_cmd: + and ax,not DISABLE_MASK ; assume normal function + test RL_FLAGS,RLF_ENHANCED ; compatibilty required? then it + jz read_ll10 ; has to be a normal function + test EDIT_CNTRL,DISABLE_MASK ; history enabled, so we make + jz read_ll10 ; our code match DISABLE mask + or ax,DISABLE_MASK ; of table entry +read_ll10: + cmp ax,EDIT_CNTRL ; check for a match (Escape Flag + je read_ll_found_cmd ; and the character) + add bx,EDIT_LEN ; Add the entry length + loop read_ll_next_cmd ; and scan the whole table + +; We have failed to find a command so insert char in buffer + + test ah,ESC_CODE ; Ignore non-matched escaped keys + jnz read_line_loop + + call save_char ; not an command so save the character + or RL_FLAGS,RLF_DIRTY ; and remember we have something new + +; Are we in search mode ? + + test RL_FLAGS,RLF_ENHANCED ; Compatibilty required? + jz read_line_loop + test RL_FLAGS,RLF_SEARCH+RLF_MATCH + jz read_line_loop ; is searching/matching on ? + push si ; save current offset + call search_cmd + pop ax ; this is our target offset +read_ll20: + cmp ax,si ; are we there yet ? + jae read_line_loop + push ax ; no, keep rewinding cursor + call prev_char ; until we reach position + pop ax ; before we tried to match + jmps read_ll20 + +read_ll_found_cmd: ; get the address of the corresponding + mov cx,EDIT_FUNC ; function from the table + call cx ; execute the correct function + jmps read_line_loop ; and go back for next character + +eject +; +; the SAVE_CHAR routine will write the character in AL into +; the buffer in memory and then update the screen image. The +; RLF_INS flag is used to determine if INSERT is active. +; +save_c10: + ret + +save_char: + cmp ah,TRUE ; Ignore any un-matched escape + jz save_c10 ; sequences + call save_kanji ; Test if AL is a Kanji Character + ; and setup up the parameter blocks + ; for the INTSAVE_CHAR routine +; +; INTSAVE_CHAR is the internal entry point to the Character Save +; routine. It assumes the following:- +; +; On Entry:- AX(AL) Contains the character +; CX the new character length in bytes +; RLF_KANJI Flag is set for a Kanji Character +; RL_KANJI Contains the kanji charater +; +intsave_char: + mov bx,cx + test RL_FLAGS,RLF_INS ; Overwrite the character in the + jnz save_c50 ; buffer currently + add bx,si ; Add the current index to the character + cmp bx,RL_MAXLEN ; size and compare against the buffer len + jae bell_char ; Full ? Yes Ring dat Bell ! + + cmp dx,si ; Are we at the end of the line + jnz intsave_c10 ; No so check character types + push ax ! push cx + call skip_one_char ; Skip the coresponding character in + pop cx ! pop ax ; the save buffer + jmps simple_save + +intsave_c10: + push ax ; Save the Input Character + call char_type ; Get the character type + mov bx,ax ; and save in BX + mov al,es:[di] ; get the byte to be replaced + call char_type ; and get its type + and ah,CHAR_SIZE ; Mask the Character SIZE attributes + and bh,CHAR_SIZE ; and check both storage and display + ; sizes are the same for old and new + cmp ah,bh ; and do simple save if the character + pop ax ; Restore the input character to AX(AL) + jnz save_c30 ; type match + sub dx,cx ; Character overwritten so prevent + ; Max Index being incremented + +simple_save: + add si,cx ; Assume at the EOL + add dx,cx + stosb ; Save the character typed + test RL_FLAGS,RLF_KANJI ; is this a Kanji character + jz simple_s10 ; No so just output 1 character + call put_char ; and echo it to the user + mov al,byte ptr RL_KANJI+1 ; Get the high byte of the Kanji + stosb ; character save and then display it. +simple_s10: + jmp put_char +; ret + +; +; The SAVE_C30 function supports the Complex overwrite conditions +; where the size of the character in memory or on the display do not +; match with those of the present incumbent. eg a SPACE character +; overwriting a TAB or a KANJI character overwriting a SPACE. +; +; To minimize the complexity of the code the character to be +; overwritten is deleted and the new character then inserted. +; This is not an optimal solution but drastically reduces the +; amount of code required. +; +save_c30: + push ax ! push cx + call deln_char + pop cx ! pop ax + cmp dx,si + jz simple_save + or RL_FLAGS,RLF_INS + call save_c50 + and RL_FLAGS,not RLF_INS + ret + +bell_char: + mov al,BELL + jmp write_char +; +; This code is called when INSERT mode is active and a +; character (possibly Kanji) is to be inserted in the buffer +; +; On Entry:- CX the new character length in bytes +; +save_c50: + mov bx,cx ; Save new character length + add cx,dx ; Add the current max to the character + cmp cx,RL_MAXLEN ; size and compare against the buffer len + jae bell_char ; Full ? Yes Ring dat Bell ! + mov cx,bx ; Restore Character Length + cmp dx,si ; If we are at the end of the line + je simple_save ; Use the simple save code +; +; Create space in the current buffer for the new character +; + push ds + push si ! push di + mov cx,dx ! sub cx,si ; CX -> Number of bytes to move + mov di,dx ! add di,RL_BUFOFF ; DI -> End of Destination Offset + add di,bx ! dec di ; -> + Insert Char len - 1 + mov si,di ! sub si,bx ; SI -> DI - Insert Char Len + push es ! pop ds ; DS == ES + std ; Make the right amount of space in + rep movsb ; the buffer + cld + pop di ! pop si + pop ds + + add dx,bx ; Update the Buffer Length + stosb ; Save the New character + test RL_FLAGS,RLF_KANJI ; Check if this was a Kanji Character + jz save_c60 ; No + xchg al,ah ! stosb ; Yes Save high byte + +save_c60: + mov cx,dx ! sub cx,si ; Display the updated string + add si,bx ! push si ; Save the Updated Index + mov si,di ! sub si,bx ; Get the offset of the new char + call put_string ; in the buffer and display all + pop si ; Restore the new index + xchg di,dx ; and calculate the number of BS + call calc_chars ; characters required to get back + xchg di,dx + jmp bs_out +; +; On Entry: AL First byte of Character +; +; On Exit: AX Complete Character Code +; CX Character Size Bytes +; RL_KANJI and RLF_KANJI set correctly +; +save_kanji: + and RL_FLAGS,not RLF_KANJI + mov RL_KANJI,ax ; Save the Character + call char_type ; Is this the first byte of a + test ah,CHAR_KANJI ; two byte Kanji character + mov cx,1 ; Character size in bytes + jz save_k10 ; No + or RL_FLAGS,RLF_KANJI ; Set internal Flag + call get_char ; Get the high byte and save + mov byte ptr RL_KANJI+1,al ; in the local variable + mov ax,RL_KANJI ; Get the complete character + mov cx,2 ; Character size in bytes +save_k10: + ret + +eject +; +; The following group of functions modify the flags which control +; the command line editor. +; +toggle_ins: + xor RL_FLAGS,RLF_INS ; Toggle the OverWrite/Insert + ret ; Flag + +toggle_search: + and RL_FLAGS,not RLF_MATCH ; clear match bit + xor RL_FLAGS,RLF_SEARCH ; Toggle the Search on/off flag + ret + +eject +; +; This group of functions moves the cursor along the display +; as well as updating the local variables. +; +goto_bol: + test si,si ; Move the cursor to the begining of + jz goto_b10 ; the displayed line + mov di,si ; Set the buffer index to the + xor si,si ; start of the line and the current + call calc_chars ; location + call bs_out + xor si,si + mov di,RL_BUFOFF +goto_b10: + ret + +next_char: + cmp si,dx + jnz next_c05 ; Treat this as "F1" when we at the + jmp copy_char ; end of the line + +next_c05: + mov al,es:[di] ; Get the Offset of the next character + mov cx,1 ; the character itself and assume + call char_type ; it is 1 byte long + test ah,CHAR_KANJI ! jz next_c10 + inc cx +next_c10: + xchg si,di ; Get the string offset in SI + call put_string ; display the character and + xchg si,di ; restore the register contents + add si,cx + add di,cx + ret + +prev_char: + test si,si ; begining of line ? + jz prev_w30 + push dx ! push si ! push di + mov si,RL_BUFOFF ; Scan from the begining of the buffer + mov dx,si ; keeping the last match in DX +prev_c10: + call char_info ; Get the character information + cmp si,di ; Stop when we get to the current + je prev_w20 ; character location + mov dx,si ; Save current location + jmps prev_c10 ; and repeat + +prev_w20: + sub si,dx ; Calculate character length + push si ; save for update + + sub di,RL_BUFOFF ; Convert Offset to Index + neg si ! add si,di ; Set the buffer index to the current + call calc_chars ; location and the previous character + call bs_out ; BackSpace over character + pop cx ; Restore the character size + pop di ! pop si ! pop dx + sub si,cx ; Update the Index and Pointer + sub di,cx ; variables. +prev_w30: + ret + +eject +; +; This group of functions deletes characters or groups of characters +; from the buffer. +; + +delf_char: + cmp si,dx ; any chars to our right ? + jb deln_char ; yes, delete them first + jmp skip_one_char +; ret ; discard next saved char + +del_eol: + mov cx,dx ! sub cx,si ; Calculate the number of bytes to + jcxz del_eol10 ; delete and jump to DELN_WORD if + add cx,di ; non zero. Convert to an offset + jmps deln_w10 ; and jmp to common code. +del_eol10: + ret + +delp_char: + or si,si ! jz del_eol10 ; Ignore if the user is at the start + call back_one_char ; of the line otherwise move back one + call prev_char ; character in the line buffer + + +deln_char: + cmp dx,si ! jz del_eol10 + mov al,es:[di] ; Get the Offset of the next character + lea cx,1[di] ; the character itself and assume + call char_type ; it is 1 byte long + test ah,CHAR_KANJI ! jz deln_w10 + inc cx +; jmps deln_w10 + +; +; The 3 delete functions come together at this point with the standard +; register format Plus CX is the offset of the first character not to +; be deleted. +; +deln_w10: + push cx ; Save Delete Offset + xchg di,dx ; Determine the no of characters + call calc_chars ; displayed to the end of the line + xchg di,dx + mov bx,cx ; Save the Column count + pop ax ; restore the delete offset + + push bx ! push bx ; Save the count twice + + push si ! push di + mov cx,dx ! sub cx,si ; No of chars from old EOL + mov si,ax ; Get the Source Offset + sub ax,di ; calculate its length. + sub dx,ax ; Update the string length + + sub cx,ax ; Number of chars to copy + push ds ; Move the contents of the + push es ! pop ds ; string down in memory and + rep movsb ; then update the screen image + pop ds + pop si ! pop di ; Get the current buffer offset + ; Restore SWAPPED SI <-> DI + + mov cx,dx ; Calculate the length of the + sub cx,di ; string and print it alll + call put_string + xchg si,di ; Restore SI and DI + + jcxz deln_w20 + xchg di,dx ; Calculate the number of columns + call calc_chars ; displayed + xchg di,dx + +deln_w20: + pop bx ; Restore the original line length + sub bx,cx ; and calculate the number of spaces + mov cx,bx ; required to overwrite the data + call space_out + + pop cx ; Finally move the cursor back to + jmp bs_out ; its correct place + + + + +; +; Delete the contents of the complete line +; +del_line: + mov RL_SAVPOS,0 ; Reset the buffer index + test dx,dx + jz del_l10 + call goto_bol ; Jump to the begining of the line + mov di,dx ; calculate the number of display + call calc_chars ; columns it currently takes up + call space_out ; Overwrite with spaces + call bs_out ; Move back to the start of the line + xor si,si ; and update all the initial variables + mov dx,si + mov di,RL_BUFOFF +del_l10: + ret + +eject +; +; The following routines manipulate the SAVE Buffer data. Which +; is initialised on entry to this function. +; +; SKIP_ONE_CHAR increments the Save Buffer control variables and +; returns the number of bytes skipped in CX. +; +; On Entry: Standard Registers +; +; On Exit: AX Next Character in Buffer +; CX Character Size (Bytes) +; +skip_one_char: + xor cx,cx + mov bx,RL_SAVPOS ; Update the Save Buffer variables + cmp bx,RL_SAVMAX ; Check the current save buffer is + jae soc_20 ; valid and has not been exhausted. + ; Otherwise increment the RL_SAVPOS + mov bx,offset savbuf ; pointer by one character. This + add bx,RL_SAVPOS ; means that the RL_SAVPOS can be + mov al,ds:[bx] ; incremented by 1 or 2 depending on + call char_type ; the contents of the buffer + test ah,CHAR_KANJI + jz soc_10 + mov ah,ds:1[bx] + inc cx +soc_10: + inc cx +soc_20: + add RL_SAVPOS,cx + ret +; +; +; BACK_ONE_CHAR decrements the Save Buffer control variables and +; returns the number of bytes skipped in CX. +; +; On Entry: Standard Registers +; +; On Exit: RL_SAVPOS points to previous buffer char +; AX,BX,CX,DX Unknown +; +back_one_char: + push dx + mov bx,offset savbuf ; Get the Buffer address + mov cx,bx ! add cx,RL_SAVPOS ; CX is the Current location + mov dx,bx ; DX is last matching character +boc_10: + cmp bx,cx ; Have we reached the current Char + jz boc_20 ; Yes exit and update buffer + mov dx,bx ; Update last character location + mov al,ds:[bx] ; incremented by 1 or 2 depending on + call char_type ; the contents of the buffer + inc bx + test ah,CHAR_KANJI ; Increment pointer by 2 for a Kanji + jz boc_10 ; character + inc bx + jmps boc_10 + +boc_20: + sub dx,offset savbuf ; Calculate the character Index + mov RL_SAVPOS,dx ; and save in RL_SAVPOS + pop dx + ret + +copy_char: + cmp dx,si ; If at end of line copy characters + jz copy_c5 + call next_char ; Otherwise just move by 1 + jmp copy_c10 +copy_c5: + call skip_one_char ; Calculate Bytes to copy + jcxz copy_c10 ; Skip Update in no characters skipped + sub RL_SAVPOS,cx ; Restore the Buffer Position + jmps copy_a10 ; and copy the data +copy_c10: + ret + +copy_till_char: + cmp dx,si ; Copy out if at end of line + jnz move_till_char + call skip_till_char ; Returns index to the next char + sub RL_SAVPOS,cx + jmps copy_a10 +move_till_char: + mov RL_SAVPOS,si ; Start search from the current + call skip_till_char ; position + jcxz no_move ; CX=0 - dont move +move_along: + push cx + call next_char ; Shuttle along the line until + pop cx ; we reach the character + loop move_along +no_move: + ret + +copy_all: + mov cx,RL_SAVMAX ; Calculate the number of bytes to + sub cx,RL_SAVPOS ; copy from the buffer. +copy_a10: + cmp cx,0 ; do we have nothing to copy + jle copy_a30 ; (or less than nothing..) + + push RL_FLAGS ; Save State flags and prevent + or RL_FLAGS,RLF_INS ; SAVPOS being modified +copy_a20: + push cx + and RL_FLAGS,not RLF_KANJI + call skip_one_char ; Return the next character and its + cmp cx,1 + jz copy_a25 ; size in bytes + mov RL_KANJI,ax ; Save the Kanji Character and + or RL_FLAGS,RLF_KANJI ; set the control flag + pop bx + dec bx + push bx ; Decrement the Loop Count + +copy_a25: + call intsave_char ; Save the character + pop cx ; and repeat till all bytes have + loop copy_a20 ; been copied + pop RL_FLAGS ; Restore State Flags +copy_a30: + ret + +skip_till_char: + call get_char ; Get the first character + call save_kanji ; Setup RL_KANJI etc. + push dx + call skip_one_char ; don't match on 1st char + mov dx,cx ; remember we've skipped 1st char + jcxz stc_40 ; buffer exhausted +stc_10: + call skip_one_char ; Get the Next Character + jcxz stc_40 ; Buffer exhausted + add dx,cx ; Update the Total Byte Count + cmp cx,2 ! jz stc_20 ; Was this a Kanji Character + test RL_FLAGS,RLF_KANJI ; No but are we looking for one ? + jnz stc_10 ; Yes so get the next character + cmp al,byte ptr RL_KANJI ; Have we got a matching character ? + jnz stc_10 ; No so look again + jmps stc_30 ; Return Sucess + +stc_20: ; Kanji Character in Buffer + test RL_FLAGS,RLF_KANJI ; Are we looking for a Kanji Char + jz stc_10 ; No so try again + cmp ax,RL_KANJI ; Check the character and repeat + jnz stc_10 ; if they donot match + +stc_30: ; Character Match + sub dx,cx ; Correct the Total Byte Count + sub RL_SAVPOS,cx ; point to the matching char + xchg cx,dx ; and return the Match Count + pop dx + ret + +stc_40: ; No Match + sub RL_SAVPOS,dx ; Restore RL_SAVPOS to orginal value + xor cx,cx ; and return 0000 characters skipped + pop dx + ret + +; +; Update the Save buffer with the contents of the users +; line buffer. +; +; On Entry: ES:DI -> Current location in Buffer +; DX No. of bytes in buffer +; +; On Exit: Update RL_SAVMAX, RL_SAVPOS, RL_SAVBUF +; +save_line: + xor ax,ax + mov RL_SAVPOS,ax + mov RL_SAVMAX,ax + mov cx,dx ; Current Line Length + jcxz save_l10 + cmp cx,savbuf_size ; clip the amount saved + jb save_l5 ; to be a maximum of + mov cx,savbuf_size ; the save buffer size +save_l5: + mov RL_SAVMAX,cx ; Set the Save Data Length + push ds ! push es + push si ! push di + + push ds ! pop es + lds si,RL_BUFPTR + mov di,offset savbuf + rep movsb ; save the data + pop di ! pop si + pop es ! pop ds +save_l10: +; ret + +ignore_char: + ret + +mem_line: ;; JFL save from beginning of line + call save_line + jmp goto_bol +; ret + + +eof_char: ;; JFL make F6 return a CTL Z + mov al,01Ah + mov cx,1 + jmp intsave_char +; ret + +ctlat_char: ;; JFL make F7 return a CTL @ + mov al,0h + mov cx,1 + jmp intsave_char +; ret + + +eject +; +; CHAR_TYPE get the next character from the buffer ES:SI and returns +; its type in AH using the equates CHAR_????. The character is returned +; in AL. +; +; +; +char_type: + mov ah,CHAR_SPACE or CHAR_STD ; WhiteSpace + cmp al,' ' ! jz char_t100 + mov ah,CHAR_TAB ; Tab Character + cmp al,TAB ! jz char_t100 + mov ah,CHAR_ALPHAN or CHAR_STD + cmp al,CTLU ! jz char_t100 ; Control-U and Control-T are treated + cmp al,CTLT ! jz char_t100 ; as normal characters + mov ah,CHAR_CTL ; Control Character + cmp al,' ' ! jb char_t100 + + mov ah,CHAR_ALPHAN or CHAR_STD + cmp al,'0' ! jb char_t90 ; Return SYMBOL + cmp al,'9' ! jbe char_t100 ; Return AlphaNumeric + cmp al,'A' ! jb char_t90 ; Return Symbol + cmp al,'Z' ! jbe char_t100 ; Return AlphaNumeric + cmp al,'a' ! jb char_t90 ; Return Symbol + cmp al,'z' ! jbe char_t100 ; Return AlphaNumeric + cmp al,80h ! jb char_t90 ; Return Symbol + + mov ah, CHAR_KANJI ; assume character is 16 bits + call dbcs_lead ; is byte a DBCS lead? + je char_t100 ; yes - done +char_t90: + mov ah,CHAR_OTHER or CHAR_STD ; no - Normal Character Symbol + +char_t100: + ret + + + + + +; +; CHAR_INFO will return various information about the character +; at ES:SI +; +; On Entry: ES:SI Character Pointer +; BX Current Column No. +; CX Byte Scan Count +; +; On Exit: ES:SI Points to the next Character +; BX Updates Column No. +; CX Updates Byte Scan Count +; AH Character type Flags +; AL First byte of Character +char_info: + lods es:al + call char_type ; Test the character type and assume + inc bx ; it will take 1 Screen location + test ah,CHAR_ONECOL + jnz char_i20 + + inc bx ; Now check for the Control Characters + test ah,CHAR_CTL ; which take up 2 cols + jnz char_i20 + + test ah,CHAR_KANJI ; If this was the first byte of a + jz char_i10 ; KANJI character then skip the + inc si ! dec cx ; next byte + jmps char_i20 + +char_i10: + push ax ; Save AX and calculate the number + dec bx ! dec bx ; of screen locations that this TAB + mov ax,bx ; character will use based on the fact + and ax,7 ; BX contains the current column + neg ax ! add ax,8 + add bx,ax + pop ax + +char_i20: + ret + +eject +; +; CALC_CHARS calculates the number of character locations used +; on the screen to display a particular sub-string of the current +; buffer. This routine takes account of the Kanji, Control and TAB +; characters. +; +; On Entry: SI Start Buffer Index +; DI End Buffer Index +; +; On Exit: CX Count +; +calc_chars: + push bx + push si ! push di + mov bx,RL_INICOL ; Get the initial Column + sub di,si ; DI = Sub-string length bytes + mov cx,si ; Use the Start Index for the + mov si,RL_BUFOFF ; initial count and scan from the + jcxz calc_c20 ; start of the buffer + +calc_c10: + call char_info + loop calc_c10 + +calc_c20: + mov cx,di ; Sub-String Length + mov di,bx ; Current Column position + +calc_c30: + call char_info + loop calc_c30 + + sub bx,di + mov cx,bx + pop di ! pop si + pop bx + ret + +eject +; +; The following functions are purely Low level character output +; functions. +; +space_out: ; Write CX Space characters to the + mov al,' ' ; Output handle + jmps block_out + +bs_out: + mov al,CTLH ; Write CX BackSpace characters to +;; jmps block_out ; Output Handle + +block_out: + jcxz block_o20 + push cx +block_o10: + call write_char ; output this character + loop block_o10 + pop cx +block_o20: + ret + +; +; Display CX characters from the string at ES:SI +; +put_string: + jcxz puts_s20 + push cx ! push si +put_s10: + push cx + lods es:al + call put_char + pop cx + loop put_s10 + pop si ! pop cx +puts_s20: + ret + +; +; Display the character in AL +; +put_char: + cmp al,' ' ! jae write_char ; skip if it's printable + cmp al,CTLT! je write_char ; Control-T and Control-U are treated + cmp al,CTLU! je write_char ; like normal Characters. + cmp al,TAB ! je write_char ; skip if it's TAB + or al,040h ; Convert Character to Uppercase + push ax ; save it + mov al,'^' ; display the character + call write_char ; in ^X format + pop ax +write_char: + push es + push dx + push cx + push si + push di + push ax ; char on stack + mov bx,RL_OUTPUT ; Output AL to the OUTPUT Handle + push ss ! pop es ; ES:DX -> Character Buffer + mov si,sp ; buffer offset + mov cx,1 ; character count + call cooked_write ; Write Character + pop ax + pop di + pop si + pop cx + pop dx + pop es + ret +; +; Read 1 a character from RL_INPUT saving all the vital registers +; from corruption. If the first character is the ESCAPE character +; set AH to TRUE and read the next byte. Otherwise AH is FALSE +; +get_char: + push ds + push es + push dx + push si + push di + + call get_dseg ; point at pcmode data + lds si,con_device ; DS:SI -> current console device + test ds:DH_ATTRIB[si],DA_IOCTL ; test bit 14: IOCTL bit + jz get_c05 ; error if IOCTL not supported + sub sp,RH_SIZE ; reserve this many words on the stack + mov bx,sp ; SS:BX -> request packet + push ss ! pop es ; ES:BX -> request packet + lea dx,RL_FLAGS ; point at flags + mov es:RH_CMD[bx],CMD_OUTPUT_IOCTL + mov es:RH_LEN[bx],RH4_LEN + mov es:RH4_BUFOFF[bx],dx ; set up for a normal + mov es:RH4_BUFSEG[bx],ss ; IOCTL read/write + mov es:RH4_COUNT[bx],WORD + call device_driver ; execute the command + add sp,RH_SIZE ; reclaim the stack +get_c05: + + call get_dseg ; point at pcmode data + mov bx,RL_INPUT ; BX = input stream + call cmdline_read ; get a character + + mov ah,FALSE ; Assume this is NOT the Escape + cmp al,esc_char ; character and set high byte of the + jnz get_c10 ; match word to FALSE + + call raw_read ; read the second byte of the escape + mov ah,ESC_CODE ; sequence, setting high byte to ESC +get_c10: + pop di + pop si + pop dx + pop es + pop ds + ret + +PCM_RODATA CSEG WORD + +EDIT_CNTRL equ cs:word ptr 0[bx] ; Character and Esc Flag +EDIT_FUNC equ cs:word ptr 2[bx] ; Edit Function Address +EDIT_LEN equ 4 ; Edit Table Entry Size + +esc_char db 0 ; Command Line Editor Escape Character +edit_size dw (offset edit_end - edit_table)/EDIT_LEN + +edit_table db CR ! db NESC_CODE ! dw ret_string + db LF ! db NESC_CODE ! dw ignore_char + db CTLH ! db NESC_CODE ! dw delp_char + db DEL ! db NESC_CODE ! dw delf_char + + db ESC ! db NESC_CODE ! dw del_line + db ';' ! db ESC_CODE ! dw copy_char ; Function 1 + db '<' ! db ESC_CODE ! dw copy_till_char ; Function 2 + db '=' ! db ESC_CODE ! dw copy_all ; Function 3 + db '>' ! db ESC_CODE ! dw skip_till_char ; Function 4 + db '?' ! db ESC_CODE ! dw mem_line ; Function 5 + + db '@' ! db ESC_CODE ! dw eof_char ; Function 6 + db 'A' ! db ESC_CODE ! dw ctlat_char ; Function 7 + db 'B' ! db ESC_CODE or DISABLE ! dw match_cmd ; Function 8 + + db 'R' ! db ESC_CODE ! dw toggle_ins ; Insert + db 'S' ! db ESC_CODE ! dw delf_char ; Delete + db 'K' ! db ESC_CODE or DISABLE ! dw prev_char ; Left Arrow + db 'M' ! db ESC_CODE or DISABLE ! dw next_char ; Right Arrow +; When advanced editing is disabled the match for Left/Right arrows will fall +; through to here + db 'K' ! db ESC_CODE ! dw delp_char ; Left Arrow - compat + db 'M' ! db ESC_CODE ! dw copy_char ; Right Arrow - compat +; +; Extended functions from here on +; + db 'C' ! db ESC_CODE or DISABLE ! dw del_cur_history_buffer ; Func 9 + db 'D' ! db ESC_CODE or DISABLE ! dw del_history_buffers ; Func 10 + db 'G' ! db ESC_CODE or DISABLE ! dw goto_bol ; Home + db 'O' ! db ESC_CODE or DISABLE ! dw goto_eol ; End + db 't' ! db ESC_CODE or DISABLE ! dw next_word ; Control Right Arrow + db 's' ! db ESC_CODE or DISABLE ! dw prev_word ; Control Left Arrow + + + db CTLV ! db NESC_CODE or DISABLE ! dw toggle_ins + db CTLQ ! db NESC_CODE or DISABLE ! dw goto_bol + db CTLW ! db NESC_CODE or DISABLE ! dw goto_eol + db CTLR ! db NESC_CODE or DISABLE ! dw match_cmd + db CTLD ! db NESC_CODE or DISABLE ! dw next_char + db CTLS ! db NESC_CODE or DISABLE ! dw prev_char + db CTLF ! db NESC_CODE or DISABLE ! dw next_word + db CTLA ! db NESC_CODE or DISABLE ! dw prev_word + db CTLG ! db NESC_CODE or DISABLE ! dw deln_char + db CTLT ! db NESC_CODE or DISABLE ! dw deln_word + db CTLY ! db NESC_CODE or DISABLE ! dw del_line + db CTLB ! db NESC_CODE or DISABLE ! dw del_bol + db CTLK ! db NESC_CODE or DISABLE ! dw del_eol + + db 'I' ! db ESC_CODE or DISABLE ! dw ignore_char ; PageUP + db 'Q' ! db ESC_CODE or DISABLE ! dw ignore_char ; PageDown + db 'H' ! db ESC_CODE or DISABLE ! dw prev_cmd ; Up Arrow + db 'P' ! db ESC_CODE or DISABLE ! dw next_cmd ; Down Arrow + db CTLE ! db NESC_CODE or DISABLE ! dw prev_cmd + db CTLX ! db NESC_CODE or DISABLE ! dw next_cmd + db CTLUB ! db NESC_CODE or DISABLE ! dw toggle_search ; Default search mode +edit_end rb 0 + + +PCMODE_DATA DSEG WORD + + extrn con_device:dword ; Current Console Device + extrn column:byte ; Console Cursor Location + + savbuf_size equ 128 + + extrn savbuf:byte ; fixed location in DOS data area + + extrn cle_state:word ; command line editing state + + end + diff --git a/IBMDOS/CMDLINE.EQU b/IBMDOS/CMDLINE.EQU new file mode 100644 index 0000000..633a918 --- /dev/null +++ b/IBMDOS/CMDLINE.EQU @@ -0,0 +1,70 @@ +; File : $CMDLINE.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG + +RL_INPUT equ word ptr -2[bp] ; READ_LINE Input Handle +RL_OUTPUT equ word ptr -4[bp] ; READ_LINE Output Handle +RL_BUFSEG equ word ptr -6[bp] ; Retained line Segment +RL_BUFOFF equ word ptr -8[bp] ; Retained line Offset +RL_BUFPTR equ dword ptr -8[bp] ; Retained line Buffer +RL_INICOL equ word ptr -10[bp] ; initial column +RL_FLAGS equ word ptr -12[bp] ; Control Flags +RL_MAXLEN equ word ptr -14[bp] ; Maximum Buffer Size +RL_KANJI equ word ptr -16[bp] ; Kanji Character Buffer +RL_SAVMAX equ word ptr -18[bp] ; Size of retained data +RL_SAVPOS equ word ptr -20[bp] ; Current Position in data +RL_HIST_RECL equ word ptr -22[bp] ; We recall from here +RL_HIST_SAVE equ word ptr -24[bp] ; We save to here +RL_HIST_SIZE equ word ptr -26[bp] ; buffer is this big +RL_HIST_SEG equ word ptr -28[bp] ; buffer is at this segment +RL_LENGTH equ 28 + +RLF_ENHANCED equ 0000$0001b ; Enhanced features are on +RLF_INS equ 0000$0010b ; Insert Flag +RLF_SEARCH equ 0000$0100b ; Search mode on +RLF_MATCH equ 0000$1000b ; We are matching a command +RLF_RECALLED equ 0001$0000b ; Line already recalled +RLF_DIRTY equ 0010$0000b ; Partial line needs saved +RLF_KANJI equ 0100$0000b ; RL_KANJI is valid +RLF_INROOT equ 1000$0000b ; In root + +CHAR_SPACE equ 0000$0001b ; Space Character +CHAR_TAB equ 0000$0010b ; Tab Character +CHAR_CTL equ 0000$0100b ; Control Character expanded to "^X" +CHAR_KANJI equ 0000$1000b ; Japanese Kanji character +CHAR_ALPHAN equ 0001$0000b ; Alpha/Numeric +CHAR_OTHER equ 0010$0000b ; Non AlphaNumeric +CHAR_STD equ 1000$0000b ; Stored as a Byte displayed in 1 Col + +CHAR_SIZE equ CHAR_STD or CHAR_KANJI or CHAR_TAB or CHAR_CTL +CHAR_ONECOL equ CHAR_SPACE or CHAR_OTHER or CHAR_ALPHAN diff --git a/IBMDOS/COUNTRY.A86 b/IBMDOS/COUNTRY.A86 new file mode 100644 index 0000000..3860b9c --- /dev/null +++ b/IBMDOS/COUNTRY.A86 @@ -0,0 +1,3662 @@ +NOIFLIST +TITLE 'National Data' +; File : $COUNTRY.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; COUNTRY.A86 1.14 94/09/07 11:47:03 +; Added Brazilian (55) country support. +; COUNTRY.A86 1.10 93/11/19 16:25:11 +; Change some countries to 24 hour format +; COUNTRY.A86 1.9 93/11/18 19:49:03 +; Change German time seperator from '.' to ':' - +; COUNTRY.A86 1.8 93/09/02 22:23:32 +; Turn on COMPATIBLE flag +; COUNTRY.A86 1.6 93/06/23 19:58:29 +; Remove historic CDOS and DOSPLUS defines, add new COUNTRY define +; +; ENDLOG +; + +; COUNTRY.ASM source for DR-DOS 3.3 COUNTRY.SYS +; generation: +; RASM86 country +; LINKEXE country +; BIN2ASC -ob -s512 country.exe +; DEL country.sys +; REN country.bin country.sys +; +; +; History: +; 26/May/88 Remove incorrect CS override in International Uppercase routine. +; 20/Jun/89 Added AUSTRIA (43) for German Office. +; 10/Oct/89 Added double byte character set lead byte range table DBCS_tbl. +; 16/Feb/90 Change default Japanese and Korean Code Pages to be 932 and 934 respectively. +; 21/Feb/90 cur_cp and cur_country added +; 23/May/90 Added Russian Country data and CodePage 866 Support +; ??/???/90 Added compatibility flag +; 23/Jul/90 Added Turkish Country Data and CodePage 853 Support +; 17/Sep/90 Turkish uses CodePage 857 +; 17/Sep/90 Change Spain 850 to 3 character currency symbol 'Pts' +; 21/Sep/90 Added Hungarian Country data and CodePage 852 Support +; 31/Oct/90 Amended Hungarian data +; 21/Nov/90 Corrected Hungarian Codepages 852 and 850 +; 13/Dec/90 Corrected SpainCollating entries for '€', '‡', '¤', and '¥'. +; 19/Dec/90 Use Collating850 for Spain and Denmark. +; +VALID_SIG equ 0EDC1h + +COMPATIBLE equ 1 +TURKCP equ 857 ; Turkish Code Page (853 or 857) +; + eject ! include i:country.def +; +DGROUP group _DATA +_DATA dseg word 'DATA' +; +; File structure: List of country information pointers +; country code dw ; Header words +; code page number dw ; +; unused dw +; Data dw -> ; Pointer to 16 byte data area +; StdUcase dw -> ; Pointer to Std Uppercase table +; unused dw +; Ucase dw -> ; Pointer to Uppercase table +; FileChars dw -> ; Pointer to legal file characters +; Collating dw -> ; Pointer to collating table +; unused dw +; +; ** IMPORTANT ** The list is sorted by country code, codepage and is +; terminated by a record of nulls +; +; +; +; Copyright message such that it will be displayed if a user tries to 'type' the +; file. *NOTE* This message is of a fixed length, (3Fh) bytes. + + org 0 +copyright: + db 'COUNTRY.SYS R2.01 Copyright (c) 1988,1996 Caldera, Inc.' + db 0Ah,0Dh,0 + db 01Ah ; End of file to stop 'type'. + + org 7Eh + dw VALID_SIG ; signature word + + org 80h +US_xlat equ 0 +Russian_xlat equ 0 +Turkish_xlat equ 0 +Canadian_xlat equ 0 +Dutch_xlat equ 0 +Belgian_xlat equ 0 +French_xlat equ 0 +Spanish_xlat equ 0 +Hungarian_xlat equ 0 +Italian_xlat equ 0 +Swiss_xlat equ 0 +UK_xlat equ 0 +Danish_xlat equ 0 +Swedish_xlat equ 0 +Norwegian_xlat equ 0 +German_xlat equ 0 +Australian_xlat equ 0 +Portugese_xlat equ 0 +Finish_xlat equ 0 +Arabic_xlat equ 0 +Jewish_xlat equ 0 +xlat_850 equ 0 +Default_xlat equ 0 + +; +; The following array of country information contain all the +; predefined country data tables used by PCMODE. +; + +UnitedStates: + dw 1 ; Country code + dw 437 ; Code page number + dw 0 + dw offset UnitedStatesData ; Data area + dw offset Ucasetbl ; Uppercase table + dw 0 + dw offset Ucasetbl ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collatingtbl ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +UnitedStates850: + dw 1 ; Country code + dw 850 ; Code page number + dw 0 + dw offset UnitedStatesData850 ; Data area + dw offset Ucasetbl850 ; Uppercase table + dw 0 + dw offset Ucasetbl850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Canada: + dw 2 ; Country code + dw 863 ; Code page number + dw 0 + dw offset CanadaData ; Data area + dw offset CanadaUcase ; Standard Uppercase table + dw 0 + dw offset CanadaUcase ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset CanadaCollating ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Canada850: + dw 2 ; Country code + dw 850 ; Code page number + dw 0 + dw offset CanadaData850 ; Data area + dw offset Ucasetbl850 ; Standard Uppercase table + dw 0 + dw offset Ucasetbl850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +LatinAmerica: + dw 3 ; Country code + dw 437 ; Code page number + dw 0 + dw offset LatinAmericaData ; Data area + dw offset Ucasetbl ; Uppercase table + dw 0 + dw offset Ucasetbl ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset SpainCollating ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +LatinAmerica850: + dw 3 ; Country code + dw 850 ; Code page number + dw 0 + dw offset LatinAmericaData850 ; Data area + dw offset LatiCase850 ; Uppercase table + dw 0 + dw offset LatiCase850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset LatiCollating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Russian: + dw 7 ; Country code + dw 866 ; Code page number + dw 0 + dw offset RussianData ; Data area + dw offset RussianUcase ; Standard Uppercase table + dw 0 + dw offset RussianUcase ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset RussianCollating ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Russian850: + dw 7 ; Country code + dw 850 ; Code page number + dw 0 + dw offset RussianData850 ; Data area + dw offset Ucasetbl850 ; Standard Uppercase table + dw 0 + dw offset Ucasetbl850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Netherlands: + dw 31 ; Country code + dw 437 ; Code page number + dw 0 + dw offset NetherlandsData ; Data area + dw offset NetherlandsUcase ; Standard Uppercase table + dw 0 + dw offset NetherlandsUcase ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset NetherlandsCollating ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Netherlands850: + dw 31 ; Country code + dw 850 ; Code page number + dw 0 + dw offset NetherlandsData850 ; Data area + dw offset NethCase850 ; Standard Uppercase table + dw 0 + dw offset NethCase850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset NethCollating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Belgium: + dw 32 ; Country code + dw 437 ; Code page number + dw 0 + dw offset BelgiumData ; Data area + dw offset SwedenUcase ; Standard Uppercase table + dw 0 + dw offset SwedenUcase ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset BelgiumCollating ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Belgium850: + dw 32 ; Country code + dw 850 ; Code page number + dw 0 + dw offset BelgiumData850 ; Data area + dw offset LatiCase850 ; Standard Uppercase table + dw 0 + dw offset LatiCase850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset BelgCollating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +France: + dw 33 ; Country code + dw 437 ; Code page number + dw 0 + dw offset FranceData ; Data area + dw offset Ucasetbl ; Uppercase table + dw 0 + dw offset Ucasetbl ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collatingtbl ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +France850: + dw 33 ; Country code + dw 850 ; Code page number + dw 0 + dw offset FranceData850 ; Data area + dw offset Ucasetbl850 ; Uppercase table + dw 0 + dw offset Ucasetbl850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Spain: + dw 34 ; Country code + dw 437 ; Code page number + dw 0 + dw offset SpainData ; Data area + dw offset Ucasetbl ; Uppercase table + dw 0 + dw offset Ucasetbl ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset SpainCollating ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Spain850: + dw 34 ; Country code + dw 850 ; Code page number + dw 0 + dw offset SpainData850 ; Data area + dw offset LatiCase850 ; Uppercase table + dw 0 + dw offset LatiCase850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Hungary: + dw 36 ; Country code + dw 852 ; Code page number + dw 0 + dw offset HungaryData ; Data area + dw offset HungaryUcase ; Uppercase table + dw 0 + dw offset HungaryUcase ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset HungaryCollating ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Hungary850: + dw 36 ; Country code + dw 850 ; Code page number + dw 0 + dw offset HungaryData850 ; Data area + dw offset Ucasetbl850 ; Uppercase table + dw 0 + dw offset Ucasetbl850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Italy: + dw 39 ; Country code + dw 437 ; Code page number + dw 0 + dw offset ItalyData ; Data area + dw offset Ucasetbl ; Uppercase table + dw 0 + dw offset Ucasetbl ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collatingtbl ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Italy850: + dw 39 ; Country code + dw 850 ; Code page number + dw 0 + dw offset ItalyData850 ; Data area + dw offset Ucasetbl850 ; Uppercase table + dw 0 + dw offset Ucasetbl850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Switzerland: + dw 41 ; Country code + dw 437 ; Code page number + dw 0 + dw offset SwitzerlandData ; Data area + dw offset SwitzerlandUcase ; Standard Uppercase table + dw 0 + dw offset SwitzerlandUcase ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset SwitzerlandCollating ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Switzerland850: + dw 41 ; Country code + dw 850 ; Code page number + dw 0 + dw offset SwitzerlandData850 ; Data area + dw offset LatiCase850 ; Standard Uppercase table + dw 0 + dw offset LatiCase850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset SwisCollating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Czechoslovakia: + dw 42 ; Country code + dw 852 ; Code page number + dw 0 + dw offset CzechoslovakiaData ; Data area + dw offset CzecUcase ; Uppercase table + dw 0 + dw offset CzecUcase ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset CzecCollating ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Czechoslovakia850: + dw 42 ; Country code + dw 850 ; Code page number + dw 0 + dw offset CzechoslovakiaData850 ; Data area + dw offset CzecUcase850 ; Uppercase table + dw 0 + dw offset CzecUcase850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset CzecCollating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Austria: + dw 43 ; Country code + dw 437 ; Code page number + dw 0 + dw offset AustriaData ; Data area + dw offset Ucasetbl ; Uppercase table + dw 0 + dw offset Ucasetbl ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collatingtbl ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Austria850: + dw 43 ; Country code + dw 850 ; Code page number + dw 0 + dw offset AustriaData850 ; Data area + dw offset GermCase850 ; Uppercase table + dw 0 + dw offset GermCase850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +GreatBritain: + dw 44 ; Country code + dw 437 ; Code page number + dw 0 + dw offset GreatBritainData ; Data area + dw offset Ucasetbl ; Uppercase table + dw 0 + dw offset Ucasetbl ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collatingtbl ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +GreatBritain850: + dw 44 ; Country code + dw 850 ; Code page number + dw 0 + dw offset GreatBritainData850 ; Data area + dw offset Ucasetbl850 ; Uppercase table + dw 0 + dw offset Ucasetbl850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Denmark: + dw 45 ; Country code + dw 865 ; Code page number + dw 0 + dw offset DenmarkData ; Data area + dw offset DenmarkUcase ; Standard Uppercase table + dw 0 + dw offset DenmarkUcase ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset DenmarkCollating ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Denmark850: + dw 45 ; Country code + dw 850 ; Code page number + dw 0 + dw offset DenmarkData850 ; Data area + dw offset LatiCase850 ; Standard Uppercase table + dw 0 + dw offset LatiCase850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Sweden: + dw 46 ; Country code + dw 437 ; Code page number + dw 0 + dw offset SwedenData ; Data area + dw offset SwedenUcase ; Standard Uppercase table + dw 0 + dw offset SwedenUcase ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset SwedenCollating ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Sweden850: + dw 46 ; Country code + dw 850 ; Code page number + dw 0 + dw offset SwedenData850 ; Data area + dw offset LatiCase850 ; Standard Uppercase table + dw 0 + dw offset LatiCase850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset SwedCollating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Norway: + dw 47 ; Country code + dw 865 ; Code page number + dw 0 + dw offset NorwayData ; Data area + dw offset DenmarkUcase ; Standard Uppercase table + dw 0 + dw offset DenmarkUcase ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset NorwayCollating ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Norway850: + dw 47 ; Country code + dw 850 ; Code page number + dw 0 + dw offset NorwayData850 ; Data area + dw offset LatiCase850 ; Standard Uppercase table + dw 0 + dw offset LatiCase850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset NorwCollating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Poland: + dw 48 ; Country code + dw 852 ; Code page number + dw 0 + dw offset PolandData ; Data area + dw offset PolandUcase ; Uppercase table + dw 0 + dw offset PolandData ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset PolCollating ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Poland850: + dw 48 ; Country code + dw 850 ; Code page number + dw 0 + dw offset PolandData850 ; Data area + dw offset PolandUcase850 ; Uppercase table + dw 0 + dw offset PolandUcase850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset PolCollating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Germany: + dw 49 ; Country code + dw 437 ; Code page number + dw 0 + dw offset GermanyData ; Data area + dw offset Ucasetbl ; Uppercase table + dw 0 + dw offset Ucasetbl ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collatingtbl ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Germany850: + dw 49 ; Country code + dw 850 ; Code page number + dw 0 + dw offset GermanyData850 ; Data area + dw offset GermCase850 ; Uppercase table + dw 0 + dw offset GermCase850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + +Brazil: + dw 55 ; Country code + dw 437 ; Code page number + dw 0 + dw offset BrazilData ; Data area + dw offset BrazilUcase ; Uppercase table + dw 0 + dw offset BrazilUcase ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset BrazilCollating ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + +Brazil850: + dw 55 ; Country code + dw 850 ; Code page number + dw 0 + dw offset BrazilData850 ; Data area + dw offset BrazilUcase850 ; Uppercase table + dw 0 + dw offset BrazilUcase850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset BrazilCollat850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + +Australia: + dw 61 ; Country code + dw 437 ; Code page number + dw 0 + dw offset AustraliaData ; Data area + dw offset Ucasetbl ; Uppercase table + dw 0 + dw offset Ucasetbl ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collatingtbl ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Australia850: + dw 61 ; Country code + dw 437 ; Code page number + dw 0 + dw offset AustraliaData850 ; Data area + dw offset Ucasetbl850 ; Uppercase table + dw 0 + dw offset Ucasetbl850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Japan: + dw 81 ; Country code + dw 437 ; Code page number + dw 0 + dw offset JapanData ; Data area + dw offset Ucasetbl ; Uppercase table + dw 0 + dw offset Ucasetbl ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collatingtbl ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Japan932: + dw 81 ; Country code + dw 932 ; Code page number + dw 0 + dw offset JapanData932 ; Data area + dw offset Ucasetbl932 ; Uppercase table + dw 0 + dw offset Ucasetbl932 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collating932 ; Collating table + dw offset DBCS_932 ; double byte char set range table + + + +Korea: + dw 82 ; Country code + dw 437 ; Code page number + dw 0 + dw offset KoreaData ; Data area + dw offset Ucasetbl ; Uppercase table + dw 0 + dw offset Ucasetbl ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collatingtbl ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Korea934: + dw 82 ; Country code + dw 934 ; Code page number + dw 0 + dw offset KoreaData934 ; Data area + dw offset Ucasetbl932 ; Uppercase table + dw 0 + dw offset Ucasetbl932 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collating934 ; Collating table + dw offset DBCS_934 ; double byte char set range table + +Turkish: + dw 90 ; Country code + dw TURKCP ; Code page number + dw 0 + dw offset TurkishData ; Data area + dw offset TurkishUcase ; Standard Uppercase table + dw 0 + dw offset TurkishUcase ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset TurkishCollating ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Turkish850: + dw 90 ; Country code + dw 850 ; Code page number + dw 0 + dw offset TurkishData850 ; Data area + dw offset Ucasetbl850 ; Standard Uppercase table + dw 0 + dw offset Ucasetbl850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Portugal: + dw 351 ; Country code + dw 860 ; Code page number + dw 0 + dw offset PortugalData ; Data area + dw offset PortugalUcase ; Standard Uppercase table + dw 0 + dw offset PortugalUcase ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset PortugalCollating ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Portugal850: + dw 351 ; Country code + dw 850 ; Code page number + dw 0 + dw offset PortugalData850 ; Data area + dw offset Ucasetbl850 ; Standard Uppercase table + dw 0 + dw offset Ucasetbl850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Finland: + dw 358 ; Country code + dw 437 ; Code page number + dw 0 + dw offset FinlandData ; Data area + dw offset SwedenUcase ; Standard Uppercase table + dw 0 + dw offset SwedenUcase ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset SwedenCollating ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Finland850: + dw 358 ; Country code + dw 850 ; Code page number + dw 0 + dw offset FinlandData850 ; Data area + dw offset LatiCase850 ; Standard Uppercase table + dw 0 + dw offset LatiCase850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset FinlCollating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +MiddleEast: + dw 785 ; Country code + dw 864 ; Code page number + dw 0 + dw offset MiddleEastData ; Data area + dw offset Ucasetbl ; Uppercase table + dw 0 + dw offset Ucasetbl ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset MiddleEastCollating ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +MiddleEast850: + dw 785 ; Country code + dw 850 ; Code page number + dw 0 + dw offset MiddleEastData850 ; Data area + dw offset Ucasetbl850 ; Uppercase table + dw 0 + dw offset Ucasetbl850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Israel: + dw 972 ; Country code + dw 862 ; Code page number + dw 0 + dw offset IsraelData ; Data area + dw offset IsraelUcase ; Standard Uppercase table + dw 0 + dw offset IsraelUcase ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset IsraelCollating ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +Israel850: + dw 972 ; Country code + dw 850 ; Code page number + dw 0 + dw offset IsraelData850 ; Data area + dw offset Ucasetbl850 ; Standard Uppercase table + dw 0 + dw offset Ucasetbl850 ; Uppercase table + dw offset FileCharstbl ; File character table + dw offset Collating850 ; Collating table + dw offset DBCS_tbl ; double byte char set range table + + + +LastEntry: + dw 0 ; Country code + dw 0 ; Code page number + dw 0 + dw 0 ; Data area + dw 0 ; Standard Uppercase table + dw 0 + dw 0 ; Uppercase table + dw 0 ; File character table + dw 0 ; Collating table + dw 0 ; double byte char set range table + + +; Country Data for UnitedStates (Code - 1) +UnitedStatesData: + dw 1 ; Country Code + dw 437 ; Code Page + dw US_DATE ; Date Format (Binary) + db '$',0,0,0,0 ; Currency Symbol + db ',',0 ; Thousands Separator + db '.',0 ; Decimal Separator + db '-',0 ; Date Separator + db ':',0 ; Time Separator + db 0 ; Symbol before Value without Space ($n.nn) + db 2 ; Significant Currency Digits + db CLOCK_12 ; Time Format + dw US_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ',',0 ; Data List Separator + + +UnitedStatesData850: + dw 1 ; Country Code + dw 850 ; Code Page + dw US_DATE ; Date Format (Binary) + db '$',0,0,0,0 ; Currency Symbol + db ',',0 ; Thousands Separator + db '.',0 ; Decimal Separator + db '-',0 ; Date Separator + db ':',0 ; Time Separator + db 0 ; Symbol before Value without Space ($n.nn) + db 2 ; Significant Currency Digits + db CLOCK_12 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ',',0 ; Data List Separator + +; Country Data for Canada (Code - 2) +CanadaData850: + dw 2 ; Country Code + dw 850 ; Code Page + dw JAP_DATE ; Date Format (Binary) + db '$',0,0,0,0 ; Currency Symbol + db ' ',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '-',0 ; Date Separator + db ':',0 ; Time Separator + db 3 ; Symbol after Value with Space (n.nn $) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for Canada (Code - 2) +CanadaData: + dw 2 ; Country Code + dw 863 ; Code Page + dw JAP_DATE ; Date Format (Binary) + db '$',0,0,0,0 ; Currency Symbol + db ' ',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '-',0 ; Date Separator + db ':',0 ; Time Separator + db 3 ; Symbol after Value with Space (n.nn $) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Canadian_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for LatinAmerica (Code - 3) +LatinAmericaData: + dw 3 ; Country Code + dw 437 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db '$',0,0,0,0 ; Currency Symbol + db ',',0 ; Thousands Separator + db '.',0 ; Decimal Separator + db '/',0 ; Date Separator + db ':',0 ; Time Separator + db 0 ; Symbol before Value without Space ($n.nn) + db 2 ; Significant Currency Digits + db CLOCK_12 ; Time Format + dw Default_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ',',0 ; Data List Separator + + +; Country Data for LatinAmerica (Code - 3) +LatinAmericaData850: + dw 3 ; Country Code + dw 850 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db '$',0,0,0,0 ; Currency Symbol + db ',',0 ; Thousands Separator + db '.',0 ; Decimal Separator + db '/',0 ; Date Separator + db ':',0 ; Time Separator + db 0 ; Symbol before Value without Space ($n.nn) + db 2 ; Significant Currency Digits + db CLOCK_12 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ',',0 ; Data List Separator + + +RussianData850: ; ##JC## + dw 7 ; Country Code + dw 850 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db ' rub.' ; Currency Symbol + db ' ',0 ; Thousands Separator + db '.',0 ; Decimal Separator + db '/',0 ; Date Separator + db ':',0 ; Time Separator + db 3 ; Symbol after Value with Space (n.nn $) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Russian_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for Russia (Code - 7) +RussianData: + dw 7 ; Country Code + dw 866 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'ý',0,0,0,0 ; Currency Symbol + db ' ',0 ; Thousands Separator + db '.',0 ; Decimal Separator + db '/',0 ; Date Separator + db ':',0 ; Time Separator + db 0 ; Symbol before Value without Space ($n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Russian_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for Netherlands (Code - 31) +NetherlandsData: + dw 31 ; Country Code + dw 437 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 159,0,0,0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '-',0 ; Date Separator + db ':',0 ; Time Separator + db 2 ; Symbol before Value with Space ($ n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Dutch_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for Netherlands (Code - 31) +NetherlandsData850: + dw 31 ; Country Code + dw 850 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 159,0,0,0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '-',0 ; Date Separator + db ':',0 ; Time Separator + db 2 ; Symbol before Value with Space ($ n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for Belgium (Code - 32) +BelgiumData: + dw 32 ; Country Code + dw 437 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'BF',0,0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '/',0 ; Date Separator + db ':',0 ; Time Separator + db 2 ; Symbol before Value with Space ($ n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Belgian_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for Belgium (Code - 32) +BelgiumData850: + dw 32 ; Country Code + dw 850 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'BF',0,0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '/',0 ; Date Separator + db ':',0 ; Time Separator + db 2 ; Symbol before Value with Space ($ n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for France (Code - 33) +FranceData: + dw 33 ; Country Code + dw 437 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'F',0,0,0,0 ; Currency Symbol + db ' ',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '.',0 ; Date Separator + db ':',0 ; Time Separator + db 3 ; Symbol after Value with Space (n.nn $) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw French_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + + +; Country Data for France (Code - 33) +FranceData850: + dw 33 ; Country Code + dw 850 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'F',0,0,0,0 ; Currency Symbol + db ' ',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '.',0 ; Date Separator + db ':',0 ; Time Separator + db 3 ; Symbol after Value with Space (n.nn $) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + + +; Country Data for Spain (Code - 34) +SpainData: + dw 34 ; Country Code + dw 437 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 158,0,0,0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '/',0 ; Date Separator + db ':',0 ; Time Separator + db 2 ; Symbol before Value with Space ($ n.nn) + db 0 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Spanish_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for Spain (Code - 34) +SpainData850: + dw 34 ; Country Code + dw 850 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'Pts',0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '/',0 ; Date Separator + db ':',0 ; Time Separator + db 2 ; Symbol before Value with Space ($ n.nn) + db 0 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for Hungary (Code - 36) +HungaryData: + dw 36 ; Country Code + dw 852 ; Code Page + dw JAP_DATE ; Date Format (Binary) + db 'Ft',0,0,0 ; Currency Symbol + db ' ',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '.',0 ; Date Separator + db ':',0 ; Time Separator + db 3 ; Symbol after Value with Space (n.nn $) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Hungarian_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for Hungary (Code - 36) +HungaryData850: + dw 36 ; Country Code + dw 850 ; Code Page + dw JAP_DATE ; Date Format (Binary) + db 'Ft',0,0,0 ; Currency Symbol + db ' ',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '.',0 ; Date Separator + db ':',0 ; Time Separator + db 3 ; Symbol after Value with Space (n.nn $) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for Italy (Code - 39) +ItalyData: + dw 39 ; Country Code + dw 437 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'L.',0,0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '/',0 ; Date Separator + db '.',0 ; Time Separator + db 2 ; Symbol before Value with Space ($ n.nn) + db 0 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Italian_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for Italy (Code - 39) +ItalyData850: + dw 39 ; Country Code + dw 850 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'L.',0,0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '.',0 ; Date Separator + db ':',0 ; Time Separator + db 2 ; Symbol before Value with Space ($ n.nn) + db 0 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + + +; Country Data for Switzerland (Code - 41) +SwitzerlandData: + dw 41 ; Country Code + dw 437 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'Fr.',0,0 ; Currency Symbol + db 39,0 ; Thousands Separator + db '.',0 ; Decimal Separator + db '.',0 ; Date Separator + db ',',0 ; Time Separator + db 2 ; Symbol before Value with Space ($ n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Swiss_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + +; Country Data for Switzerland (Code - 41) +SwitzerlandData850: + dw 41 ; Country Code + dw 850 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'Fr.',0,0 ; Currency Symbol + db 39,0 ; Thousands Separator + db '.',0 ; Decimal Separator + db '.',0 ; Date Separator + db ',',0 ; Time Separator + db 2 ; Symbol before Value with Space ($ n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for Czechoslovakia (Code - 42) +CzechoslovakiaData: + dw 42 ; Country Code + dw 852 ; Code Page + dw JAP_DATE ; Date Format (Binary) + db 'K',159,'s',0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '-',0 ; Date Separator + db ':',0 ; Time Separator + db 2 ; Symbol before Value without Space ($n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw US_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ',',0 ; Data List Separator + + +CzechoslovakiaData850: + dw 42 ; Country Code + dw 850 ; Code Page + dw JAP_DATE ; Date Format (Binary) + db 'K',159,'s',0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '-',0 ; Date Separator + db ':',0 ; Time Separator + db 2 ; Symbol before Value without Space ($n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ',',0 ; Data List Separator + + +; Country Data for Austria (Code - 43) +AustriaData: + dw 43 ; Country Code + dw 437 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db '™S',0,0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '.',0 ; Date Separator + db '.',0 ; Time Separator + db 2 ; Symbol before Value with Space ($ n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw German_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + +; Country Data for Austrian (Code - 43) +AustriaData850: + dw 43 ; Country Code + dw 850 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db '™S',0,0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '.',0 ; Date Separator + db '.',0 ; Time Separator + db 2 ; Symbol before Value with Space ($ n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for GreatBritain (Code - 44) + +GreatBritainData: + dw 44 ; Country Code + dw 437 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 156,0,0,0,0 ; Currency Symbol + db ',',0 ; Thousands Separator + db '.',0 ; Decimal Separator + db '/',0 ; Date Separator + db ':',0 ; Time Separator + db 0 ; Symbol before Value without Space ($n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw UK_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ',',0 ; Data List Separator + + +; Country Data for GreatBritain (Code - 44) + +GreatBritainData850: + dw 44 ; Country Code + dw 850 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 156,0,0,0,0 ; Currency Symbol + db ',',0 ; Thousands Separator + db '.',0 ; Decimal Separator + db '/',0 ; Date Separator + db ':',0 ; Time Separator + db 0 ; Symbol before Value without Space ($n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ',',0 ; Data List Separator + + +; Country Data for Denmark (Code - 45) +DenmarkData: + dw 45 ; Country Code + dw 865 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'kr',0,0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '-',0 ; Date Separator + db '.',0 ; Time Separator + db 2 ; Symbol before Value with Space ($ n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Danish_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for Denmark (Code - 45) +DenmarkData850: + dw 45 ; Country Code + dw 850 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'kr',0,0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '-',0 ; Date Separator + db '.',0 ; Time Separator + db 2 ; Symbol before Value with Space ($ n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for Sweden (Code - 46) +SwedenData: + dw 46 ; Country Code + dw 437 ; Code Page + dw JAP_DATE ; Date Format (Binary) + db 'Kr',0,0,0 ; Currency Symbol + db ' ',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '-',0 ; Date Separator + db '.',0 ; Time Separator + db 3 ; Symbol after Value with Space (n.nn $) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Swedish_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for Sweden (Code - 46) +SwedenData850: + dw 46 ; Country Code + dw 850 ; Code Page + dw JAP_DATE ; Date Format (Binary) + db 'Kr',0,0,0 ; Currency Symbol + db ' ',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '-',0 ; Date Separator + db '.',0 ; Time Separator + db 3 ; Symbol after Value with Space (n.nn $) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for Norway (Code - 47) +NorwayData: + dw 47 ; Country Code + dw 865 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'Kr',0,0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '.',0 ; Date Separator + db ':',0 ; Time Separator + db 2 ; Symbol before Value with Space ($ n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Norwegian_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for Norway (Code - 47) +NorwayData850: + dw 47 ; Country Code + dw 850 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'Kr',0,0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '.',0 ; Date Separator + db ':',0 ; Time Separator + db 2 ; Symbol before Value with Space ($ n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for Poland (Code - 48) +PolandData: + dw 48 ; Country Code + dw 852 ; Code Page + dw JAP_DATE ; Date Format (Binary) + db 'Z',136,0,0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '-',0 ; Date Separator + db ':',0 ; Time Separator + db 0 ; Symbol before Value without Space ($n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw US_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ',',0 ; Data List Separator + + +PolandData850: + dw 48 ; Country Code + dw 850 ; Code Page + dw JAP_DATE ; Date Format (Binary) + db 'Z',136,0,0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '-',0 ; Date Separator + db ':',0 ; Time Separator + db 0 ; Symbol before Value without Space ($n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ',',0 ; Data List Separator + + +; Country Data for Germany (Code - 49) +GermanyData: + dw 49 ; Country Code + dw 437 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'DM',0,0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '.',0 ; Date Separator + db ':',0 ; Time Separator + db 0 ; Symbol before Value without Space ($n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw German_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + + +; Country Data for Germany (Code - 49) +GermanyData850: + dw 49 ; Country Code + dw 850 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'DM',0,0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '.',0 ; Date Separator + db '.',0 ; Time Separator + db 0 ; Symbol before Value without Space ($n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + + +; Country Data for Brazil (Code - 55) +BrazilData: + dw 55 ; Country Code + dw 437 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'Cr$',0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '/',0 ; Date Separator + db ':',0 ; Time Separator + db 2 ; Symbol before Value with Space ($ n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Default_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + + +; Country Data for Brazil (Code - 55) +BrazilData850: + dw 55 ; Country Code + dw 850 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'Cr$',0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '/',0 ; Date Separator + db ':',0 ; Time Separator + db 2 ; Symbol before Value with Space ($ n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + + +; Country Data for Australia (Code - 61) +AustraliaData: + dw 61 ; Country Code + dw 437 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db '$',0,0,0,0 ; Currency Symbol + db ',',0 ; Thousands Separator + db '.',0 ; Decimal Separator + db '-',0 ; Date Separator + db ':',0 ; Time Separator + db 0 ; Symbol before Value without Space ($n.nn) + db 2 ; Significant Currency Digits + db CLOCK_12 ; Time Format + dw Australian_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ',',0 ; Data List Separator + + + +; Country Data for Australia (Code - 61) +AustraliaData850: + dw 61 ; Country Code + dw 850 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db '$',0,0,0,0 ; Currency Symbol + db ',',0 ; Thousands Separator + db '.',0 ; Decimal Separator + db '-',0 ; Date Separator + db ':',0 ; Time Separator + db 0 ; Symbol before Value without Space ($n.nn) + db 2 ; Significant Currency Digits + db CLOCK_12 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ',',0 ; Data List Separator + + + +; Country Data for Japan (Code - 81) +JapanData: + dw 81 ; Country Code + dw 437 + dw JAP_DATE ; Date Format (Binary) +;; db 05Ch,0,0,0,0 ; '' Currency Symbol (NEC 9801 Character Set) + db 09Dh,0,0,0,0 ; '' Currency Symbol (IBM CodePage 437) + db ',',0 ; Thousands Separator + db '.',0 ; Decimal Separator + db '-',0 ; Date Separator + db ':',0 ; Time Separator + db 0 ; Symbol after Value with Space (n.nn $) + db 0 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Default_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ',',0 ; Data List Separator + + +; Country Data for Japan (Code - 81) +JapanData932: + dw 81 ; Country Code + dw 932 + dw JAP_DATE ; Date Format (Binary) + db 05Ch,0,0,0,0 ; '' Currency Symbol (NEC 9801 Character Set) +;; db 09Dh,0,0,0,0 ; '' Currency Symbol (IBM CodePage 437) + db ',',0 ; Thousands Separator + db '.',0 ; Decimal Separator + db '-',0 ; Date Separator + db ':',0 ; Time Separator + db 0 ; Symbol after Value with Space (n.nn $) + db 0 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Default_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ',',0 ; Data List Separator + + +; Country Data for Korea (Code - 82) +KoreaData: + dw 82 ; Country Code + dw 437 + dw JAP_DATE ; Date Format (Binary) + db 05Ch,0,0,0,0 ; 'W' with two horizontal lines through +;; db 09Dh,0,0,0,0 ; '' Currency Symbol (IBM CodePage 437) + db ',',0 ; Thousands Separator + db '.',0 ; Decimal Separator + db '.',0 ; Date Separator + db ':',0 ; Time Separator + db 0 ; Symbol after Value with Space (n.nn $) + db 0 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Default_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ',',0 ; Data List Separator + + +; Country Data for Korea (Code - 82) +KoreaData934: + dw 82 ; Country Code + dw 934 + dw JAP_DATE ; Date Format (Binary) + db 05Ch,0,0,0,0 ; 'W' with two horizontal lines through +;; db 09Dh,0,0,0,0 ; '' Currency Symbol (IBM CodePage 437) + db ',',0 ; Thousands Separator + db '.',0 ; Decimal Separator + db '.',0 ; Date Separator + db ':',0 ; Time Separator + db 0 ; Symbol after Value with Space (n.nn $) + db 0 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Default_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ',',0 ; Data List Separator + + +; Country Data for Turkey (Code - 90) +TurkishData: + dw 90 ; Country Code + dw TURKCP ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'TL',0,0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '/',0 ; Date Separator + db ':',0 ; Time Separator + db 4 ; Symbol in middle Value without Space (n$nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Turkish_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ',',0 ; Data List Separator + + +; Country Data for Turkey (Code - 90) +TurkishData850: + dw 90 ; Country Code + dw 850 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'TL',0,0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '/',0 ; Date Separator + db ':',0 ; Time Separator + db 4 ; Symbol in middle Value without Space (n$nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Turkish_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ',',0 ; Data List Separator + + +; Country Data for Portugal (Code - 351) +PortugalData850: + dw 351 ; Country Code + dw 850 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'Esc.',0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '/',0 ; Date Separator + db ':',0 ; Time Separator + db 3 ; Symbol after Value with Space (n.nn $) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for Portugal (Code - 351) +PortugalData: + dw 351 ; Country Code + dw 860 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'Esc.',0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '-',0 ; Date Separator + db ':',0 ; Time Separator + db 3 ; Symbol after Value with Space (n.nn $) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Portugese_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for Finland (Code - 358) +FinlandData: + dw 358 ; Country Code + dw 437 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'mk',0,0,0 ; Currency Symbol + db ' ',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '.',0 ; Date Separator + db '.',0 ; Time Separator + db 3 ; Symbol after Value with Space (n.nn $) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Finish_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + + +; Country Data for Finland (Code - 358) +FinlandData850: + dw 358 ; Country Code + dw 850 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 'mk',0,0,0 ; Currency Symbol + db ' ',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '.',0 ; Date Separator + db '.',0 ; Time Separator + db 3 ; Symbol after Value with Space (n.nn $) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + + +; Country Data for MiddleEast (Code - 785) +MiddleEastData850: + dw 785 ; Country Code + dw 850 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 207,0,0,0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '/',0 ; Date Separator + db ':',0 ; Time Separator + db 3 ; Symbol after Value with Space (n.nn $) + db 3 ; Significant Currency Digits + db CLOCK_12 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for MiddleEast (Code - 785) +MiddleEastData: + dw 785 ; Country Code + dw 864 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 164,0,0,0,0 ; Currency Symbol + db '.',0 ; Thousands Separator + db ',',0 ; Decimal Separator + db '/',0 ; Date Separator + db ':',0 ; Time Separator + db 3 ; Symbol after Value with Space (n.nn $) + db 3 ; Significant Currency Digits + db CLOCK_12 ; Time Format + dw Arabic_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ';',0 ; Data List Separator + + +; Country Data for Israel (Code - 972) +IsraelData850: + dw 972 ; Country Code + dw 850 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 153,0,0,0,0 ; Currency Symbol + db ',',0 ; Thousands Separator + db '.',0 ; Decimal Separator + db ' ',0 ; Date Separator + db ':',0 ; Time Separator + db 2 ; Symbol before Value with Space ($ n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw xlat_850 ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ',',0 ; Data List Separator + +; Country Data for Israel (Code - 972) +IsraelData: + dw 972 ; Country Code + dw 862 ; Code Page + dw EURO_DATE ; Date Format (Binary) + db 153,0,0,0,0 ; Currency Symbol + db ',',0 ; Thousands Separator + db '.',0 ; Decimal Separator + db ' ',0 ; Date Separator + db ':',0 ; Time Separator + db 2 ; Symbol before Value with Space ($ n.nn) + db 2 ; Significant Currency Digits + db CLOCK_24 ; Time Format + dw Jewish_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ',',0 ; Data List Separator + + dw 0 ; End of Country Data Marker + +if COMPATIBLE +Ucasetbl: +else +Ucasetbl: +NetherlandsUcase: +SwedenUcase: +SwitzerlandUcase: +endif + dw 128 ; Table Size +standard_table db 080h, 09ah +if COMPATIBLE + db 'E' +else + db 090h +endif + db 'A', 08eh, 'A', 08fh, 080h + db 'E', 'E', 'E', 'I', 'I', 'I', 08eh, 08fh + db 090h, 092h, 092h, 'O', 099h, 'O', 'U', 'U' + db 'Y', 099h, 09ah, 09bh, 09ch, 09dh, 09eh, 09fh + db 'A', 'I', 'O', 'U', 0a5h + db 0a5h, 0a6h, 0a7h + db 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 0e1h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh +info2_len equ word ptr (offset $ - offset Ucasetbl) + +FileCharstbl: + dw 22 ; Table Size + db 001h, 000h, 0ffh, 000h, 000h, 020h, 002h, 00eh + db 02eh, 022h, 02fh, 05ch, 05bh, 05dh, 03ah, 07ch + db 03ch, 03eh, 02bh, 03dh, 03bh, 02ch +info5_len equ word ptr (offset $ - offset FileCharstbl) + +Collatingtbl: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + db 043h, 055h, 045h, 041h, 041h, 041h, 041h, 043h + db 045h, 045h, 045h, 049h, 049h, 049h, 041h, 041h + db 045h, 041h, 041h, 04fh, 04fh, 04fh, 055h, 055h + db 059h, 04fh, 055h, 024h, 024h, 024h, 024h, 024h + db 041h, 049h, 04fh, 055h, 04eh, 04eh, 0a6h, 0a7h + db 03fh, 0a9h, 0aah, 0abh, 0ach, 021h, 022h, 022h + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 053h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh +info6_len equ word ptr (offset $ - offset Collatingtbl) + +DBCS_tbl: + dw 0 ; Table Size + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h +info7_len equ word ptr (offset $ - offset DBCS_tbl) + + +Collating850: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + db 043h, 055h, 045h, 041h, 041h, 041h, 041h, 043h + db 045h, 045h, 045h, 049h, 049h, 049h, 041h, 041h + db 045h, 041h, 041h, 04fh, 04fh, 04fh, 055h, 055h + db 059h, 04fh, 055h, 04fh, 024h, 04fh, 09eh, 024h + db 041h, 049h, 04fh, 055h, 04eh, 04eh, 0a6h, 0a7h + db 03fh, 0a9h, 0aah, 0abh, 0ach, 021h, 022h, 022h + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 041h, 041h, 041h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 024h, 024h, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 041h, 041h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 024h + db 044h, 044h, 045h, 045h, 045h, 049h, 049h, 049h + db 049h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 049h, 0dfh + db 04fh, 053h, 04fh, 04fh, 04fh, 04fh, 0e6h, 0e8h + db 0e8h, 055h, 055h, 055h, 059h, 059h, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + + +LatiCollating850: + dw 256 ; Table Size + db 000h, 096h, 097h, 098h, 099h, 09ah, 09bh, 09ch + db 09dh, 09eh, 09fh, 0a0h, 0a1h, 0a2h, 0a3h, 0a4h + db 0a5h, 0a6h, 0a7h, 0a8h, 0a9h, 0aah, 0abh, 0ach + db 0adh, 0aeh, 0afh, 0b0h, 0b1h, 0b2h, 0b3h, 0b4h + db 000h, 03ch, 03dh, 03eh, 03fh, 040h, 041h, 000h + db 042h, 043h, 044h, 045h, 046h, 000h, 047h, 048h + db 022h, 023h, 024h, 025h, 026h, 027h, 028h, 029h + db 02ah, 02bh, 049h, 04ah, 04bh, 04ch, 04dh, 04eh + db 04fh, 001h, 002h, 003h, 006h, 008h, 009h, 00ah + db 00bh, 00ch, 00dh, 00eh, 00fh, 011h, 012h, 014h + db 015h, 016h, 017h, 018h, 01ah, 01ch, 01dh, 01eh + db 01fh, 020h, 021h, 050h, 051h, 052h, 053h, 054h + db 055h, 001h, 002h, 003h, 006h, 008h, 009h, 00ah + db 00bh, 00ch, 00dh, 00eh, 00fh, 011h, 012h, 014h + db 015h, 016h, 017h, 018h, 01ah, 01ch, 01dh, 01eh + db 01fh, 020h, 021h, 056h, 057h, 058h, 059h, 05ah + db 004h, 01ch, 008h, 001h, 001h, 001h, 001h, 004h + db 008h, 008h, 008h, 00ch, 00ch, 00ch, 001h, 001h + db 008h, 001h, 001h, 014h, 014h, 014h, 01ch, 01ch + db 020h, 014h, 01ch, 014h, 05ch, 014h, 05eh, 05fh + db 001h, 00ch, 014h, 01ch, 013h, 013h, 001h, 014h + db 060h, 061h, 062h, 063h, 064h, 065h, 066h, 067h + db 068h, 069h, 06ah, 06bh, 06ch, 001h, 001h, 001h + db 0b8h, 06dh, 06eh, 001h, 001h, 05bh, 05dh, 071h + db 072h, 073h, 074h, 075h, 076h, 077h, 0bbh, 0bch + db 078h, 079h, 07ah, 07bh, 07ch, 07dh, 07eh, 0bdh + db 007h, 007h, 008h, 008h, 008h, 00ch, 00ch, 00ch + db 00ch, 07fh, 080h, 081h, 082h, 0c7h, 00ch, 083h + db 014h, 019h, 014h, 014h, 014h, 014h, 084h, 01bh + db 01bh, 01ch, 01ch, 01ch, 020h, 020h, 0d5h, 0d6h + db 000h, 085h, 0d8h, 0d9h, 0dah, 0dbh, 086h, 0dch + db 0ddh, 0deh, 000h, 0dfh, 0e0h, 087h, 088h, 0e1h + +SwedCollating850: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + db 043h, 059h, 045h, 041h, 05ch, 041h, 05bh, 043h + db 045h, 045h, 045h, 049h, 049h, 049h, 05ch, 05bh + db 045h, 05ch, 05ch, 04fh, 05dh, 04fh, 055h, 055h + db 059h, 05dh, 059h, 05dh, 024h, 05dh, 09eh, 024h + db 041h, 049h, 04fh, 055h, 04eh, 04eh, 0a6h, 0a7h + db 03fh, 0a9h, 0aah, 0abh, 0ach, 021h, 022h, 022h + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 041h, 041h, 041h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 024h, 024h, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 041h, 041h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 024h + db 044h, 044h, 045h, 045h, 045h, 049h, 049h, 049h + db 049h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 049h, 0dfh + db 04fh, 053h, 04fh, 04fh, 05dh, 05dh, 0e6h, 0e8h + db 0e8h, 055h, 055h, 055h, 059h, 059h, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + +DenmCollating850: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 028h, 02fh, 029h, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 028h, 02fh, 029h, 07eh, 07fh + db 043h, 059h, 045h, 041h, 05bh, 041h, 05dh, 043h + db 045h, 045h, 045h, 049h, 049h, 049h, 05bh, 05dh + db 045h, 05bh, 05bh, 04fh, 05ch, 04fh, 055h, 055h + db 059h, 05ch, 059h, 05ch, 024h, 05ch, 09eh, 024h + db 041h, 049h, 04fh, 055h, 04eh, 04eh, 041h, 04fh + db 03fh, 0a9h, 0aah, 0abh, 0ach, 021h, 022h, 022h + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 041h, 041h, 041h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 024h, 024h, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 041h, 041h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 024h + db 044h, 044h, 045h, 045h, 045h, 049h, 049h, 049h + db 049h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 049h, 0dfh + db 04fh, 053h, 04fh, 04fh, 04fh, 04fh, 0e6h, 050h + db 050h, 055h, 055h, 055h, 059h, 059h, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + +SwisCollating850: + dw 256 ; Table Size + db 0e0h, 0e1h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + db 000h, 0a5h, 0a8h, 085h, 0b9h, 086h, 087h, 0a9h + db 0aah, 0abh, 088h, 09eh, 0ach, 0aeh, 0afh, 0b0h + db 075h, 076h, 078h, 07ah, 07ch, 07dh, 07eh, 07fh + db 080h, 081h, 0b1h, 0b2h, 0a0h, 0a1h, 0a2h, 0b3h + db 089h, 002h, 012h, 014h, 018h, 01ch, 026h, 028h + db 02ah, 02ch, 037h, 039h, 03bh, 03dh, 03fh, 043h + db 051h, 053h, 055h, 057h, 05ah, 05eh, 068h, 06ah + db 06ch, 06eh, 073h, 08ah, 08bh, 08ch, 0bfh, 0adh + db 0beh, 003h, 013h, 015h, 019h, 01dh, 027h, 029h + db 02bh, 038h, 02dh, 03ah, 03ch, 03eh, 040h, 044h + db 052h, 054h, 056h, 058h, 05bh, 05fh, 069h, 06bh + db 06dh, 06fh, 074h, 08eh, 08fh, 090h, 0c1h, 09dh + db 016h, 067h, 01fh, 009h, 00bh, 007h, 00fh, 017h + db 023h, 025h, 021h, 035h, 033h, 031h, 00ah, 00eh + db 01eh, 011h, 010h, 04ah, 04ch, 048h, 065h, 063h + db 072h, 04bh, 066h, 050h, 0b8h, 04fh, 0a4h, 0bch + db 005h, 02fh, 046h, 061h, 042h, 041h, 095h, 094h + db 0b4h, 09ah, 09ch, 083h, 082h, 0a6h, 0b5h, 0b6h + db 0cfh, 0d0h, 0d1h, 0ceh, 0cch, 004h, 008h, 006h + db 099h, 0d2h, 0d3h, 0d4h, 0d5h, 0bah, 0bbh, 0c6h + db 0c5h, 0cah, 0c9h, 0cbh, 0cdh, 0c8h, 00dh, 00ch + db 0d6h, 0d7h, 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0b7h + db 01bh, 01ah, 022h, 024h, 020h, 036h, 02eh, 032h + db 034h, 0c7h, 0c4h, 0dfh, 0ddh, 09bh, 030h, 0deh + db 045h, 059h, 049h, 047h, 04eh, 04dh, 092h, 05ch + db 05dh, 060h, 064h, 062h, 071h, 070h, 091h, 0bdh + db 0a7h, 09fh, 08dh, 084h, 097h, 096h, 0a3h, 0c2h + db 093h, 0c0h, 0c3h, 077h, 07bh, 079h, 098h, 001h + +CzecCollating850: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00Ah, 00Bh, 00Ch, 00Dh, 00Eh, 00Fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01Ah, 01Bh, 01Ch, 01Dh, 01Eh, 01Fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02Ah, 02Bh, 02Ch, 02Dh, 02Eh, 02Fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03Ah, 03Bh, 03Ch, 03Dh, 03Eh, 03Fh + db 040h, 041h, 043h, 044h, 045h, 047h, 049h, 04Ah + db 04Bh, 04Ch, 04Eh, 04Fh, 050h, 051h, 052h, 053h + db 055h, 056h, 057h, 058h, 059h, 05Ah, 05Ch, 05Dh + db 05Eh, 05Fh, 061h, 028h, 02Fh, 029h, 05Eh, 05Fh + db 060h, 041h, 043h, 044h, 045h, 047h, 049h, 04Ah + db 04Bh, 04Ch, 04Eh, 04Fh, 050h, 051h, 052h, 053h + db 055h, 056h, 057h, 058h, 059h, 05Ah, 05Ch, 05Dh + db 05Eh, 05Fh, 061h, 028h, 02Fh, 029h, 07Eh, 07Fh + db 044h, 05Bh, 048h, 042h, 042h, 042h, 042h, 044h + db 048h, 048h, 048h, 04Dh, 04Dh, 04Dh, 042h, 042h + db 048h, 063h, 063h, 054h, 064h, 054h, 05Bh, 05Bh + db 060h, 064h, 05Bh, 054h, 024h, 054h, 09Eh, 024h + db 042h, 04Dh, 054h, 05Bh, 052h, 052h, 041h, 054h + db 03Fh, 0A9h, 0AAh, 0ABh, 0ACh, 021h, 022h, 022h + db 0B0h, 0B1h, 0B2h, 0B3h, 0B4h, 042h, 042h, 042h + db 0B8h, 0B9h, 0BAh, 0BBh, 0BCh, 024h, 024h, 0BFh + db 0C0h, 0C1h, 0C2h, 0C3h, 0C4h, 0C5h, 042h, 042h + db 0C8h, 0C9h, 0CAh, 0CBh, 0CCh, 0CDh, 0CEh, 024h + db 046h, 046h, 048h, 048h, 048h, 04Ch, 04Dh, 04Dh + db 04Dh, 0D9h, 0DAh, 0DBh, 0DCh, 0DDh, 04Dh, 0DFh + db 054h, 043h, 054h, 054h, 054h, 054h, 0E6h, 062h + db 062h, 05Bh, 05Bh, 05Bh, 060h, 060h, 0EEh, 0EFh + db 0F0h, 0F1h, 0F2h, 0F3h, 0F4h, 0F5h, 09Fh, 001h + db 04Fh, 00Eh, 080h, 0FCh, 014h, 074h, 005h, 02Eh + +PolCollating850: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00Ah, 00Bh, 00Ch, 00Dh, 00Eh, 00Fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01Ah, 01Bh, 01Ch, 01Dh, 01Eh, 01Fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02Ah, 02Bh, 02Ch, 02Dh, 02Eh, 02Fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03Ah, 03Bh, 03Ch, 03Dh, 03Eh, 03Fh + db 040h, 041h, 043h, 044h, 045h, 047h, 049h, 04Ah + db 04Bh, 04Ch, 04Eh, 04Fh, 050h, 051h, 052h, 053h + db 055h, 056h, 057h, 058h, 059h, 05Ah, 05Ch, 05Dh + db 05Eh, 05Fh, 061h, 028h, 02Fh, 029h, 05Eh, 05Fh + db 060h, 041h, 043h, 044h, 045h, 047h, 049h, 04Ah + db 04Bh, 04Ch, 04Eh, 04Fh, 050h, 051h, 052h, 053h + db 055h, 056h, 057h, 058h, 059h, 05Ah, 05Ch, 05Dh + db 05Eh, 05Fh, 061h, 028h, 02Fh, 029h, 07Eh, 07Fh + db 044h, 05Bh, 048h, 042h, 042h, 042h, 042h, 044h + db 048h, 048h, 048h, 04Dh, 04Dh, 04Dh, 042h, 042h + db 048h, 063h, 063h, 054h, 064h, 054h, 05Bh, 05Bh + db 060h, 064h, 05Bh, 054h, 024h, 054h, 09Eh, 024h + db 042h, 04Dh, 054h, 05Bh, 052h, 052h, 041h, 054h + db 03Fh, 0A9h, 0AAh, 0ABh, 0ACh, 021h, 022h, 022h + db 0B0h, 0B1h, 0B2h, 0B3h, 0B4h, 042h, 042h, 042h + db 0B8h, 0B9h, 0BAh, 0BBh, 0BCh, 024h, 024h, 0BFh + db 0C0h, 0C1h, 0C2h, 0C3h, 0C4h, 0C5h, 042h, 042h + db 0C8h, 0C9h, 0CAh, 0CBh, 0CCh, 0CDh, 0CEh, 024h + db 046h, 046h, 048h, 048h, 048h, 04Ch, 04Dh, 04Dh + db 04Dh, 0D9h, 0DAh, 0DBh, 0DCh, 0DDh, 04Dh, 0DFh + db 054h, 043h, 054h, 054h, 054h, 054h, 0E6h, 062h + db 062h, 05Bh, 05Bh, 05Bh, 060h, 060h, 0EEh, 0EFh + db 0F0h, 0F1h, 0F2h, 0F3h, 0F4h, 0F5h, 09Fh, 001h + db 04Fh, 00Eh, 080h, 0FCh, 014h, 074h, 005h, 02Eh + +NorwCollating850: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + db 043h, 055h, 045h, 041h, 05bh, 041h, 05dh, 043h + db 045h, 045h, 045h, 049h, 049h, 049h, 05bh, 05dh + db 045h, 05bh, 05bh, 04fh, 05ch, 04fh, 055h, 055h + db 059h, 05ch, 059h, 05ch, 024h, 05ch, 09eh, 024h + db 041h, 049h, 04fh, 055h, 04eh, 04eh, 041h, 04fh + db 03fh, 0a9h, 0aah, 0abh, 0ach, 021h, 022h, 022h + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 041h, 041h, 041h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 024h, 024h, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 041h, 041h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 024h + db 044h, 044h, 045h, 045h, 045h, 049h, 049h, 049h + db 049h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 049h, 0dfh + db 04fh, 053h, 04fh, 04fh, 04fh, 04fh, 0e6h, 050h + db 050h, 055h, 055h, 055h, 059h, 059h, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + +BelgCollating850: + dw 256 ; Table Size + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 0ffh, 021h, 022h, 023h, 024h, 025h, 026h, 0ffh + db 028h, 029h, 02ah, 02bh, 02ch, 0ffh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + db 043h, 055h, 045h, 041h, 041h, 041h, 041h, 043h + db 045h, 045h, 045h, 049h, 049h, 049h, 041h, 041h + db 045h, 041h, 041h, 04fh, 04fh, 04fh, 055h, 055h + db 059h, 04fh, 055h, 04fh, 09ch, 04fh, 09eh, 09fh + db 041h, 049h, 04fh, 055h, 04eh, 0a4h, 0a6h, 0a7h + db 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 041h, 041h, 041h + db 0b8h, 0ffh, 0ffh, 0ffh, 0ffh, 0bdh, 0beh, 0ffh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 041h, 041h + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0cfh + db 044h, 044h, 045h, 045h, 045h, 049h, 049h, 049h + db 049h, 0ffh, 0ffh, 0ffh, 0ffh, 0ddh, 049h, 0ffh + db 04fh, 053h, 04fh, 04fh, 04fh, 04fh, 0e6h, 054h + db 054h, 055h, 055h, 055h, 059h, 059h, 0eeh, 0efh + db 0ffh, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0ffh, 0ffh + +NethCollating850: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + db 043h, 055h, 045h, 041h, 041h, 041h, 08fh, 043h + db 045h, 045h, 045h, 049h, 049h, 049h, 041h, 08fh + db 045h, 092h, 092h, 04fh, 04fh, 04fh, 055h, 055h + db 098h, 04fh, 055h, 04fh, 09ch, 04fh, 09eh, 09fh + db 041h, 049h, 04fh, 055h, 0a5h, 0a5h, 0a6h, 0a7h + db 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 041h, 041h, 041h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 041h, 041h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d1h, 0d1h, 045h, 045h, 045h, 049h, 049h, 049h + db 049h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 049h, 0dfh + db 04fh, 0e1h, 04fh, 04fh, 04fh, 04fh, 0e6h, 0e8h + db 0e8h, 055h, 055h, 055h, 059h, 059h, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + + +FinlCollating850: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + db 043h, 059h, 045h, 041h, 05ch, 041h, 05bh, 043h + db 045h, 045h, 045h, 049h, 049h, 049h, 05ch, 05bh + db 045h, 05ch, 05ch, 04fh, 05dh, 04fh, 055h, 055h + db 059h, 05dh, 059h, 05dh, 024h, 05dh, 09eh, 024h + db 041h, 049h, 04fh, 055h, 04eh, 04eh, 0a6h, 0a7h + db 03fh, 0a9h, 0aah, 0abh, 0ach, 021h, 022h, 022h + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 041h, 041h, 041h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 024h, 024h, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 041h, 041h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 024h + db 044h, 044h, 045h, 045h, 045h, 049h, 049h, 049h + db 049h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 049h, 0dfh + db 04fh, 053h, 04fh, 04fh, 04fh, 04fh, 0e6h, 0e8h + db 0e8h, 055h, 055h, 055h, 059h, 059h, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + + +Collating932: + dw 256 ; Table size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + db 080h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 081h, 082h, 083h, 084h, 085h, 0bdh, 086h, 087h + db 088h, 089h, 08ah, 08bh, 08ch, 08dh, 08eh, 08fh + db 090h, 091h, 092h, 093h, 094h, 095h, 096h, 097h + db 098h, 099h, 09ah, 09bh, 09ch, 09dh, 09eh, 09fh + db 0a0h, 0a1h, 0a2h, 0a3h, 0a4h, 0a5h, 0a6h, 0a7h + db 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0beh, 0bfh, 0c0h + db 0e0h, 0e1h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + + +Collating934: + dw 256 ; Table size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + db 080h, 0beh, 0bfh, 0c0h, 0c1h, 0c2h, 0c3h, 0c4h + db 0c5h, 0c6h, 0c7h, 0c8h, 0c9h, 0cah, 0cbh, 0cch + db 0cdh, 0ceh, 0cfh, 0d0h, 0d1h, 0d2h, 0d3h, 0d4h + db 0d5h, 0d6h, 0d7h, 0d8h, 0d9h, 0dah, 0dbh, 0dch + db 0ddh, 0deh, 0dfh, 0e0h, 0e1h, 0e2h, 0e3h, 0e4h + db 0e5h, 0e6h, 0e7h, 0e8h, 0e9h, 0eah, 0ebh, 0ech + db 0edh, 0eeh, 0efh, 0f0h, 0f1h, 0f2h, 0f3h, 0f4h + db 0f5h, 0f6h, 0f7h, 0f8h, 0f9h, 0fah, 0fbh, 0fch + db 081h, 082h, 083h, 084h, 085h, 086h, 087h, 088h + db 089h, 08ah, 08bh, 08ch, 08dh, 08eh, 08fh, 090h + db 091h, 092h, 093h, 094h, 095h, 096h, 097h, 098h + db 099h, 09ah, 09bh, 09ch, 09dh, 09eh, 09fh, 0a0h + db 0a1h, 0a2h, 0a3h, 0a4h, 0a5h, 0a6h, 0a7h, 0a8h + db 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh, 0b0h + db 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h, 0b8h + db 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0fdh, 0feh, 0ffh + + +CanadaUcase: + dw 128 ; Table Size + +Canadian_table db 'C', 'U', 'E', 'A', 'A', 'A', 086h, 'C' + db 'E', 'E', 'E', 'I', 'I', 08dh, 'A', 08fh + db 'E', 'E', 'E', 'O', 'E', 'I', 'U', 'U' + db 098h, 'O', 'U', 09bh, 09ch, 'U', 'U', 09fh + db 0a0h, 0a1h, 'O', 'U', 0a4h, 0a5h, 0a6h, 0a7h + db 'I' + db 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 0e1h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + +CanadaCollating: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + db 043h, 055h, 045h, 041h, 041h, 041h, 086h, 043h + db 045h, 045h, 045h, 049h, 049h, 08dh, 041h, 08fh + db 045h, 045h, 045h, 04fh, 045h, 049h, 055h, 055h + db 098h, 04fh, 055h, 09bh, 09ch, 055h, 055h, 09fh + db 0a0h, 0a1h, 04fh, 055h, 0a4h, 0a5h, 0a6h, 0a7h + db 049h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 0e1h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + + +; +; UpperCase Table for Russian CodePage 866 +; +RussianUcase: + dw 128 ; Table Size +Russian_table: + db 080h, 081h, 082h, 083h, 084h, 085h, 086h, 087h + db 088h, 089h, 08ah, 08bh, 08ch, 08dh, 08eh, 08fh + db 090h, 091h, 092h, 093h, 094h, 095h, 096h, 097h + db 098h, 099h, 09ah, 09Bh, 09Ch, 09Dh, 09Eh, 09Fh + db 080h, 081h, 082h, 083h, 084h, 085h, 086h, 087h + db 088h, 089h, 08ah, 08bh, 08ch, 08dh, 08eh, 08fh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 090h, 091h, 092h, 093h, 094h, 095h, 096h, 097h + db 098h, 099h, 09ah, 09Bh, 09Ch, 09Dh, 09Eh, 09Fh + db 0f0h, 0f0h, 0f2h, 0f2h, 0f4h, 0f4h, 0f6h, 0f6h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + +RussianCollating: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + + db 080h, 081h, 082h, 083h, 084h, 085h ;; + db 088h, 089h, 08ah, 08ch, 08dh, 08eh, 08fh ;; + db 090h, 091h, 092h, 093h, 094h, 095h, 096h ;; + db 098h, 099h, 09ah, 09Bh, 09Ch, 09Dh, 09Eh, 09Fh ;; + db 0A0h, 0A1h, 0A2h, 0A3h ;; + db 080h, 081h, 082h, 083h, 084h, 085h ;; + db 088h, 089h, 08ah, 08ch, 08dh, 08eh, 08fh ;; + db 090h, 091h, 092h ;; + + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + + db 093h, 094h, 095h, 096h ;; + db 098h, 099h, 09ah, 09Bh, 09Ch, 09Dh, 09Eh, 09Fh ;; + db 0A0h, 0A1h, 0A2h, 0A3h ;; + + db 086h, 086h, 087h, 087h, 08Bh, 08Bh, 097h, 097h + db 0f8h, 0f9h, 0fah, 0fbh, 023h, 024h, 0feh, 0ffh + + +if COMPATIBLE +NetherlandsUcase: + dw 128 ; Table Size + + db 080h, 'U', 'E', 'A', 'A', 'A', 08fh, 080h + db 'E', 'E', 'E', 'I', 'I', 'I', 'A', 08fh + db 'E', 092h, 092h, 'O', 'O', 'O', 'U', 'U' + db 098h, 'O', 'U', 09bh, 09ch, 09dh, 09eh, 09fh + db 'A', 'I', 'O', 'U', 0a5h, 0a5h, 0a6h, 0a7h + db 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 0e1h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh +endif + +NetherlandsCollating: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + db 080h, 09ah, 090h, 041h, 08eh, 041h, 08fh, 080h + db 045h, 045h, 045h, 049h, 049h, 049h, 08eh, 08fh + db 090h, 092h, 092h, 04fh, 04fh, 04fh, 055h, 055h + db 098h, 04fh, 055h, 09bh, 09ch, 09dh, 09eh, 09fh + db 041h, 049h, 04fh, 055h, 0a5h, 0a5h, 0a6h, 0a7h + db 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 0e1h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + + + +BelgiumCollating: + dw 256 ; Table Size + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 0ffh, 021h, 022h, 023h, 024h, 025h, 026h, 0ffh + db 028h, 029h, 02ah, 02bh, 02ch, 0ffh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + db 043h, 055h, 045h, 041h, 041h, 041h, 041h, 043h + db 045h, 045h, 045h, 049h, 049h, 049h, 041h, 041h + db 045h, 041h, 041h, 04fh, 04fh, 04fh, 055h, 055h + db 059h, 04fh, 055h, 09bh, 09ch, 09dh, 09eh, 09fh + db 041h, 049h, 04fh, 055h, 04eh, 04eh, 0a6h, 0a7h + db 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh + db 0e0h, 053h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0ffh, 0ffh + + +SpainCollating: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + db 043h, 055h, 045h, 041h, 041h, 041h, 041h, 043h + db 045h, 045h, 045h, 049h, 049h, 049h, 041h, 041h + db 045h, 041h, 041h, 04fh, 04fh, 04fh, 055h, 055h + db 059h, 04fh, 055h, 024h, 024h, 024h, 024h, 024h + db 041h, 049h, 04fh, 055h, 04eh, 04eh, 0a6h, 0a7h + db 03fh, 0a9h, 0aah, 0abh, 0ach, 021h, 022h, 022h + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 053h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + +HungaryUcase: + dw 128 + db 080h, 09ah, 090h, 0b6h, 08eh, 0deh, 08fh, 080h + db 09dh, 0d3h, 08ah, 08ah, 0d7h, 08dh, 08eh, 08fh + db 090h, 091h, 0d6h, 0e2h, 099h, 095h, 095h, 097h + db 097h, 099h, 09ah, 09bh, 09bh, 09dh, 09eh, 0ach + db 0b5h, 0d6h, 0e0h, 0e9h, 0a4h, 0a4h, 0a6h, 0a6h + db 0a8h, 0a8h, 0aah, 08dh, 0ach, 0b8h, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0bdh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c6h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d1h, 0d1h, 0d2h, 0d3h, 0d2h, 0d5h, 0d6h, 0d7h + db 0b7h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 053h, 0e2h, 0e3h, 0e3h, 0d5h, 0e6h, 0e6h + db 0e8h, 0e9h, 0e8h, 0ebh, 0edh, 0edh, 0ddh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0ebh, 0fch, 0fch, 0feh, 0ffh + +HungaryCollating: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + db 043h, 055h, 045h, 041h, 041h, 055h, 043h, 043h + db 04ch, 045h, 04fh, 04fh, 049h, 05ah, 041h, 043h + db 045h, 04ch, 049h, 04fh, 04fh, 04ch, 049h, 053h + db 053h, 04fh, 055h, 054h, 054h, 04ch, 09eh, 043h + db 041h, 049h, 04fh, 055h, 041h, 041h, 05ah, 05ah + db 045h, 045h, 0aah, 05ah, 043h, 053h, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 041h, 041h, 045h + db 053h, 0b9h, 0bah, 0bbh, 0bch, 05ah, 05ah, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 041h, 041h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 044h, 044h, 044h, 045h, 044h, 04eh, 049h, 049h + db 045h, 0d9h, 0dah, 0dbh, 0dch, 054h, 055h, 0dfh + db 04fh, 053h, 04fh, 04eh, 04eh, 04eh, 053h, 053h + db 052h, 055h, 052h, 055h, 059h, 059h, 054h, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 055h, 052h, 052h, 0feh, 0ffh + + +if COMPATIBLE +SwitzerlandUcase: + dw 128 ; Table Size + + db 080h, 09ah, 090h, 'A', 08eh, 'A', 08fh, 080h + db 'E', 'E', 'E', 'I', 'I', 'I', 08eh, 08fh + db 090h, 092h, 092h, 'O', 099h, 'O', 'U', 'U' + db 'Y', 099h, 09ah, 09bh, 09ch, 09dh, 09eh, 09fh + db 'A', 'I', 'O', 'U', 0a5h, 0a5h, 'A', 'O' + db 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 0e1h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh +endif +SwitzerlandCollating: + dw 256 ; Table Size + db 001h, 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh + db 0cfh, 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h + db 0d7h, 0d8h, 0d9h, 0dah, 08ch, 08dh, 0dbh, 0dch + db 0ddh, 0deh, 0dfh, 0e0h, 0e1h, 0e2h, 0e3h, 0e4h + db 001h, 03ch, 03dh, 03dh, 03fh, 040h, 041h, 042h + db 043h, 044h, 045h, 046h, 047h, 048h, 049h, 04ah + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 04bh, 04ch, 04dh, 04eh, 04fh, 050h + db 051h, 002h, 003h, 004h, 005h, 007h, 008h, 009h + db 00ah, 00bh, 00ch, 00dh, 00eh, 00fh, 010h, 012h + db 013h, 014h, 015h, 016h, 018h, 01ah, 01bh, 01ch + db 01dh, 01eh, 01fh, 052h, 053h, 054h, 034h, 055h + db 033h, 002h, 003h, 004h, 005h, 007h, 008h, 009h + db 00ah, 00bh, 00ch, 00dh, 00eh, 00fh, 010h, 012h + db 013h, 014h, 015h, 016h, 018h, 01ah, 01bh, 01ch + db 01dh, 01eh, 01fh, 056h, 057h, 058h, 036h, 059h + db 004h, 01ah, 007h, 002h, 002h, 002h, 002h, 004h + db 007h, 007h, 007h, 00bh, 00bh, 00bh, 002h, 002h + db 007h, 002h, 002h, 012h, 012h, 012h, 01ah, 01ah + db 01eh, 012h, 01ah, 06fh, 05ah, 070h, 096h, 05ch + db 002h, 00bh, 012h, 01ah, 011h, 011h, 002h, 012h + db 05dh, 097h, 05fh, 060h, 061h, 062h, 063h, 064h + db 065h, 066h, 067h, 068h, 069h, 098h, 099h, 09ah + db 09bh, 06bh, 06ch, 06dh, 06eh, 09ch, 09dh, 071h + db 072h, 073h, 074h, 075h, 076h, 077h, 09eh, 09fh + db 078h, 079h, 07ah, 07bh, 07ch, 07dh, 07eh, 0a0h + db 0a1h, 0a2h, 0a3h, 0a4h, 0a5h, 0a6h, 0a7h, 0a8h + db 0a9h, 080h, 081h, 082h, 083h, 0aah, 0abh, 085h + db 0ach, 017h, 0adh, 0aeh, 0afh, 0b0h, 086h, 0b1h + db 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h, 0b8h, 0b9h + db 0bah, 089h, 0bbh, 0bch, 0bdh, 0beh, 08eh, 0bfh + db 08fh, 0c0h, 090h, 0c1h, 0c2h, 093h, 094h, 001h + +CzecCollating: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00Ah, 00Bh, 00Ch, 00Dh, 00Eh, 00Fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01Ah, 01Bh, 01Ch, 01Dh, 01Eh, 01Fh + db 06Eh, 06Fh, 070h, 071h, 072h, 073h, 074h, 075h + db 076h, 077h, 078h, 079h, 07Ah, 07Bh, 07Ch, 07Dh + db 064h, 065h, 066h, 067h, 068h, 069h, 06Ah, 06Bh + db 06Ch, 06Dh, 07Eh, 07Fh, 080h, 081h, 082h, 083h + db 084h, 021h, 027h, 028h, 02Ch, 02Fh, 034h, 035h + db 036h, 037h, 03Ah, 03Bh, 03Ch, 040h, 041h, 044h + db 049h, 04Ah, 04Bh, 04Eh, 053h, 056h, 05Bh, 05Ch + db 05Dh, 05Eh, 060h, 085h, 086h, 087h, 088h, 089h + db 08Ah, 021h, 027h, 028h, 02Ch, 02Fh, 034h, 035h + db 036h, 037h, 03Ah, 03Bh, 03Ch, 040h, 041h, 044h + db 049h, 04Ah, 04Bh, 04Eh, 053h, 056h, 05Bh, 05Ch + db 05Dh, 05Eh, 060h, 08Bh, 08Ch, 08Dh, 08Eh, 020h + db 02Bh, 059h, 030h, 026h, 023h, 058h, 029h, 02Bh + db 03Fh, 033h, 048h, 048h, 039h, 062h, 023h, 029h + db 030h, 03Dh, 03Dh, 046h, 047h, 03Eh, 03Eh, 052h + db 052h, 047h, 059h, 054h, 054h, 03Fh, 08Fh, 02Ah + db 022h, 038h, 045h, 057h, 024h, 024h, 061h, 061h + db 032h, 032h, 090h, 062h, 02Ah, 051h, 091h, 092h + db 097h, 098h, 099h, 09Ah, 09Bh, 022h, 026h, 031h + db 051h, 09Ch, 09Dh, 09Eh, 09Fh, 063h, 063h, 0A0h + db 0A1h, 0A2h, 0A3h, 0A4h, 0A5h, 0A6h, 025h, 025h + db 0A7h, 0A8h, 0A9h, 0AAh, 0ABh, 0ACh, 0ADh, 093h + db 02Dh, 02Dh, 02Eh, 033h, 02Eh, 042h, 038h, 039h + db 031h, 0AEh, 0AFh, 0B0h, 0B1h, 055h, 058h, 0B2h + db 045h, 04Fh, 046h, 043h, 043h, 042h, 050h, 050h + db 04Ch, 057h, 04Ch, 05Ah, 05Fh, 05Fh, 055h, 0B4h + db 094h, 0B5h, 0B6h, 0B7h, 0B8h, 095h, 09Fh, 001h + db 04Fh, 00Eh, 080h, 0FCh, 014h, 074h, 005h, 0FFh + +PolCollating: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00Ah, 00Bh, 00Ch, 00Dh, 00Eh, 00Fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01Ah, 01Bh, 01Ch, 01Dh, 01Eh, 01Fh + db 06Eh, 06Fh, 070h, 071h, 072h, 073h, 074h, 075h + db 076h, 077h, 078h, 079h, 07Ah, 07Bh, 07Ch, 07Dh + db 064h, 065h, 066h, 067h, 068h, 069h, 06Ah, 06Bh + db 06Ch, 06Dh, 07Eh, 07Fh, 080h, 081h, 082h, 083h + db 084h, 021h, 027h, 028h, 02Ch, 02Fh, 034h, 035h + db 036h, 037h, 03Ah, 03Bh, 03Ch, 040h, 041h, 044h + db 049h, 04Ah, 04Bh, 04Eh, 053h, 056h, 05Bh, 05Ch + db 05Dh, 05Eh, 060h, 085h, 086h, 087h, 088h, 089h + db 08Ah, 021h, 027h, 028h, 02Ch, 02Fh, 034h, 035h + db 036h, 037h, 03Ah, 03Bh, 03Ch, 040h, 041h, 044h + db 049h, 04Ah, 04Bh, 04Eh, 053h, 056h, 05Bh, 05Ch + db 05Dh, 05Eh, 060h, 08Bh, 08Ch, 08Dh, 08Eh, 020h + db 02Bh, 059h, 030h, 026h, 023h, 058h, 029h, 02Bh + db 03Fh, 033h, 048h, 048h, 039h, 062h, 023h, 029h + db 030h, 03Dh, 03Dh, 046h, 047h, 03Eh, 03Eh, 052h + db 052h, 047h, 059h, 054h, 054h, 03Fh, 08Fh, 02Ah + db 022h, 038h, 045h, 057h, 024h, 024h, 061h, 061h + db 032h, 032h, 090h, 062h, 02Ah, 051h, 091h, 092h + db 097h, 098h, 099h, 09Ah, 09Bh, 022h, 026h, 031h + db 051h, 09Ch, 09Dh, 09Eh, 09Fh, 063h, 063h, 0A0h + db 0A1h, 0A2h, 0A3h, 0A4h, 0A5h, 0A6h, 025h, 025h + db 0A7h, 0A8h, 0A9h, 0AAh, 0ABh, 0ACh, 0ADh, 093h + db 02Dh, 02Dh, 02Eh, 033h, 02Eh, 042h, 038h, 039h + db 031h, 0AEh, 0AFh, 0B0h, 0B1h, 055h, 058h, 0B2h + db 045h, 04Fh, 046h, 043h, 043h, 042h, 050h, 050h + db 04Ch, 057h, 04Ch, 05Ah, 05Fh, 05Fh, 055h, 0B4h + db 094h, 0B5h, 0B6h, 0B7h, 0B8h, 095h, 09Fh, 001h + db 04Fh, 00Eh, 080h, 0FCh, 014h, 074h, 005h, 02Eh + +CzecUcase: + dw 128 ; Table Size + db 080h, 09Ah, 090h, 0B6h, 08Eh, 0DEh, 08Fh, 080h + db 09Dh, 0D3h, 08Ah, 08Ah, 0D7h, 08Dh, 08Eh, 08Fh + db 090h, 091h, 091h, 0E2h, 099h, 095h, 095h, 097h + db 097h, 099h, 09Ah, 09Bh, 09Bh, 09Dh, 09Eh, 0ACh + db 0B5h, 0D6h, 0E0h, 0E9h, 0A4h, 0A4h, 0A6h, 0A6h + db 0A8h, 0A8h, 0AAh, 08Dh, 0ACh, 0B8h, 0AEh, 0AFh + db 0B0h, 0B1h, 0B2h, 0B3h, 0B4h, 0B5h, 0B6h, 0B7h + db 0B8h, 0B9h, 0BAh, 0BBh, 0BCh, 0BDh, 0BDh, 0BFh + db 0C0h, 0C1h, 0C2h, 0C3h, 0C4h, 0C5h, 0C6h, 0C6h + db 0C8h, 0C9h, 0CAh, 0CBh, 0CCh, 0CDh, 0CEh, 0CFh + db 0D1h, 0D1h, 0D2h, 0D3h, 0D2h, 0D5h, 0D6h, 0D7h + db 0B7h, 0D9h, 0DAh, 0DBh, 0DCh, 0DDh, 0DEh, 0DFh + db 0E0h, 0E1h, 0E2h, 0E3h, 0E3h, 0D5h, 0E6h, 0E6h + db 0E8h, 0E9h, 0E8h, 0EBh, 0EDh, 0EDh, 0DDh, 0EFh + db 0F0h, 0F1h, 0F2h, 0F3h, 0F4h, 0F5h, 0F6h, 0F7h + db 0F8h, 0F9h, 0FAh, 0EBh, 0FCh, 0FCh, 0FEh, 0FFh + +CzecUcase850: + dw 128 ; Table Size + db 080h, 09Ah, 090h, 0B6h, 08Eh, 0B7h, 08Fh, 080h + db 0D2h, 0D3h, 0D4h, 0D8h, 0D7h, 0DEh, 08Eh, 08Fh + db 090h, 092h, 092h, 0E2h, 099h, 0E3h, 0EAh, 0EBh + db 098h, 099h, 09Ah, 09Dh, 09Ch, 09Dh, 09Eh, 09Fh + db 0B5h, 0D6h, 0E0h, 0E9h, 0A5h, 0A5h, 0A6h, 0A7h + db 0A8h, 0A9h, 0AAh, 0ABh, 0ACh, 0ADh, 0AEh, 0AFh + db 0B0h, 0B1h, 0B2h, 0B3h, 0B4h, 0B5h, 0B6h, 0B7h + db 0B8h, 0B9h, 0BAh, 0BBh, 0BCh, 0BDh, 0BEh, 0BFh + db 0C0h, 0C1h, 0C2h, 0C3h, 0C4h, 0C5h, 0C7h, 0C7h + db 0C8h, 0C9h, 0CAh, 0CBh, 0CCh, 0CDh, 0CEh, 0CFh + db 0D1h, 0D1h, 0D2h, 0D3h, 0D4h, 0D5h, 0D6h, 0D7h + db 0D8h, 0D9h, 0DAh, 0DBh, 0DCh, 0DDh, 0DEh, 0DFh + db 0E0h, 0E1h, 0E2h, 0E3h, 0E5h, 0E5h, 0E6h, 0E8h + db 0E8h, 0E9h, 0EAh, 0EBh, 0EDh, 0EDh, 0EEh, 0EFh + db 0F0h, 0F1h, 0F2h, 0F3h, 0F4h, 0F5h, 0F6h, 0F7h + db 0F8h, 0F9h, 0FAh, 0FBh, 0FCh, 0FDh, 0FEh, 0FFh + +PolandUcase: + dw 128 ; Table Size + db 080h, 09Ah, 090h, 0B6h, 08Eh, 0DEh, 08Fh, 080h + db 09Dh, 0D3h, 08Ah, 08Ah, 0D7h, 08Dh, 08Eh, 08Fh + db 090h, 091h, 091h, 0E2h, 099h, 095h, 095h, 097h + db 097h, 099h, 09Ah, 09Bh, 09Bh, 09Dh, 09Eh, 0ACh + db 0B5h, 0D6h, 0E0h, 0E9h, 0A4h, 0A4h, 0A6h, 0A6h + db 0A8h, 0A8h, 0AAh, 08Dh, 0ACh, 0B8h, 0AEh, 0AFh + db 0B0h, 0B1h, 0B2h, 0B3h, 0B4h, 0B5h, 0B6h, 0B7h + db 0B8h, 0B9h, 0BAh, 0BBh, 0BCh, 0BDh, 0BDh, 0BFh + db 0C0h, 0C1h, 0C2h, 0C3h, 0C4h, 0C5h, 0C6h, 0C6h + db 0C8h, 0C9h, 0CAh, 0CBh, 0CCh, 0CDh, 0CEh, 0CFh + db 0D1h, 0D1h, 0D2h, 0D3h, 0D2h, 0D5h, 0D6h, 0D7h + db 0B7h, 0D9h, 0DAh, 0DBh, 0DCh, 0DDh, 0DEh, 0DFh + db 0E0h, 0E1h, 0E2h, 0E3h, 0E3h, 0D5h, 0E6h, 0E6h + db 0E8h, 0E9h, 0E8h, 0EBh, 0EDh, 0EDh, 0DDh, 0EFh + db 0F0h, 0F1h, 0F2h, 0F3h, 0F4h, 0F5h, 0F6h, 0F7h + db 0F8h, 0F9h, 0FAh, 0EBh, 0FCh, 0FCh, 0FEh, 0FFh + +PolandUcase850: + dw 128 ; Table Size + db 080h, 09Ah, 090h, 0B6h, 08Eh, 0B7h, 08Fh, 080h + db 0D2h, 0D3h, 0D4h, 0D8h, 0D7h, 0DEh, 08Eh, 08Fh + db 090h, 092h, 092h, 0E2h, 099h, 0E3h, 0EAh, 0EBh + db 098h, 099h, 09Ah, 09Dh, 09Ch, 09Dh, 09Eh, 09Fh + db 0B5h, 0D6h, 0E0h, 0E9h, 0A5h, 0A5h, 0A6h, 0A7h + db 0A8h, 0A9h, 0AAh, 0ABh, 0ACh, 0ADh, 0AEh, 0AFh + db 0B0h, 0B1h, 0B2h, 0B3h, 0B4h, 0B5h, 0B6h, 0B7h + db 0B8h, 0B9h, 0BAh, 0BBh, 0BCh, 0BDh, 0BEh, 0BFh + db 0C0h, 0C1h, 0C2h, 0C3h, 0C4h, 0C5h, 0C7h, 0C7h + db 0C8h, 0C9h, 0CAh, 0CBh, 0CCh, 0CDh, 0CEh, 0CFh + db 0D1h, 0D1h, 0D2h, 0D3h, 0D4h, 0D5h, 0D6h, 0D7h + db 0D8h, 0D9h, 0DAh, 0DBh, 0DCh, 0DDh, 0DEh, 0DFh + db 0E0h, 0E1h, 0E2h, 0E3h, 0E5h, 0E5h, 0E6h, 0E8h + db 0E8h, 0E9h, 0EAh, 0EBh, 0EDh, 0EDh, 0EEh, 0EFh + db 0F0h, 0F1h, 0F2h, 0F3h, 0F4h, 0F5h, 0F6h, 0F7h + db 0F8h, 0F9h, 0FAh, 0FBh, 0FCh, 0FDh, 0FEh, 0FFh + +BrazilUcase: + dw 128 ; Table Size + db 080h, 09Ah, 045h, 041h, 08Eh, 041h, 08Fh, 080h + db 045h, 045h, 045h, 049h, 049h, 049h, 08Eh, 08Fh + db 090h, 092h, 092h, 04Fh, 099h, 04Fh, 055h, 055h + db 059h, 099h, 09Ah, 09Bh, 09Ch, 09Dh, 09Eh, 09Fh + db 041h, 049h, 04Fh, 055h, 0A5h, 0A5h, 0A6h, 0A7h + db 0A8h, 0A9h, 0AAh, 0ABh, 0ACh, 0ADh, 0AEh, 0AFh + db 0B0h, 0B1h, 0B2h, 0B3h, 0B4h, 0B5h, 0B6h, 0B7h + db 0B8h, 0B9h, 0BAh, 0BBh, 0BCh, 0BDh, 0BEh, 0BFh + db 0C0h, 0C1h, 0C2h, 0C3h, 0C4h, 0C5h, 0C6h, 0C7h + db 0C8h, 0C9h, 0CAh, 0CBh, 0CCh, 0CDh, 0CEh, 0CFh + db 0D0h, 0D1h, 0D2h, 0D3h, 0D4h, 0D5h, 0D6h, 0D7h + db 0D8h, 0D9h, 0DAh, 0DBh, 0DCh, 0DDh, 0DEh, 0DFh + db 0E0h, 0E1h, 0E2h, 0E3h, 0E4h, 0E5h, 0E6h, 0E7h + db 0E8h, 0E9h, 0EAh, 0EBh, 0ECh, 0EDh, 0EEh, 0EFh + db 0F0h, 0F1h, 0F2h, 0F3h, 0F4h, 0F5h, 0F6h, 0F7h + db 0F8h, 0F9h, 0FAh, 0FBh, 0FCh, 0FDh, 0FEh, 0FFh + +BrazilUcase850: + dw 128 ; Table Size + db 080h, 09Ah, 090h, 0B6h, 08Eh, 0B7h, 08Fh, 080h + db 0D2h, 0D3h, 0D4h, 0D8h, 0D7h, 0DEh, 08Eh, 08Fh + db 090h, 092h, 092h, 0E2h, 099h, 0E3h, 0EAh, 0EBh + db 098h, 099h, 09Ah, 09Dh, 09Ch, 09Dh, 09Eh, 09Fh + db 0B5h, 0D6h, 0E0h, 0E9h, 0A5h, 0A5h, 0A6h, 0A7h + db 0A8h, 0A9h, 0AAh, 0ABh, 0ACh, 0ADh, 0AEh, 0AFh + db 0B0h, 0B1h, 0B2h, 0B3h, 0B4h, 0B5h, 0B6h, 0B7h + db 0B8h, 0B9h, 0BAh, 0BBh, 0BCh, 0BDh, 0BEh, 0BFh + db 0C0h, 0C1h, 0C2h, 0C3h, 0C4h, 0C5h, 0C7h, 0C7h + db 0C8h, 0C9h, 0CAh, 0CBh, 0CCh, 0CDh, 0CEh, 0CFh + db 0D1h, 0D1h, 0D2h, 0D3h, 0D4h, 0D5h, 0D6h, 0D7h + db 0D8h, 0D9h, 0DAh, 0DBh, 0DCh, 0DDh, 0DEh, 0DFh + db 0E0h, 0E1h, 0E2h, 0E3h, 0E5h, 0E5h, 0E6h, 0E8h + db 0E8h, 0E9h, 0EAh, 0EBh, 0EDh, 0EDh, 0EEh, 0EFh + db 0F0h, 0F1h, 0F2h, 0F3h, 0F4h, 0F5h, 0F6h, 0F7h + db 0F8h, 0F9h, 0FAh, 0FBh, 0FCh, 0FDh, 0FEh, 0FFh + +BrazilCollating: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00Ah, 00Bh, 00Ch, 00Dh, 00Eh, 00Fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01Ah, 01Bh, 01Ch, 01Dh, 01Eh, 01Fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02Ah, 02Bh, 02Ch, 02Dh, 02Eh, 02Fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03Ah, 03Bh, 03Ch, 03Dh, 03Eh, 03Fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04Ah, 04Bh, 04Ch, 04Dh, 04Eh, 04Fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05Ah, 05Bh, 05Ch, 05Dh, 05Eh, 05Fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04Ah, 04Bh, 04Ch, 04Dh, 04Eh, 04Fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05Ah, 07Bh, 07Ch, 07Dh, 07Eh, 07Fh + db 043h, 055h, 045h, 041h, 041h, 041h, 041h, 043h + db 045h, 045h, 045h, 049h, 049h, 049h, 041h, 041h + db 045h, 041h, 041h, 04Fh, 04Fh, 04Fh, 055h, 055h + db 059h, 04Fh, 055h, 024h, 024h, 024h, 024h, 024h + db 041h, 049h, 04Fh, 055h, 04Eh, 04Eh, 0A6h, 0A7h + db 03Fh, 0A9h, 0AAh, 0ABh, 0ACh, 021h, 022h, 022h + db 0B0h, 0B1h, 0B2h, 0B3h, 0B4h, 0B5h, 0B6h, 0B7h + db 0B8h, 0B9h, 0BAh, 0BBh, 0BCh, 0BDh, 0BEh, 0BFh + db 0C0h, 0C1h, 0C2h, 0C3h, 0C4h, 0C5h, 0C6h, 0C7h + db 0C8h, 0C9h, 0CAh, 0CBh, 0CCh, 0CDh, 0CEh, 0CFh + db 0D0h, 0D1h, 0D2h, 0D3h, 0D4h, 0D5h, 0D6h, 0D7h + db 0D8h, 0D9h, 0DAh, 0DBh, 0DCh, 0DDh, 0DEh, 0DFh + db 0E0h, 053h, 0E2h, 0E3h, 0E4h, 0E5h, 0E6h, 0E7h + db 0E8h, 0E9h, 0EAh, 0EBh, 0ECh, 0EDh, 0EEh, 0EFh + db 0F0h, 0F1h, 0F2h, 0F3h, 0F4h, 0F5h, 0A0h, 001h + db 0C4h, 012h, 080h, 0FCh, 014h, 074h, 005h, 02Eh + +BrazilCollat850: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00Ah, 00Bh, 00Ch, 00Dh, 00Eh, 00Fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01Ah, 01Bh, 01Ch, 01Dh, 01Eh, 01Fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02Ah, 02Bh, 02Ch, 02Dh, 02Eh, 02Fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03Ah, 03Bh, 03Ch, 03Dh, 03Eh, 03Fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04Ah, 04Bh, 04Ch, 04Dh, 04Eh, 04Fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05Ah, 05Bh, 05Ch, 05Dh, 05Eh, 05Fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04Ah, 04Bh, 04Ch, 04Dh, 04Eh, 04Fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05Ah, 07Bh, 07Ch, 07Dh, 07Eh, 07Fh + db 043h, 055h, 045h, 041h, 041h, 041h, 041h, 043h + db 045h, 045h, 045h, 049h, 049h, 049h, 041h, 041h + db 045h, 041h, 041h, 04Fh, 04Fh, 04Fh, 055h, 055h + db 059h, 04Fh, 055h, 04Fh, 024h, 04Fh, 09Eh, 024h + db 041h, 049h, 04Fh, 055h, 04Eh, 04Eh, 0A6h, 0A7h + db 03Fh, 0A9h, 0AAh, 0ABh, 0ACh, 021h, 022h, 022h + db 0B0h, 0B1h, 0B2h, 0B3h, 0B4h, 041h, 041h, 041h + db 0B8h, 0B9h, 0BAh, 0BBh, 0BCh, 024h, 024h, 0BFh + db 0C0h, 0C1h, 0C2h, 0C3h, 0C4h, 0C5h, 041h, 041h + db 0C8h, 0C9h, 0CAh, 0CBh, 0CCh, 0CDh, 0CEh, 024h + db 044h, 044h, 045h, 045h, 045h, 049h, 049h, 049h + db 049h, 0D9h, 0DAh, 0DBh, 0DCh, 0DDh, 049h, 0DFh + db 04Fh, 053h, 04Fh, 04Fh, 04Fh, 04Fh, 0E6h, 0E8h + db 0E8h, 055h, 055h, 055h, 059h, 059h, 0EEh, 0EFh + db 0F0h, 0F1h, 0F2h, 0F3h, 0F4h, 0F5h, 0F6h, 0F7h + db 0F8h, 0F9h, 0FAh, 0FBh, 0FCh, 0FDh, 0FEh, 0FFh + +DenmarkUcase: + dw 128 ; Table Size + + db 080h, 09ah, 090h, 'A', 08eh, 'A', 08fh, 080h + db 'E', 'E', 'E', 'I', 'I', 'I', 08eh, 08fh + db 090h, 092h, 092h, 'O', 099h, 'O', 'U', 'U' + db 'Y', 099h, 09ah +danish_table: + db 09dh, 09ch, 09dh, 09eh, 09fh ; 9Bh + db 'A', 'I', 'O', 'U', 0a5h, 0a5h, 0a6h, 0a7h + db 0a8h, 0a9h + db 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 0e1h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + +DenmarkCollating: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 028h, 02fh, 029h, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 028h, 02fh, 029h, 07eh, 07fh + db 043h, 059h, 045h, 041h, 05bh, 041h, 05dh, 043h + db 045h, 045h, 045h, 049h, 049h, 049h, 05bh, 05dh + db 045h, 05bh, 05bh, 04fh, 05ch, 04fh, 055h, 055h + db 059h, 05ch, 059h, 05ch, 024h, 05ch, 024h, 024h + db 041h, 049h, 04fh, 055h, 04eh, 04eh, 041h, 04fh + db 03fh, 0a9h, 0aah, 0abh, 0ach, 021h, 022h, 024h + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 053h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + + +if COMPATIBLE +SwedenUcase: + dw 128 ; Table Size + + db 080h, 09ah, 090h, 'A', 08eh, 'A', 08fh, 080h + db 'E', 'E', 'E', 'I', 'I', 'I', 08eh, 08fh + db 090h, 092h, 092h, 'O', 099h, 'O', 'U', 'U' + db 'Y', 099h, 09ah, 09bh, 09ch, 09dh, 09eh, 09fh + db 'A', 'I', 'O', 'U', 0a5h, 0a5h, 0a6h, 0a7h + db 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 0e1h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh +endif +SwedenCollating: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + db 043h, 059h, 045h, 041h, 05ch, 041h, 05bh, 043h + db 045h, 045h, 045h, 049h, 049h, 049h, 05ch, 05bh + db 045h, 05ch, 05ch, 04fh, 05dh, 04fh, 055h, 055h + db 059h, 05dh, 059h, 024h, 024h, 024h, 024h, 024h + db 041h, 049h, 04fh, 055h, 04eh, 04eh, 0a6h, 0a7h + db 03fh, 0a9h, 0aah, 0abh, 0ach, 021h, 022h, 022h + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 053h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + + + +NorwayCollating: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + db 043h, 059h, 045h, 041h, 05bh, 041h, 05dh, 043h + db 045h, 045h, 045h, 049h, 049h, 049h, 05bh, 05dh + db 045h, 05bh, 05bh, 04fh, 05ch, 04fh, 055h, 055h + db 059h, 05ch, 059h, 05ch, 024h, 05ch, 024h, 024h + db 041h, 049h, 04fh, 055h, 04eh, 04eh, 041h, 04fh + db 03fh, 0a9h, 0aah, 0abh, 0ach, 021h, 022h, 024h + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 053h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + +if TURKCP EQ 853 +; +; UpperCase Table for Turkish CodePage 853 +; +TurkishUcase: + dw 128 ; Table Size +Turkish_table: + db 080h, 09ah, 090h, 0b6h, 08eh, 0b7h, 08fh, 080h + db 0d2h, 0d3h, 0d4h, 0d8h, 0d7h, 049h, 08eh, 08fh + db 090h, 092h, 092h, 0e2h, 099h, 0e3h, 0eah, 0ebh + db 098h, 099h, 09ah, 09dh, 09ch, 09dh, 09eh, 09eh + db 0b5h, 0d6h, 0e0h, 0e9h, 0a5h, 0a5h, 0a6h, 0a6h + db 0a8h, 0a8h, 0aah, 0abh, 0ach, 09eh, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0bdh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c6h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 049h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 0e1h, 0e2h, 0e3h, 0e4h, 0e4h, 0e6h, 0e7h + db 0e7h, 0e9h, 0eah, 0ebh, 0ech, 0ech, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + +TurkishCollating: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + + db 043h, 055h, 045h, 041h, 041h, 041h, 043h, 043h + db 045h, 045h, 045h, 049h, 049h, 049h, 041h, 043h + db 045h, 043h, 043h, 04fh, 04fh, 04fh, 055h, 055h + db 049h, 04fh, 055h, 047h, 024h, 047h, 053h, 053h + db 041h, 049h, 04fh, 055h, 04eh, 04eh, 047h, 047h + db 048h, 048h, 020h, 0abh, 04ah, 053h, 022h, 022h + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 041h, 041h, 041h + db 053h, 0b9h, 0bah, 0bbh, 0bch, 05ah, 05ah, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 053h, 053h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 024h + db 020h, 020h, 045h, 045h, 045h, 049h, 049h, 049h + db 049h, 0d9h, 0dah, 0dbh, 0dch, 020h, 049h, 0dfh + db 04fh, 0e1h, 04fh, 04fh, 047h, 047h, 0e6h, 048h + db 048h, 055h, 055h, 055h, 055h, 055h, 020h, 0efh + db 0f0h, 020h, 0f2h, 04eh, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 020h, 0fch, 0fdh, 0feh, 0ffh +endif + +if TURKCP EQ 857 +; +; Turkish UpperCase Table codepage 857 ???? +; +TurkishUcase: + dw 128 ; Table Size +Turkish_table: + db 080h, 09ah, 090h, 0b6h, 08eh, 0b7h, 08fh, 080h + db 0d2h, 0d3h, 0d4h, 0d8h, 0d7h, 049h, 08eh, 08fh + db 090h, 092h, 092h, 0e2h, 099h, 0e3h, 0eah, 0ebh + db 098h, 099h, 09ah, 09dh, 09ch, 09dh, 09eh, 09eh + db 0b5h, 0d6h, 0e0h, 0e9h, 0a5h, 0a5h, 0a6h, 0a6h + db 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c7h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 0e1h, 0e2h, 0e3h, 0e5h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0deh, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh +; +; +TurkishCollating: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 028h, 02fh, 029h, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 028h, 02fh, 029h, 07eh, 07fh + + db 043h, 055h, 045h, 041h, 041h, 041h, 041h, 043h + db 045h, 045h, 045h, 049h, 049h, 049h, 041h, 041h + db 045h, 041h, 041h, 04fh, 04fh, 04fh, 055h, 055h + db 049h, 04fh, 055h, 09bh, 024h, 04dh, 053h, 053h + db 041h, 049h, 04fh, 055h, 04eh, 04eh, 047h, 047h + db 0a8h, 0a9h, 0aah, 0abh, 0ach, 021h, 022h, 022h + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 041h, 041h, 041h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 041h, 041h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 024h + db 0d0h, 0d1h, 045h, 045h, 045h, 020h, 049h, 049h + db 049h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 049h, 0dfh + db 04fh, 0e1h, 04fh, 04fh, 04fh, 04fh, 0e6h, 020h + db 0e8h, 055h, 055h, 055h, 049h, 059h, 0eeh, 0efh + db 0f0h, 0f1h, 020h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh +endif + +;; +PortugalUcase: + dw 128 ; Table Size +Portugese_table: + db 080h, 09ah, 090h, 08fh, 08eh, 091h, 086h, 080h + db 089h, 089h, 092h, 08bh, 08ch, 098h, 08eh, 08fh + db 090h, 091h, 092h, 08ch, 099h, 0a9h, 096h, 09dh + db 098h, 099h, 09ah, 09bh, 09ch, 09dh, 09eh, 09fh + db 086h, 08bh, 09fh, 096h, 0a5h + db 0a5h, 0a6h, 0a7h + db 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 0e1h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + +PortugalCollating: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + db 043h, 055h, 045h, 041h, 041h, 041h, 041h, 043h + db 045h, 045h, 045h, 049h, 04fh, 049h, 041h, 041h + db 045h, 041h, 045h, 04fh, 04fh, 04fh, 055h, 055h + db 049h, 04fh, 055h, 024h, 024h, 055h, 024h, 04fh + db 041h, 049h, 04fh, 055h, 04eh, 04eh, 0a6h, 0a7h + db 03fh, 04fh, 0aah, 0abh, 0ach, 021h, 022h, 022h + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 053h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + + + +MiddleEastCollating: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + db 080h, 081h, 082h, 083h, 084h, 085h, 086h, 087h + db 088h, 089h, 08ah, 08bh, 08ch, 08dh, 08eh, 08fh + db 090h, 091h, 092h, 093h, 094h, 095h, 096h, 097h + db 098h, 0e9h, 0eah, 0fbh, 0ffh, 0ebh, 0ech, 0b3h + db 099h, 09ah, 0b6h, 09bh, 09ch, 0b8h, 0fdh, 0feh + db 0bch, 0bdh, 0c0h, 0c2h, 0a3h, 0c4h, 0c6h, 0c8h + db 0a4h, 0a5h, 0a6h, 0a7h, 0a8h, 0a9h, 0aah, 0abh + db 0ach, 0adh, 0e0h, 0aeh, 0ceh, 0d0h, 0d2h, 0afh + db 09dh, 0b4h, 0b5h, 0b7h, 0b9h, 0d9h, 0bah, 0bbh + db 0beh, 0bfh, 0c1h, 0c3h, 0c5h, 0c7h, 0c9h, 0cah + db 0cbh, 0cch, 0cdh, 0cfh, 0d1h, 0d3h, 0d5h, 0d6h + db 0d7h, 0dah, 0deh, 09eh, 09fh, 0a0h, 0a1h, 0d8h + db 0b2h, 0e1h, 0e3h, 0e5h, 0edh, 0efh, 0f1h, 0f3h + db 0f5h, 0f6h, 0fah, 0d4h, 0dbh, 0ddh, 0dch, 0eeh + db 0b1h, 0b0h, 0f0h, 0f2h, 0f4h, 0f7h, 0f9h, 0dfh + db 0e2h, 0e7h, 0e8h, 0e6h, 0e4h, 0f8h, 0a2h, 0ffh + + + + +IsraelUcase: + dw 128 ; Table Size + + db 080h, 081h, 082h, 083h, 084h, 085h, 086h, 087h + db 088h, 089h, 08ah, 08bh, 08ch, 08dh, 08eh, 08fh + db 090h, 091h, 092h, 093h, 094h, 095h, 096h, 097h + db 098h, 099h, 09ah, 09bh, 09ch, 09dh, 09eh, 09fh + db 'A', 'I', 'O', 'U', 0a5h, 0a5h, 0a6h, 0a7h + db 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 0e1h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh +IsraelCollating: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + db 080h, 081h, 082h, 083h, 084h, 085h, 086h, 087h + db 088h, 089h, 08ah, 08bh, 08ch, 08dh, 08eh, 08fh + db 090h, 091h, 092h, 093h, 094h, 095h, 096h, 097h + db 098h, 099h, 09ah, 024h, 024h, 024h, 024h, 024h + db 041h, 049h, 04fh, 055h, 04eh, 04eh, 0a6h, 0a7h + db 03fh, 0a9h, 0aah, 0abh, 0ach, 021h, 022h, 022h + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 053h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + +if COMPATIBLE +Ucasetbl850: + dw 128 ; Table Size + db 043h, 055h, 045h, 041h, 041h, 041h, 041h, 043h + db 045h, 045h, 045h, 049h, 049h, 049h, 041h, 041h + db 045h, 092h, 092h, 04fh, 04fh, 04fh, 055h, 055h + db 059h, 04fh, 055h, 04fh, 09ch, 04fh, 09eh, 09fh + db 041h, 049h, 04fh, 055h, 0a5h, 0a5h, 0a6h, 0a7h + db 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 041h, 041h, 041h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 041h, 041h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d1h, 0d1h, 045h, 045h, 045h, 049h, 049h, 049h + db 049h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 049h, 0dfh + db 04fh, 0e1h, 04fh, 04fh, 04fh, 04fh, 0e6h, 0e8h + db 0e8h, 055h, 055h, 055h, 059h, 059h, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh +else + +Ucasetbl850: +Nethcase850: +Germcase850: +endif + +LatiCase850: + dw 128 ; Table Size + db 080h, 09ah, 090h, 0b6h, 08eh, 0b7h, 08fh, 080h + db 0d2h, 0d3h, 0d4h, 0d8h, 0d7h, 0deh, 08eh, 08fh + db 090h, 092h, 092h, 0e2h, 099h, 0e3h, 0eah, 0ebh + db 059h, 099h, 09ah, 09dh, 09ch, 09dh, 09eh, 09fh + db 0b5h, 0d6h, 0e0h, 0e9h, 0a5h, 0a5h, 0a6h, 0a7h + db 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c7h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d1h, 0d1h, 0d2h, 0d3h, 0d4h, 049h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 0e1h, 0e2h, 0e3h, 0e5h, 0e5h, 0e6h, 0e8h + db 0e8h, 0e9h, 0eah, 0ebh, 0edh, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + +if COMPATIBLE +NethCase850: + dw 128 ; Table Size + + db 080h, 055h, 45h, 041h, 041h, 041h, 08fh, 080h + db 045h, 045h, 045h, 049h, 049h, 049h, 041h, 08fh + db 045h, 092h, 092h, 04fh, 04fh, 04fh, 055h, 055h + db 098h, 04fh, 055h, 04fh, 09ch, 04fh, 09eh, 09fh + db 041h, 049h, 04fh, 055h, 0a5h, 0a5h, 0a6h, 0a7h + db 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 041h, 041h, 041h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 041h, 041h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d1h, 0d1h, 045h, 045h, 045h, 049h, 049h, 049h + db 049h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 049h, 0dfh + db 04fh, 0e1h, 04fh, 04fh, 04fh, 04fh, 0e6h, 0e8h + db 0e8h, 055h, 055h, 055h, 059h, 059h, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + +GermCase850: + dw 128 ; Table Size + db 043h, 09ah, 045h, 041h, 08eh, 041h, 041h, 043h + db 045h, 045h, 045h, 049h, 049h, 049h, 08eh, 041h + db 045h, 092h, 092h, 04fh, 099h, 04fh, 055h, 055h + db 059h, 099h, 09ah, 04fh, 09ch, 04fh, 09eh, 09fh + db 041h, 049h, 04fh, 055h, 0a5h, 0a5h, 0a6h, 0a7h + db 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 041h, 041h, 041h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 041h, 041h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d1h, 0d1h, 045h, 045h, 045h, 049h, 049h, 049h + db 049h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 049h, 0dfh + db 04fh, 0e1h, 04fh, 04fh, 04fh, 04fh, 0e6h, 0e8h + db 0e8h, 055h, 055h, 055h, 059h, 059h, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh +endif + +Ucasetbl932: + dw 128 ; Table size + db 080h, 081h, 082h, 083h, 084h, 085h, 086h, 087h + db 088h, 089h, 08ah, 08bh, 08ch, 08dh, 08eh, 08fh + db 090h, 091h, 092h, 093h, 094h, 095h, 096h, 097h + db 098h, 099h, 09ah, 09bh, 09ch, 09dh, 09eh, 09fh + db 0a0h, 0a1h, 0a2h, 0a3h, 0a4h, 0a5h, 0a6h, 0a7h + db 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 0e1h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + +DBCS_932: + dw 6 ; Table Size + db 081h, 09fh, 0e0h, 0fch, 000h, 000h + + +DBCS_934: + dw 4 ; Table Size + db 0a1h, 0feh, 000h, 000h + + +DBCS_936: + dw 4 ; Table Size + db 081h, 0fch, 000h, 000h + + + END diff --git a/IBMDOS/COUNTRY.DEF b/IBMDOS/COUNTRY.DEF new file mode 100644 index 0000000..3ea7880 --- /dev/null +++ b/IBMDOS/COUNTRY.DEF @@ -0,0 +1,73 @@ +; File : $COUNTRY.DEF$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG + +US_DATE equ 0 ; American Date Format mm/dd/yy +EURO_DATE equ 1 ; European Date Format dd/mm/yy +JAP_DATE equ 2 ; Japanese Date Format yy/mm/dd + +CLOCK_12 equ 0 ; 12 Hour Clock Time Format +CLOCK_24 equ 1 ; 24 Hour Clock Time Format + +CI_CODE equ word ptr 0FFFCh ; Country Code +CI_CODEPAGE equ word ptr 0FFFEh ; Code page +CI_DATEFMT equ word ptr 0 ; Date Format +CI_CURRENCY equ byte ptr 2 ; Currency Symbols +CI_THOUSANDS equ byte ptr 7 ; Thousands Separator +CI_DECIMAL equ byte ptr 9 ; Decimal Separator +CI_DATESEP equ byte ptr 11 ; Date Separator +CI_TIMESEP equ byte ptr 13 ; Time Separator +CI_CURFMT equ byte ptr 15 ; Currency Format +CI_CURDIGITS equ byte ptr 16 ; Significant Currency Digits +CI_TIMEFMT equ byte ptr 17 ; Time Format +CI_CASEOFF equ word ptr 18 ; Case Translation Offset +CI_CASESEG equ word ptr 20 ; Case Translation Segment +CI_DATASEP equ byte ptr 22 ; Data List Separator +CI_STATICLEN equ 24 ; Static Country Data Length +CI_LENGTH equ 32 ; Total Country Data Length + +EXI_ID equ byte ptr 0 ; Information ID +EXI_TBLOFF equ word ptr 1 ; Table Offset +EXI_TBLSEG equ word ptr 3 ; Table Segment + +EXI_ID1 equ byte ptr 0 ; 6501 Info ID (why move it?!) +EXI_LENGTH equ word ptr 1 ; 6501 Table Length +EXI_DATA_LEN equ 3 ; 6501 Country Data + +EXCI_CUR_COUNTRY equ word ptr 0 ; Current Country +EXCI_CUR_CP equ word ptr 2 ; Current Codepage +EXCI_CI_DATAOFF equ 4 ; Start of CI_ data + +EXCI_STATLEN equ CI_STATICLEN+4 ; Static Ext Country Info +EXCI_MAXLEN equ EXCI_STATLEN+10+EXI_DATA_LEN ; Max Ext Country Info + diff --git a/IBMDOS/DIRS.A86 b/IBMDOS/DIRS.A86 new file mode 100644 index 0000000..effbb68 --- /dev/null +++ b/IBMDOS/DIRS.A86 @@ -0,0 +1,827 @@ +title 'DIRS - dos directory support' +; File : $DIRS.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; DIRS.A86 1.13 94/12/01 13:16:24 +; changed error code if directory entry cannot be allocated; +; DIRS.A86 1.12 93/08/27 18:49:04 +; hash code fixup on previously unused entries resets hash count +; pcformat bug where an extra (zero-length) command.com was left on disk +; ENDLOG +; +; Date Who Modification +; --------- --- --------------------------------------- +; 19 Aug 91 Initial version created for VLADIVAR + +eject + +include bdos.equ +include i:mserror.equ +include i:fdos.equ + +eject +PCMODE_DATA dseg +if DELWATCH + extrn fdos_stub:dword ; for calling delwatch TSR +endif + +BDOS_DATA dseg word + extrn adrive:byte + EXTRN clsize:WORD + extrn diradd:word + extrn dirinroot:word + EXTRN dirperclu:WORD + EXTRN dosfat:WORD + extrn hashroot:dword + extrn hashmax:word + EXTRN info_fcb:BYTE + extrn lastcl:word + extrn psecsiz:word + +eject + +hash rw 2 ; hash code work area + +; The dirbcb says what is in the local dirbuf + +dirbcb db 0ffh ; drive of dirbuf entry +dirbcb_cl dw 0 ; cluster of dirbuf entry +dirbcb_dcnt dw 0 ; directory index of dirbuf entry +dirbcb_block rw 2 ; block of dirbuf entry +dirbcb_offset dw 0 ; byte offset in block of dirbuf entry + + + public dirbuf +dirbuf rb 32 ; local directory buffer + + public dirp +dirp dw 0 ; directory entry pointer + + public dcnt +dcnt dw 0 ; directory index count + + public finddfcb_mask +finddfcb_mask dw 0800h ; hi byte = reject DA_VOLUME attribs + ; lo byte = accept non-0 start clusters + ; 00FF = include labels, but not + ; pending deletes + ; 0000 = include everything + public chdblk +chdblk dw 0 ; current cluster # of directory + + +BDOS_CODE cseg + extrn alloc_cluster:NEAR + extrn clus2sec:near + extrn hdsblk:near ; get current directory block + extrn fdos_error:NEAR + extrn fixfat:NEAR + extrn getnblk:NEAR + extrn locate_buffer:near + extrn update_dir:NEAR + extrn update_fat:NEAR + extrn zeroblk:near + +eject + + + public allocdir + public discard_dirbuf + public finddfcb + public finddfcbf + public fill_dirbuf + public flush_dirbuf + public getdir + public hshdscrd + public mkhsh + public setenddir +eject + +;---------- +fill_dirbuf: ;get 32 byte directory entry +;---------- +; On Entry: +; AX = cluster to read (0=root) +; BX = dir within cluster +; On Exit: +; DI -> dirbuf entry + + call discard_dirbuf ; invalidate block in case of error + mov dirbcb_cl,ax ; remember which cluster + mov dirbcb_dcnt,bx ; and dir entry we want + test ax,ax ; are we in the root ? + jz fill_dirbuf10 + mov cl,FCBSHF + shl bx,cl ; BX = byte offset in cluster + call clus2sec ; DX:AX -> sector + jmps fill_dirbuf20 ; BX = offset in sector +fill_dirbuf10: + mov ax,FCBLEN + mul bx ; DX:AX = byte offset + div psecsiz ; AX = sector offset, DX = byte offset + mov bx,dx ; BX = byte offset in sector + xor dx,dx + add ax,diradd ; add in start of root dir + adc dx,dx +fill_dirbuf20: + mov dirbcb_block,ax ; we want this sector + mov dirbcb_block+WORD,dx + mov dirbcb_offset,bx + xchg ax,dx ; DX = low word of sector + mov ah,al ; AH = low byte of high word + push bx ; save byte offset in sector + mov cx,0FF00h+BF_ISDIR ; locate directory sector + call locate_buffer ; ES:SI -> BCB_ + pop bx ; BX = offset within sector + push es ! pop ds ; DS:SI -> buffer control block + lea si,BCB_DATA[si+bx] ; DS:SI -> data in buffer + push ss ! pop es + mov di,offset dirbuf ; ES:DI -> dir buffer + push di + mov cx,32/WORD ; copy into local buffer + rep movsw + pop di ; DI -> dir buffer + push ss ! pop ds + mov al,adrive ; remember where we are + mov dirbcb,al ; so we can write it back + ret + + +;------------ +flush_dirbuf: +;------------ + mov al,0FFh + xchg al,dirbcb ; do we have anything to flush ? + cmp al,adrive + jne flush_dir20 ; skip if invalid contents + mov si,offset dirbcb_block + lodsw ; get low word of block + xchg ax,dx ; put it in DX where it belongs + lodsw ; get high word of block + mov ah,al ; AH:DX -> block to find + mov cx,0FF00h+BF_ISDIR ; look for directory + call locate_buffer ; locate physical sector + or es:BCB_FLAGS[si],BF_DIRTY; mark this buffer as modified + mov bx,dirbcb_offset ; BX = offset within buffer + lea di,BCB_DATA[si+bx] ; ES:DI -> offset in buffer + + mov al,es:[di] ; AL = 1st character of dir entry + + mov si,offset dirbuf ; get CP/M buffer address + mov cx,32/WORD + rep movsw ; copy modified entry back + + push ax + xor dh,dh ; we only want HCB_ if it's there + mov cx,dirbcb_cl ; and it's this cluster + call find_hcb ; does an HCB_ exist for this entry ? + pop ax + jc flush_dir20 ; no, skip update + mov di,dirbcb_dcnt ; we want this dir entry + cmp di,es:HCB_CNT[bx] ; is this within the hashed entries ? + jae flush_dir20 ; no, skip the fixup + + test al,al ; are we using a never used entry ? + jnz flush_dir10 ; if so don't trust subsequent hash + inc di ; codes as they have never been read. + mov es:HCB_CNT[bx],di ; Truncate table to force a read of the + dec di ; next dir entry (which will normally +flush_dir10: ; also be never used) + shl di,1 ; DI = offset of hashed entry + lea di,HCB_DATA[bx+di] + mov si,offset dirbuf ; this is the dir entry + call mkhsh ; AX = hash code of our entry + stosw ; update hash code for dir entry +flush_dir20: + push ds ! pop es ; ES = local data segment + ret + +;-------------- +discard_dirbuf: +;-------------- + mov dirbcb,0FFh ; invalidate dirbuf + ret + + +;-------- +rd_pcdir: +;-------- +; Exit: AX = offset of directory entry +; = 0 if end of directory + + + mov bx,dcnt + inc bx + mov dcnt,bx ; dcnt=dcnt+1 + call hdsblk ; AX = current directory block + jz rd_pcdir40 ; skip if we're at the root + +; we we in a subdirectory - lets follow the chain + + xchg ax,cx ; keep subdir cluster in CX + mov ax,FCBLEN ; AX = size of dir entry + mul bx ; DX:AX = offset of set entry we want + div clsize ; AX = # clusters to skip, DX = offset in cluster + xchg ax,dx ; DX = # to skip, AX = offset in cluster + xchg ax,cx ; AX = start of chain, CX = offset in cluster + xchg bx,cx ; BX = offset in cluster, CX = dcnt + jcxz rd_pcdir20 ; 1st subdir entry, we are already there + mov cx,chdblk ; do we already know where we are ? + jcxz rd_pcdir10 ; if not trace from start of chain + xchg ax,cx ; AX = cluster of last dir entry + test bx,bx ; have we moved onto next cluster? + jnz rd_pcdir20 ; no, trust me.. + mov dx,1 ; move on to next entry in the chain +rd_pcdir10: + or dx,dx ; skip along chain until we arrive + jz rd_pcdir20 ; at the destination cluster + dec dx + push bx + push dx + call getnblk ; AX = next cluster in chain + pop dx + pop bx + cmp ax,lastcl ; have we fallen off the end of the chain ? + jbe rd_pcdir10 + jmps rd_pcdir30 ; yes, set end of directory +rd_pcdir20: + mov chdblk,ax ; remember this cluster for next time + mov cl,FCBSHF ; to divide by fcb size + shr bx,cl ; BX = dir offset in cluster + jmps rd_pcdir50 ; now go and find the entry + +rd_pcdir30: + call setenddir ; yes, set dcnt to end of directory + jmps rd_pcdir60 + +rd_pcdir40: +; we are in the root directory + cmp bx,dirinroot ; end of the root directory ? + jae rd_pcdir30 +rd_pcdir50: + call fill_dirbuf ;locate directory entry + xchg ax,di ; AX -> dir entry + cmp dcnt,ENDDIR + jnz rd_pcdir70 +rd_pcdir60: + xor ax,ax ; return 0 if endofdir +rd_pcdir70: + mov bx,ax + ret + + +;--------- +setenddir: ;set dcnt to the end of directory (dcnt = 0ffffh) +;--------- + mov dcnt,ENDDIR + mov chdblk,0 + ret + + +chk_wild: ;check fcb for ? marks +;-------- +; On Entry: +; bx -> FCB +; On Exit: +; ZF set if ? found +; BX preserved + push ds ! pop es ; ES -> SYSDAT + lea di,byte ptr FNAME[bx] ; ES:DI -> name to scan + mov cx,11 + mov al,'?' ; scan for wild cards + repne scasb + ret + +eject + +eject +;--------- +finddfcbf: ; Find matching directory fcb(dfcb) from beginning of directory +;--------- + call setenddir ; set up for search first + +;-------- +finddfcb: ; Find matching directory fcb(dfcb) +;-------- + mov cx,2 + +;------ +getdir: +;------ +; entry: CH = offset info_fcb (always 0 except from rename) +; CL = search length +; 0 = return next fcb +; 1 = return empty fcb +; 2 = find match (Based on info_fcb) +; 3 = find match? Based on info_fcb +; +; exit: AX,BX,DIRP = pointer to dfcb +; 0 = no match (end of directory) +; other = offset of requested directory entry +; ZF = zero flag is set based on AX +; + +; Note: The most common call for this function is with CX = +; 2 (match with name, not extent) with 'dcnt' set to +; 0FFFFh (search from beginning of the directory +; (e.g. open, create, delate, rename, etc.). +; Therefore we try to optimize directory searches +; using a dynamic hash table... + + ;struct dirfcb *getdir(offset,srchl); + + cmp dcnt,0FFFFh ;if ((dcnt == 0xffff) && + jne gtd_next + mov hash+2,cx ; Save off calling option + xor ax,ax ; hash code 0 for free entry + cmp cx,1 ; what kind of search? + je gtdo15 ; CL=1: find free entry (AX=0) + jb gtd_next ; CL=0: find any entry (unhashed) + or ch,ch ; name in INFO_FCB+1? + jnz gtd_next ; no, unhashed search + mov bx,offset info_fcb + call chk_wild ; wildcards used in search? + jz unhshd1 ; yes, can't use hashing + mov si,offset info_fcb+1 ; else compute hash code + call mkhsh ; for name to find +gtdo15: + mov hash,ax ; save it for search + call hdsblk ; get directory block +gtdo3: + push ax ; save dir block for later + call hashsrch ; try and use hashing to find a match + jnc gtdo4 ; look closer if we get possible match + add dcnt,ax ; else skip known non-matches + pop ax ; recover current dir block + test ax,ax ; if we are in the root + jz unhashed ; we must search the hard way + xchg ax,bx + mov ax,dcnt ; should we go onto next cluster ? + inc ax ; only if next entry is the start + xor dx,dx ; of a cluster + div dirperclu + xchg ax,bx + test dx,dx ; at start of cluster ? + jnz unhashed + call getnblk ; onto next cluster until we are + cmp ax,lastcl ; at the end of the chain + jbe gtdo3 + jmps unhashed ; out of luck +gtdo4: + add dcnt,ax ; we have found a match, so start + pop ax ; search here +; jmps unhashed +unhashed: ; /* locate entry */ + mov chdblk,0 +unhshd1: + mov cx,hash+2 ;} +gtd_next: +;-------- + push cx + call rd_pcdir ; Get Next DFCB + pop cx +gtd_exit: + mov dirp,ax ; assume this is the one + mov bx,ax + or ax,ax ; should we exit with not found ? + jz gtd2 + cmp cl,NEXT ; Caller wishes next dfcb? + jne gtd3 ; NO +gtd2: + mov ax,bx ; return BX (DIRP or NULLPTR) + or ax,ax ; return ZF (1 = not found) + ret + +gtd3: + cmp cl,EMPTY ; Caller wishes an empty dfcb? + jne gtd4 ; NO + mov al,DNAME[bx] ; Get directory type + or al,al ; Is it free? + jz gtd2 ; YES (00 -> never used) + cmp al,0E5h ; Is the dfcb empty? + je gtd2 ; YES (E5 -> erased) + jmps gtd_next ; NO, try the next + +gtd4: ; looking for particular entry + call hdsblk ; Are we at the root? + jnz gtd5 ; skip if not + mov ax,dcnt ; check for end of directory + cmp ax,dirinroot ; have we reached end of root? + mov ax,0 ; assume we have + jae gtd_exit ; exit if we have +gtd5: + mov al,DNAME[bx] ; Get dfcb type + cbw + or ax,ax ; Are we at End Of Directory(EOD) + jz gtd_exit ; YES + cmp al,0E5h ; Is this a free fcb? + je gtd_next ; Yes, try again + mov ax,finddfcb_mask ; do we want labels/pending deletes + test DATTS[bx],ah ; filter out volume labels? + jnz gtd_next ; we normally reject them +if DELWATCH + cbw ; we want labels - do we want + test word ptr DBLOCK1[bx],ax ; DELWATCH pending deletes + jnz gtd_next ; ie. labels with fat chain +endif + push cx ; we are interested - but does + mov al,ch ; the name match ? + cbw + add ax,offset info_fcb+1 + xor si,si ; we want SI = entry to match and + xchg ax,si ; AL = 0 indicating assumed match + mov cx,11 ; 11 chars in filename + mov di,bx ; ES:DI -> directory entry +match3: + jcxz match4 ; stop if we have done all 11 + repe cmpsb ; compare if 11 bytes the same + je match4 ; skip if all bytes the same + cmp byte ptr 0-1[si],'?' ; else was INFO_FCB byte = '?' + je match3 ; in that case it matches too + inc ax ; else we didn't match (AL<>0) +match4: + pop cx + or al,al ; did we match ? + jnz gtd_next ; no, try for another + mov bx,dirp ; Return (BX) + jmp gtd2 + + +eject +find_hcb: ; find HCB_ for given drive +;-------- +; On Entry: +; CX = cluster we are looking for +; DH = 00 if exact match required +; FF if we want to recyle oldest HCB_ +; On Exit: +; CY set, AX=0 if HCB_ not found +; CY clear ES:BX = offset of HCB_ (moved to head of list) +; (AX/DX trashed, All other regs preserved) +; + + les bx,hashroot ; get our hashing pointer + mov ax,es + or ax,bx ; is hashing enabled ? + jz find_hcb30 + mov dl,adrive ; look for this drive + cmp cx,es:HCB_CLU[bx] ; does cluster match? + jne find_hcb10 ; goto next if not + cmp dl,es:HCB_DRV[bx] ; does drive match? + jne find_hcb10 ; goto next if not +; clc + ret ; we have a match on the 1st one + +find_hcb10: +; no match, so look futher along the chain + mov ax,es:HCB_LINK[bx] ; onto the next entry + test ax,ax ; is there one ? + jz find_hcb20 + xchg ax,bx ; AX = previous entry, BX = current + cmp cx,es:HCB_CLU[bx] ; does cluster match? + jne find_hcb10 ; goto next if not + cmp dl,es:HCB_DRV[bx] ; does drive match? + jne find_hcb10 ; goto next if not +; we have a match, but it's not the first so recycle it + mov dx,es:HCB_LINK[bx] ; get link to the rest of the chain + xchg ax,bx ; BX = previous entry + mov es:HCB_LINK[bx],dx ; unlink ourselves from chain + mov bx,ax ; BX = current entry + xchg ax,word ptr hashroot ; put current entry at the head + mov es:HCB_LINK[bx],ax ; and relink the rest of the chain +; clc + ret + +find_hcb20: +; we have been all along the chain with no luck + xor ax,ax + test dh,dh ; no HCB_ - do we want to recyle ? + jz find_hcb30 ; if not skip + mov es:HCB_CNT[bx],ax ; we need to recycle oldest HCB_ + mov es:HCB_CLU[bx],cx ; so mark as us, but with nothing + mov es:HCB_DRV[bx],dl ; in it +; clc + ret + +find_hcb30: + stc ; return failure + ret + + +eject +;----- +mkhsh: +;----- +; +; entry: SI = 11 byte FCB to convert to hash code +; exit: AX = 1..FFFF is hash code (00/E5 == 0) +; uses: DX +; saves: BX,CX,DI,BP +; +; used for hashing the INFO_FCB & +; directory entries for DOS media + + xor dx,dx ;assume hash code is 0000 + lodsb + cmp al,0E5h ;if deleted file + je mkhsh2 ; or + cmp al,0 ;if virgin entry + je mkhsh2 ;then hash code = 0; + push cx ;else save CX + and al,7fh + mov dh,al ;initialize hash code MSB + mov cx,10 ;involve other 10 characters +mkhsh1: + lodsb ;get next character + rol dx,1 ;rotate hash code by one bit + and al,7fh ;strip top bit off character + xor dl,al ;XOR the character into the hash code + loop mkhsh1 ;repeat for all characters + pop cx ;restore CX + test dx,dx ;test if zero by any chance + jnz mkhsh2 ;skip if non-zero + inc dx ;else force it to 1 +mkhsh2: ;return hash code in AX + xchg ax,dx + ret + + +eject +if DELWATCH + Public fixup_hashing +; +; update hashing for current drive if DELWATCH changes a directory entry +; +fixup_hashing: +;------------- +; On Entry: +; AX = segment of dir buffer +; CX = cluster to fixup (0 = root) +; DI = directory entry index (clipped to cluster if subdir) +; AX:SI-> dir entry (single entry for hashing) +; +; On Exit: +; None +; + push ds + push es + + xor dh,dh ; we only want HCB_ if it's there + push ax ; save seg of dir entry + call find_hcb ; does an HCB_ exist for this entry ? + pop ds ; DS:SI -> entry to hash + jc fixup_ck10 ; not hashed, skip update + cmp di,es:HCB_CNT[bx] ; is this within the hashed entries ? + jae fixup_ck10 ; no, skip the fixup + call mkhsh ; AX = hash code of our entry + + shl di,1 ; DI = offset of hashed entry + lea di,HCB_DATA[bx+di] + stosw ; update hash code for dir entry + +fixup_ck10: + pop es + pop ds + ret ; no +endif + + +eject + +hashsrch: +;-------- +; entry: AX = starting cluster of directory +; exit: AX is possible match index +; + mov dh,0FFh ; we want HCB_ even if it's recycled + xchg ax,cx ; and this block + call find_hcb ; does an HCB_ exist for this entry ? +; mov ax,0 ; assume unhashed search required + jc hashsrch20 ; start one if no hashing +hashsrch10: + mov cx,es:HCB_CNT[bx] ; we have this many entries hashed + jcxz hashsrch30 ; skip if nothing hashed yet + mov ax,hash ; look for this hash code + lea di,HCB_DATA[bx] ; DI = offset of start of search + repne scasw ; try to find a match + jne hashsrch30 ; skip if no match found + lea ax,HCB_DATA+2[bx] ; find word offset of match + xchg ax,di ; return matching index + sub ax,di + shr ax,1 ; make dir offset +hashsrch20: + push ds ! pop es + clc ; we have found it + ret + +hashsrch30: + call rehash_entry ; try and hash another entry + jnc hashsrch10 ; look again if we succeeded + + mov ax,es:HCB_CNT[bx] ; failure, so return # to skip + push ds ! pop es +; stc ; for quicker search + ret + + +rehash_entry: +;------------ +; entry: ES:BX -> HCB +; AX = hash cluster number + + call hash_entries_to_do ; how many entries still to hash ? + jcxz rehash_entry40 ; if we have hashed them all exit + + push dcnt ; save directory count + + mov ax,dcnt ; get previous position + inc ax ; we start looking here + xor dx,dx + div dirperclu ; mask to start of cluster + mul dirperclu + add ax,es:HCB_CNT[bx] ; skip entries we already have + dec ax ; make previous entry BEFORE this + mov dcnt,ax + mov chdblk,0 ; non-sequential access + cmp cx,512/32 ; don't try reading more than 512 bytes + jb rehash_entry20 ; at a time - then with 512 byte secs + mov cx,512/32 ; we only read when we +rehash_entry20: + push es + push bx ; save hash control pointer + push cx ; save # entries to do + push ds ! pop es ; back to small model + xor cx,cx ; return any entry + call gtd_next ; unhashed search + pop cx ; restore # entries to do + pop bx ; restore hash control pointer + pop es + test ax,ax ; anything found + jz rehash_entry30 ; end of directory + xchg ax,si ; else get directory pointer + mov di,es:HCB_CNT[bx] + shl di,1 ; DI -> 1st new entry + lea di,HCB_DATA[bx+di] + push si + call mkhsh ; else calculate hash into AX + stosw ; add it to hash table + inc es:HCB_CNT[bx] ; remember we did + pop si + lodsb ; get 1st byte of hashed entry + test al,al ; is it zero (ie. never used)? + loopne rehash_entry20 ; get all hash codes + jcxz rehash_entry30 ; all done ? + call hash_entries_to_do ; how many entries still to hash ? + add es:HCB_CNT[bx],cx ; we will do them all.. + rep stosw ; zap rest of cluster +rehash_entry30: + pop dcnt ; restore count + mov chdblk,0 ; non-sequential access + clc ; we have new hashing codes + ret ; HCB updated with new cluster + +rehash_entry40: + stc ; cannot hash no more... + ret + +hash_entries_to_do: +;------------------ +; On Entry: +; ES:BX -> HCB_ +; On Exit: +; CX = maximum possible entries we still need to hash for HCB_ +; (All other regs preserved) +; + mov cx,dirinroot ; assume root dir + cmp es:HCB_CLU[bx],0 ; was it ? + je hash_etd10 + mov cx,dirperclu ; subdir, so cluster limit +hash_etd10: + cmp cx,hashmax ; do we support this many ? + jb hash_etd20 ; yes, skip it + mov cx,hashmax ; else limit it to this many +hash_etd20: + sub cx,es:HCB_CNT[bx] ; subtract number we have already done + ret + + + +eject +hshdscrd: +;-------- +; purge hash blocks for physical drive +; On Entry: +; AL = drive to discard (FF = all drives) +; On Exit: +; None (All regs preserved) + + push ds + push bx + lds bx,hashroot ; get root of hash codes +hshdsc1: + test bx,bx + jz hshdsc4 ; all blocks done + cmp al,0FFh ; FF means discard all drives + je hshdsc2 + cmp al,ds:HCB_DRV[bx] ; check if matching drive + jne hshdsc3 +hshdsc2: + mov ds:HCB_DRV[bx],0ffh ; h->hd = 0xff; +hshdsc3: + mov bx,ds:HCB_LINK[bx] ; get next hash code block + jmps hshdsc1 +hshdsc4: + pop bx + pop ds + ret + + +eject + +enlarge_root: +if DELWATCH + mov ah,DELW_FREERD ; lets ask DELWATCH if it can + mov al,adrive ; free a root directory entry + callf ss:fdos_stub ; for this drive + jnc allocdir ; it says it has so try again +endif +allocdir_err: + pop ax ; discard return address + mov ax,ED_MAKE + jmp fdos_error ; return "cannot make dir entry" + + +;-------- +allocdir: ; Called by rename and MAKE +;-------- + call setenddir ; search for first match + mov cx,1 ; return empty fcb + call getdir ; is there an empty fcb? + jz allocdir10 ; if so use that + ret +allocdir10: + call hdsblk ; Are we at the root? + jz enlarge_root ; YES -- Report error(no room) + + ; We are in a subdirectory so enlarge it + ; AX has 1st block of subdirectory NOTE -- AX is never + ; above 'lastcl' on entry. +allocdir20: + cmp ax,lastcl ; Are we at end of subdirectory? + ja allocdir30 ; YES + push ax + call getnblk ; NO -- get next block then + pop bx + jmps allocdir20 + +allocdir30: + push bx ; save last block number + xchg ax,bx ; Get a new block (start from old) + call alloc_cluster + pop bx + jc allocdir_err ; Report Error(no room on disk) + push ax ; save new block + xchg ax,bx + call fixfat ; Update fat (AX,BX) old last block + ; points to new last block + pop ax ; Get new last block + push ax + mov bx,dosfat ; 12 or 16 bit fat + call fixfat ; Update fat (AX,BX) new last block + ; has end of cluster marker + call update_fat ; Write out to disk + pop ax ; Get new last block + call zeroblk ; Zero it out + call setenddir ; Set up for search first + mov cx,1 ; Find empty fcb + jmp getdir ; Can not return with not found error + + END diff --git a/IBMDOS/DISK.A86 b/IBMDOS/DISK.A86 new file mode 100644 index 0000000..d0c31d7 --- /dev/null +++ b/IBMDOS/DISK.A86 @@ -0,0 +1,1153 @@ +; File : $DISK.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; DISK.A86 1.26 94/12/01 10:05:21 +; added attribute support for open/move/unlink during server call +; DISK.A86 1.24 93/11/16 13:46:21 +; Generate critical error on int21/36 (get free space) +; DISK.A86 1.23 93/10/25 21:58:02 +; Tighten up error checks on int21/6C modes (DL bits 0-3 = 3 rejected) +; DISK.A86 1.22 93/10/18 17:40:51 +; fix for >255 open files (PNW Server) +; DISK.A86 1.21 93/09/03 20:28:02 +; Add "no critical errors" support (int 21/6C) +; DISK.A86 1.20 93/08/04 15:15:15 +; Int21/6C allows DH=1 +; DISK.A86 1.19 93/07/22 20:32:12 +; don't check AL on int 21/6c +; DISK.A86 1.18 93/07/22 19:28:02 +; correct bug in extended open/create +; DISK.A86 1.15 93/06/23 04:05:38 +; more int21/6C - we still need no critical errors support +; DISK.A86 1.14 93/06/23 03:00:27 +; fix bug in int21/6C +; DISK.A86 1.13 93/05/07 15:09:29 +; Move delwatch free space adjust call inside the MXDisk +; DISK.A86 1.12 93/03/16 22:33:49 +; UNDELETE support changes +; DISK.A86 1.11 93/03/05 18:10:55 +; Add UNDELETE definition +; ENDLOG +; +; All FCB based PCMODE functions are translated to FDOS function +; calls in this file. +; +; 22 May 87 Support the extended CHMOD function to get/set the +; password mode. +; 28 May 87 Support the Update Handle Count Function +; 5 Nov 87 Remove MAJOR_VER reference from func0D +; 15 Mar 88 Return Attributes in CX and AX +; 3 May 88 Return correct disk size from functions 1B, 1C and 36 +; 17 May 88 Add valid drive check routine used by FUNC29 and FUNC4B +; 30 Jun 88 Call FDOS to build DDSC for INT21/53 +; 18 Aug 88 FUNC67 correctly fill new handle table with 0FFh +; Sorcim ACCPAC Plus +; 27 Sep 88 Return error codes from Read and Write Random. +; 19 Feb 89 Allowing SHARE to be disabled with DR DOS +; 16 May 89 Include Random Record field on func23 (file size) +; 23 May 89 func3F (Read) now allows Ignore on errors (CopyIIpc) +; 11 Sep 89 MSNET Flush hook added +; 20 Sep 89 func3B "d:=" form fills in LDT (func4B support) +; 24 Oct 89 func32 (getdpb) sets top bit of drive on fdos_getdpb +; to indicate free space count not required +; 27 Oct 89 mutilate the code to save space +; 24 Jan 90 valid_drive uses dos_entry, doesn't peek at HDS's +; 8 Feb 90 func_43 updated for new password support +; 27 Feb 90 func57 gives ED_FUNCTION if not get/set (HEADROOM bug) +; 7 Mar 90 Convert to register preserved function calls +; 14 Mar 90 Share func3D_mask bodge move to FDOS +; 28 Sep 90 Return sectors xfered on Int21/27 even if error (CALC.EXE>64k) +; 14 mar 91 add delwatch hook to func36 (disk free space) +; 14 jun 91 correct error codes from func3F during func4B +; 8 aug 91 func3B (chdir) now maintains LDT name for all cases +; 1 oct 91 Valdivar it +; 27 feb 92 func3E returns previous open count +; 3 mar 92 fill in default search attribute in Func3D for future +; 23 mar 92 func67 will now shrink #handles +; + + include pcmode.equ + include fdos.def + include i:doshndl.def + include i:fdos.equ + include i:psp.def + include i:msdos.equ + include i:mserror.equ + include i:redir.equ + +FCB_LEN equ 32 +XFCB_LEN equ FCB_LEN+7 + + +PCM_CODE CSEG BYTE + extrn dbcs_lead:near + extrn dos_entry:near + extrn fdos_nocrit:near + extrn fdos_crit:near, fdos_ax_crit:near + extrn fcbfdos_crit:near + extrn set_retry:near + extrn set_retry_RF:near + extrn error_exit:near + extrn error_ret:near + extrn fcberror_exit:near + + extrn reload_registers:near + extrn reload_ES:near + extrn return_AX_CLC:near + extrn return_BX:near + extrn return_CX:near + extrn return_DX:near + +; ***************************** +; *** DOS Function 0D *** +; *** Disk Reset *** +; ***************************** +; + Public func0D +func0D: + mov FD_FUNC,FD_FLUSH + call fdos_nocrit ; flush buffers + mov ax,0FFFFh + push ax + mov ax,I2F_FLUSH + int 2fh ; magic INT2F flush remote buffers + pop ax + push ss ! pop ds + ret + +; ***************************** +; *** DOS Function 0E *** +; *** Select Disk *** +; ***************************** +; + Public func0E +func0E: +; +; Entry: +; DL == drive to set as default (0 == A:) +; Exit: +; AL == Number of Drives in System (from SYSDAT) +; + mov FD_FUNC,FD_SELECT + xchg ax,dx ; drive in AL + cbw ; make that AX + mov FD_DRIVE,ax + call fdos_nocrit ; ask the FDOS to try to select it + mov al,last_drv ; Return the number of valid drives + ret + +; +; Return with the ZERO flag set if the drive passed in AL is +; valid. This function is used to set the initial AX value +; when a program is loaded. +; +; On Entry:- AL 00 - Default Drive +; 01 to 26 - A: to Z: +; +; On Exit:- ZF If AL referenced a valid drive +; + Public valid_drive +valid_drive: + push dx + mov dl,al ; get drive in DL + dec dl ; make drive zero based + js valid_drive10 ; if current drive always OK + mov ah,MS_DRV_GET + call dos_entry ; get current drive + push ax ; save for later + mov ah,MS_DRV_SET + call dos_entry ; try and select new drive + mov ah,MS_DRV_GET ; if we can select it + call dos_entry ; then it's valid + sub al,dl ; AL = 0 if drive valid + pop dx ; recover old drive + push ax ; save result + mov ah,MS_DRV_SET + call dos_entry ; reset to original drive + pop ax ; recover result +valid_drive10: + pop dx + test al,al ; set ZF if valid drive + ret + +eject +; ***************************** +; *** DOS Function 0F *** +; *** Open File (FCB) *** +; ***************************** +; + Public func0F +func0F: + +; ***************************** +; *** DOS Function 10 *** +; *** Close File (FCB) *** +; ***************************** +; + Public func10 +func10: + +; ***************************** +; *** DOS Function 11 *** +; *** Search First (FCB) *** +; ***************************** +; + Public func11 +func11: + +; ***************************** +; *** DOS Function 12 *** +; *** Search Next (FCB) *** +; ***************************** +; + Public func12 +func12: + +; ***************************** +; *** DOS Function 13 *** +; *** Delete File (FCB) *** +; ***************************** +; + Public func13 +func13: + +; ***************************** +; *** DOS Function 14 *** +; *** Sequential Read (FCB) *** +; ***************************** +; + Public func14 +func14: + +; ***************************** +; *** DOS Function 15 *** +; *** Sequential Write (FCB)*** +; ***************************** +; + Public func15 +func15: + +; ***************************** +; *** DOS Function 16 *** +; *** Create File (FCB) *** +; ***************************** +; + Public func16 +func16: + +; ***************************** +; *** DOS Function 17 *** +; *** Rename File (FCB) *** +; ***************************** +; + Public func17 +func17: + +; ***************************** +; *** DOS Function 21 *** +; *** Random Read (FCB) *** +; ***************************** +; + Public func21 +func21: + +; ***************************** +; *** DOS Function 22 *** +; *** Random Write (FCB) *** +; ***************************** +; + Public func22 +func22: + +; ***************************** +; *** DOS Function 23 *** +; *** File Size (FCB) *** +; ***************************** +; + Public func23 +func23: + +; ***************************** +; *** DOS Function 24 *** +; *** Set Relative Record *** +; ***************************** +; + Public func24 +func24: + +; ***************************** +; *** DOS Function 27 *** +; *** Random Block Read *** +; ***************************** +; + Public func27 +func27: + +; ***************************** +; *** DOS Function 28 *** +; *** Random Block Write *** +; ***************************** +; + Public func28 +func28: +; All FCB function come through here + call set_retry_RF ; Valid to RETRY or FAIL + mov ax,FD_FCB ; FCB file function + xchg ax,FD_FUNC ; recover function number + mov FD_FCBFUNC,ax ; pass FCB function number + mov FD_FCBOFF,dx ; Initialise the FCB Pointer + mov FD_FCBSEG,es + mov FD_FCBCNT,cx ; we may need record count + call fcbfdos_crit ; Execute the function + jc fcb_error ; Check for an Error + mov cx,FD_FCBCNT ; Get the number of records + jmp return_CX ; processed and return in CX +fcb_error: + jmp fcberror_exit ; Use default Error handler + + + +eject +; ***************************** +; *** DOS Function 19 *** +; *** Current Disk *** +; ***************************** + + Public func19 +func19: + mov al,current_dsk ; Get the current logical disk + ret ; and return + + +; ***************************** +; *** DOS Function 1A *** +; *** Set Disk Trans Adr *** +; ***************************** + + Public func1A +func1A: + mov dma_offset,dx ; set the PCMODE DMA Offset + mov dma_segment,es ; and then the DMA Segment + ret + +; ***************************** +; *** DOS Function 1B *** +; *** Def. Disk Info *** +; ***************************** +; + Public func1B +func1B: + +; ***************************** +; *** DOS Function 1C *** +; *** Sel. Disk Info *** +; ***************************** +; + Public func1C +func1C: + call set_retry_RF ; Valid to RETRY or FAIL + xor dh,dh ; Pass the drive requested + call fdos_DISKINFO ; find out about drive + jc fdos_DI_error + + mov cx,es:DDSC_SECSIZE[bx] ; Get the Physical Sector Size + call return_CX ; in bytes + + mov dx,es:DDSC_NCLSTRS[bx] ; Convert the last cluster no + dec dx ; returned in DDSC to maximum + call return_DX ; number of clusters and return + + mov al,es:DDSC_CLMSK[bx] ; get (sectors per cluster)-1 + inc ax ; return sectors per cluster + lea bx,DDSC_MEDIA[bx] ; return address of media byte +f1B1C1F32_common: + push ds + lds di,int21regs_ptr + mov reg_DS[di],es + mov reg_BX[di],bx + pop ds + ret + +; ***************************** +; *** DOS Function 1F *** +; *** Get Default DPB *** +; ***************************** +; + Public func1F +func1F: + +; ***************************** +; *** DOS Function 32 *** +; *** Get Requested DPB *** +; ***************************** +; + Public func32 +func32: + call set_retry_RF ; Valid to RETRY or FAIL + mov dh,80h ; set top bit - free space not needed + call fdos_DISKINFO ; and make the function call + jnc f1B1C1F32_common ; exit using common code +fdos_DI_error: + jmp fcberror_exit ; exit thru FCB error + + +; ***************************** +; *** DOS Function 36 *** +; *** Disk Free Space *** +; ***************************** +; + Public func36 +func36: + call set_retry_RF ; Valid to RETRY or FAIL + xor dh,dh ; clear out DH + call fdos_DISKINFO ; find out about drive + jnc f36_OK ; CY set if we had a problem + push es + push bx + call error_exit ; generate a critical error + pop bx + pop es + mov ax,0FFFFh ; Invalid Drive Return 0FFFFh + jc f36_exit ; No Carry +f36_OK: + mov cx,es:DDSC_SECSIZE[bx] ; Get the Physical Sector Size + call return_CX ; in bytes + + mov dx,es:DDSC_NCLSTRS[bx] ; Convert the last cluster no + dec dx ; returned in DDSC to maximum + call return_DX ; number of clusters + + mov cx,es:DDSC_FREE[bx] ; get number of free clusters +if DELWATCH + add cx,FD_ADJUST ; now add in DELWATCH adjustment +endif + xor ax,ax + mov al,es:DDSC_CLMSK[bx] ; get the sectors per cluster -1 + inc ax ; AX = sectors per cluster + + mov bx,cx + call return_BX ; return free clusters + +f36_exit: + jmp return_AX_CLC + +fdos_DISKINFO: +;------------- +; Called by func1B, func1C, func1F, func32, func36 +; Even number functions have drive in DL +; Odd numbered function use default drive (0) +; + mov ax,FD_DISKINFO ; get information about drive + xchg ax,FD_FUNC ; while getting orginal function # + test al,1 ; is it func1B/func1F ? + jz fdos_DI10 ; if so these use the default + xor dl,dl ; drive so zero DL +fdos_DI10: + mov FD_DRIVE,dx ; drive in DX + call fdos_crit + les bx,FD_DPB ; get the DPB pointer + ret + +eject +; ***************************** +; *** DOS Function 2F *** +; *** Get Disk Trans Adr *** +; ***************************** + + Public func2F +func2F: + les bx,dword ptr dma_offset ; current dma address + push ds + lds di,int21regs_ptr + mov reg_ES[di],es + mov reg_BX[di],bx + pop ds + ret + + +eject +; ***************************** +; *** DOS Function 41 *** +; *** Delete File(s) *** +; ***************************** +; + Public func41 +func41: + cmp ss:remote_call,0 + jne fdos_common41 + mov cl,06h + +; ***************************** +; *** DOS Function 39 *** +; *** Create SubDirectory *** +; ***************************** +; + Public func39 +func39: + +; ***************************** +; *** DOS Function 3A *** +; *** Delete SubDirectory *** +; ***************************** +; + Public func3A +func3A: + +; ***************************** +; *** DOS Function 3B *** +; *** Change SubDirectory *** +; ***************************** +; + Public func3B +func3B: +; ***************************** +; *** DOS Function 4E *** +; *** Find First File *** +; *** DOS Function 4F *** +; *** Find Next File *** +; ***************************** +; + Public func4E +func4E: + Public func4F +func4F: +; Func 4F has no parameters, but using the same routine saves code + +fdos_common41: + call set_retry_RF ; Valid to RETRY or FAIL +; jmps fdos_name + +fdos_name: + mov FD_NAMEOFF,dx ; Initialise Pointer + mov FD_NAMESEG,es + mov FD_ATTRIB,cx ; and attributes + jmp fdos_ax_crit + +eject +; ***************************** +; *** DOS Function 5B *** +; *** Create New File *** +; ***************************** +; + Public func5B +func5B: + +; ***************************** +; *** DOS Function 3C *** +; *** Create a File *** +; ***************************** +; + Public func3C +func3C: + call set_retry_RF ; Valid to RETRY or FAIL + cmp FD_FUNC,MS_X_CREAT ; is it a standard create ? + je f3C_10 + mov FD_FUNC,FD_NEW ; no, create a new file +f3C_10: + mov FD_MODE,DHM_RW ; create as read/write + jmps fdos_name ; go do it + +; ***************************** +; *** DOS Function 3D *** +; *** Open a File *** +; ***************************** +; + Public func3D +func3D: + call set_retry_RF ; Valid to RETRY or FAIL + cmp ss:remote_call,0 + jne funcExtendedOpenCreate + mov cl,06h ; default search mode for local +; jmp funcExtendedOpenCreate ; calls (remote it's in CL) +funcExtendedOpenCreate: +; On Entry: +; FD_FUNC = function to carry out +; ES:DX -> name +; AX = open mode +; CX = file attributes +; + push ax + and al,DHM_SHAREMSK + cmp al,DHM_DENY_NONE ; any funny share bits ? + pop ax + ja open_mode_err + push ax + and al,DHM_RWMSK + cmp al,DHM_RW ; check RW bits are valid + pop ax + ja open_mode_err + mov FD_MODE,ax ; Set Open Mode + jmps fdos_name + +open_mode_err: + mov ax,ED_ACC_CODE ; This is an illegal open mode + jmp error_exit ; return an error + + +; ***************************** +; *** DOS Function 3F *** +; *** Read from Handle *** +; ***************************** +; + Public func3F +func3F: + +; ***************************** +; *** DOS Function 40 *** +; *** Write to a Handle *** +; ***************************** +; + Public func40 +func40: + mov al,OK_RIF ; Valid to RETRY,IGNORE or FAIL + call set_retry + mov FD_BUFOFF,dx + mov FD_BUFSEG,es + mov FD_COUNT,cx + call fdos_handle + mov dx,FD_COUNT + jnc f40_10 ; no error, return # xfered + push FD_HANDLE + push dx ; an error, try critical error + call error_exit ; and if we get back here that + pop dx ; means we Fail/Ignore it + pop bx + jc f40_20 ; are we returning an error ? + push dx ; no, we are ignoring it + xor cx,cx ; CX:DX offset to skip + mov ax,(MS_X_LSEEK*256)+1 ; seek to current+offset + call dos_entry + pop dx ; finally return # we wanted +f40_10: ; to xfer + xchg ax,dx ; AX = return code + jmp return_AX_CLC +f40_20: + ret + +; ***************************** +; *** DOS Function 42 *** +; *** Move R/W Pointer *** +; ***************************** +; + Public func42 +func42: + call set_retry_RF ; Valid to RETRY or FAIL + mov word ptr FD_OFFSET+0,dx + mov word ptr FD_OFFSET+2,cx + mov FD_METHOD,ax + call fdos_handle + jc f42_error ; Do not return the current + mov ax,word ptr FD_OFFSET+0 ; file position if + mov dx,word ptr FD_OFFSET+2 ; an error occurs + call return_DX + jmp return_AX_CLC + +f42_error: + jmp error_exit + +fdos_handle: + mov FD_HANDLE,bx + jmp fdos_crit + +; ***************************** +; *** DOS Function 43 *** +; *** Change File Mode *** +; ***************************** +; +; Concurrent Password Support:- +; +; *WO* *GR* *OW* This is the format of the Password +; P---$RWED$RWED$RWED mode word which is compatible with +; the FlexOS F_PROTECT field. +; *WO* World (Ignored) +; *GR* Group (Ignored) The P flag is only used to designate +; *OW* Owner (Used) that the password is being updated. +; + Public func43 +func43: + call set_retry_RF ; Valid to RETRY or FAIL + mov FD_FLAG,ax ; Requested Attributes ignored + call fdos_name ; if flags are not being set + jc f42_error + call reload_registers ; get back AL + test al,81h + jnz f43_exit + mov cx,FD_ATTRIB + call return_CX ; Return Attribs/Password + xchg ax,cx ; Also in AX +f43_exit: + jmp return_AX_CLC + +; ***************************** +; *** DOS Function 46 *** +; *** Force Dup Handle *** +; ***************************** +; + Public func46 +func46: + xchg bx,cx ; destination handle in BX + mov ah,MS_X_CLOSE ; try to close it but ignore + call dos_entry ; errors as it may be already + xchg bx,cx ; now fall thru to handle func + mov ah,MS_X_DUP2 ; do do the duplicate + +; ***************************** +; *** DOS Function 45 *** +; *** Duplicate Handle *** +; ***************************** +; + Public func45 +func45: + +; ***************************** +; *** DOS Function 3E *** +; *** Close a File *** +; ***************************** +; + Public func3E +func3E: + mov al,OK_FAIL + call set_retry ; Valid to FAIL + mov FD_NEWHND,cx ; (in case it's force dup) +; jmps fdos_ax_handle + +fdos_ax_handle: + mov FD_HANDLE,bx + jmp fdos_ax_crit + +; ***************************** +; *** DOS Function 5C *** +; ***Lock/Unlock File Access*** +; ***************************** +; + Public func5C +func5C: + call set_retry_RF ; Valid to RETRY or FAIL + mov FD_FUNC,FD_LOCK ; Lock/Unlock File + mov word ptr FD_OFFSET+0,dx ; Lock Offset (LOW) + mov word ptr FD_OFFSET+2,cx ; Lock Offset (HIGH) + mov word ptr FD_LENGTH+0,di ; Lock Length (LOW) + mov word ptr FD_LENGTH+2,si ; Lock Length (HIGH) + mov FD_LFLAG,ax ; Lock Type + jmps fdos_ax_handle + +; ***************************** +; *** DOS Function 47 *** +; *** Get Current Dir *** +; ***************************** +; + Public func47 +func47: + call set_retry_RF ; Valid to RETRY or FAIL + mov FD_PATHOFF,si ; Initialise Pointer + mov FD_PATHSEG,es + xchg ax,dx ; drive in AL + cbw ; make that AX + mov FD_DRIVE,ax + jmp fdos_ax_crit ; return garbage in AH (SPJ bug) + +; ***************************** +; *** DOS Function 53 *** +; *** Build DPB from BPB *** +; ***************************** +; +; This function takes the BPB at DS:SI and builds a DDSC at ES:BP +; + Public func53 +func53: + call set_retry_RF ; Valid to RETRY or FAIL + mov FD_BPBOFF,si ; Segment and Offset of BPB + mov FD_BPBSEG,es + mov FD_DDSCOFF,bp ; Segment and Offset of DDSC + call reload_ES + mov FD_DDSCSEG,es + jmp fdos_nocrit +; +; ***************************** +; *** DOS Function 56 *** +; *** Rename/Move a File *** +; ***************************** +; + Public func56 +func56: + call set_retry_RF ; Valid to RETRY or FAIL + mov FD_NNAMEOFF,di ; New FileName + push es + call reload_ES ; callers ES:DI + mov FD_NNAMESEG,es ; point to new filename + pop es + mov FD_ONAMEOFF,dx ; Old FileName + mov FD_ONAMESEG,es + cmp ss:remote_call,0 + jne func56_10 + mov cl,17h +func56_10: + mov FD_ATTRIB,cx + jmp fdos_crit + +; ***************************** +; *** DOS Function 57 *** +; *** Get/Set File Time *** +; ***************************** +; + Public func57 +func57: + call set_retry_RF ; Valid to RETRY or FAIL + mov FD_DATE,dx + mov FD_TIME,cx + mov FD_SFLAG,ax + cmp al,1 ; allow get/set only + mov ax,ED_FUNCTION ; all else fails horribly + ja f57_error + call fdos_handle + jc f57_error + call reload_registers + test al,al + jnz f57_exit + mov cx,FD_TIME + call return_CX ; return TIME in CX + mov dx,FD_DATE + jmp return_DX ; and DATE in DX + +f57_exit: + ret + +f57_error: + jmp error_exit + +; ***************************** +; *** DOS Function 5A *** +; *** Create Unique File *** +; ***************************** +; + Public func5A +func5A: + mov ax,ED_ACCESS ; assume we will have an error + test cx,DA_FIXED ; because of silly attributes + jnz func5A_40 ; did we ? + mov si,dx ; find end of pathname + xor ax,ax ; no previous char +func5A_10: + xchg ax,bx ; BL = previous char + lods es:al ; get next char + test al,al ; is it the end of the string? + jz func5A_20 + call dbcs_lead ; is it a KANJI char? + jnz func5A_10 + inc si ; skip 2nd char of pair + jmps func5A_10 +func5A_20: + dec si ; SI -> NUL + cmp bl,'\' ; was last char a '\' ? + je func5A_30 + cmp bl,'/' ; (or a '/' for unix freaks) + je func5A_30 + mov es:byte ptr [si],'\' ; append a '\' to name + inc si +func5A_30: +; Here ES:DX -> start of name, ES:SI -> position to append ,0 +; CX = attribute for file. +; We generate a unique name based upon the time and date - if this already +; exists we keep retrying knowing the number of files is finite and we must +; succeed eventually + push cx ! push dx ! push si ; append a unique'ish name + call func5A_append_unique_name + pop si ! pop dx ! pop cx + mov ah,MS_X_MKNEW ; try to create unique file + call dos_entry + jnc func5A_50 ; exit if we succeeded + mov es:byte ptr [si],0 ; else forget extention + cmp ax,ED_EXISTS ; we only retry if it already exists + je func5A_30 +func5A_40: + jmp error_exit ; return error to caller +func5A_50: + jmp return_AX_CLC ; return handle to caller + +func5A_append_unique_name: +;------------------------- +; On Entry: +; ES:DX -> start of name +; ES:SI -> position to append ,0 +; CX = attribute for file. +; On Exit: +; None +; +; We append a unique 8 character filename to this based upon the current +; date/time. + push si + mov ax,120dh + int 2fh ; get date/time in AX & DX + pop di + add ax,unique_name_seed ; randomise the date otherwise we would + inc unique_name_seed ; have one second wait between names + call func5A_app_AX ; store 4 ascii bytes + xchg ax,dx ; was DX = time + call func5A_app_AX ; store 4 ascii bytes + xor ax,ax + stosb ; and a terminating NUL + ret + +func5A_app_AX: +; On Entry AX = word, ES:DI -> string +; Store 4 ASCII chars at ES:DI, based upon value in AX + call func5A_app_AL ; do low byte, falling thru to do high +func5A_app_AL: + call func5A_app_NIB ; low nibble, falling thru for high +func5A_app_NIB: + push ax + and al,0fh ; mask out a nibble + add al,'A' ; make it ASCII character + stosb ; plant the string + pop ax + mov cl,4 + shr ax,cl ; shift nibble + ret + + +; ***************************** +; *** DOS Function 60 *** +; ***Perform Name Processing*** +; ***************************** +; +; DS:SI point to a source string which contains a relative path +; specification ES:DI points to a buffer which is at least 80 +; bytes longer than the source string. +; +; The carry flag is set and AX contains an error code if the +; source string is mal formed. This function is used by the +; Ryan-McFarland COBOL compiler. +; + Public func60 +func60: + call set_retry_RF ; Valid to RETRY or FAIL + mov FD_FUNC,FD_EXPAND ; Expand a relative Path + mov FD_ONAMEOFF,si ; Initialise Source Pointer + mov FD_ONAMESEG,es + mov FD_NNAMEOFF,di ; Initialise Destination + call reload_ES ; pointer + mov FD_NNAMESEG,es + jmp fdos_crit + +; ***************************** +; *** DOS Function 67 *** +; *** Set/Handle Count *** +; ***************************** +; +; We impose a minimum of 20 handles regardless of what the caller +; requests. If the request is <=20 we use the default handle table in +; the PSP, else we allocate a memory block for the new table. +; If the old handle table was in a memory block (ie. zero offset) we +; will free that block up afterwards. +; When shrinking the handle count the error ED_HANDLE will be given if +; open files would have been lost. +; + + Public func67 +func67: + push ds + mov ds,current_psp ; DS -> current PSP blk + cmp bx,20 ; force to minimum value of 20 + jae f67_10 + mov bx,20 ; never have less than 20 handles +f67_10: + + mov cx,ds:PSP_XFNMAX ; we have this many handles + sub cx,bx ; are we growing ? + jbe f67_20 ; if shrinking make sure none open + les di,ds:PSP_XFTPTR ; point to existing handle table + lea di,[di+bx] ; point to 1st handle we will lose + mov al,0FFh ; they must all be closed + repe scasb ; or we fail + mov ax,ED_HANDLE ; fail if we are in danger of losing + jne f67_error ; open handles +f67_20: + + push bx ; save # of handles wanted + push ds ! pop es + mov di,offset PSP_XFT ; ES:DI -> new handle table + cmp bx,20 ; if we are setting to the + je f67_30 ; default size + add bx,15 ; calculate memory required + mov cl,4 ! shr bx,cl ; num of paragraphs required + xor di,di ; offset will be zero + mov ah,MS_M_ALLOC ; allocate the memory + call dos_entry + mov es,ax ; ES:DI -> new handle table +f67_30: + pop bx ; BX = # handles wanted + jc f67_error ; ES:DI -> new handle table + + mov cx,bx ; CX = new # handles + xchg cx,ds:PSP_XFNMAX ; Update the Handle Count + + mov si,di ; Update the Table Offset + xchg si,ds:PSP_XFTOFF + mov ax,es + xchg ax,ds:PSP_XFTSEG ; Update the Table Segment + mov ds,ax ; DS:SI -> old handle table + ; ES:DI -> new handle table + ; CX = # old handles to copy + ; BX = # new handles desired + + sub bx,cx ; BX = # extra "closed" handles + jae f67_40 ; negative if we are shrinking + add cx,bx ; CX = # handles we inherit + xor bx,bx ; BX = no extra "closed" handles +f67_40: + + push si ; save offset old handle table + rep movsb ; Copy the existing Handles + pop si ; SI = offset old handle table + + mov al,0FFh ; AL = unused handle + mov cx,bx ; mark extra handles as unused + rep stosb ; mark as unused + + test si,si ; do we have memory to free ? + jnz f67_50 + mov ah,MS_M_FREE + call dos_entry ; free up old handle table DMD +f67_50: + pop ds + jmp return_AX_CLC ; clear carry on return + +f67_error: + pop ds ; restore DS + jmp error_exit ; and return error AX to caller + +; ***************************** +; *** DOS Function 68 *** +; *** Commit File *** +; ***************************** +; + Public func68 +func68: + call set_retry_RF ; Valid to RETRY or FAIL + mov FD_FUNC,FD_COMMIT ; Close a File Handle + jmp fdos_handle + + +; ***************************** +; *** DOS Function 6C *** +; *** Extended Open *** +; ***************************** +; + + Public func6C +func6C: + mov al,OK_RF ; Valid to RETRY or FAIL + test bh,20h ; should we allow critical errors ? + jz f6C10 + or al,NO_CRIT_ERRORS ; no, so remember that +f6C10: + call set_retry + mov ax,ED_FUNCTION ; assume an illegal action code + test dx,not 0113h ; now check for sensible bits + jnz f6C_error + inc dx + test dl,4 ; also reject bits 0-3 = 3 + jnz f6C_error + dec dx + + xchg ax,si ; ES:AX -> name + xchg ax,dx ; AX = action, ES:DX -> name + xchg ax,bx ; AX = open mode, BX = action + + test bl,010h ; should we create if not there ? + jz f6C_open ; no, skip the attempt at make new + + and ah,(DHM_COMMIT+DHM_NOCRIT)/100h + mov FD_FUNC,FD_NEW ; create only if not there + call funcExtendedOpenCreate ; try to open/create the file + + mov cx,2 ; CX = file created + jnc f6C_exit ; return this if we succeeded + +f6C_open: + call reload_registers ; all registers as per entry + xchg ax,si ; ES:AX -> name + xchg ax,dx ; AX = action, ES:DX -> name + xchg ax,bx ; AX = open mode, BX = action + push bx ; save action + and ah,(DHM_COMMIT+DHM_NOCRIT)/100h + mov FD_FUNC,MS_X_OPEN ; try an open an existing file + call funcExtendedOpenCreate + pop bx ; recover action + jc f6C_error ; return error if we can't open file + + mov cx,1 ; CX = file opened + test bl,001h ; should we open if it exists ? + jnz f6C_exit ; yes, return the handle + + xchg ax,bx ; BX = handle, AX = action + test al,002h ; should we replace the file ? + mov ax,ED_EXISTS ; if not close and return error + jz f6C_close_on_error + mov ah,MS_X_WRITE + xor cx,cx ; write zero bytes to truncate file + call dos_entry + jc f6C_close_on_error ; on error AX = error code, return it + xchg ax,bx ; AX = handle + mov cx,3 ; CX = file replaced +f6C_exit: + jmp return_CX ; return CX to caller + +f6C_close_on_error: +; File exits, but open should be failed (error code in AX) + push ax + mov ah,MS_X_CLOSE + call dos_entry ; close that file + pop ax +f6C_error: + jmp error_exit ; generate critical error + + +PCMODE_DATA DSEG WORD + extrn current_psp:word + extrn current_dsk:byte + extrn dma_offset:word + extrn dma_segment:word + extrn int21regs_ptr:dword + extrn last_drv:byte + extrn remote_call:word +if DELWATCH + extrn fdos_stub:dword +endif + +GLOBAL_DATA dseg word +; When creating unique files we use the date/time to make the name. +; We add this seed value to "randomise" things, INCing on failure so the next +; attempt usually succeeds. + +unique_name_seed dw 0 ; so we don't have to wait 1 second + +end diff --git a/IBMDOS/DOSHNDL.DEF b/IBMDOS/DOSHNDL.DEF new file mode 100644 index 0000000..d4f2b50 --- /dev/null +++ b/IBMDOS/DOSHNDL.DEF @@ -0,0 +1,122 @@ +; File : $DOSHNDL.DEF$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG + +DCNTRL_DSADD equ dword ptr 0000h +DCNTRL_DSOFF equ word ptr 0000h +DCNTRL_DSSEG equ word ptr 0002h +DCNTRL_COUNT equ word ptr 0004h +DCNTRL_LEN equ 6 + +DHNDL_COUNT equ word ptr 00h ; 00 - Usage Count +DHNDL_MODE equ word ptr 02h ; 02 - File Mode + +DHM_FCB equ 8000h ; marks as FCB +DHM_COMMIT equ 4000h ; auto-commit file +DHM_NOCRIT equ 2000h ; no critical errors +DHM_LOCAL equ 10000000b ; file is not inherited +DHM_SHAREMSK equ 01110000b ; sharing bits +DHM_COMPAT equ 00000000b +DHM_DENY_ALL equ 00010000b ; exclusive - deny all +DHM_DENY_WRITE equ 00100000b +DHM_DENY_READ equ 00110000b +DHM_DENY_NONE equ 01000000b +DHM_RWMSK equ 00001111b ; read write bits +DHM_RW equ 00000010b ; file opened read/write +DHM_WO equ 00000001b ; file opened write only +DHM_RO equ 00000000b ; file opened read only + +; +; 01h to 03h To be Determined +; +DHNDL_DATRB equ byte ptr 04h ; Disk attribute byte +DHNDL_ATTR equ byte ptr 05h ; Attribute Byte +DHNDL_WATTR equ word ptr 05h ; Attribute Word + +DHAT_REMOTE equ 8000h ; set if file remote +DHAT_TIMEOK equ 4000h ; set if timestamp up to date +DHAT_LOCAL equ 1000h ; file is not inherited +DHAT_NETPRN equ 0800h ; device is networked printer +DHAT_DEV equ 0080h ; device/file bit +DHAT_READY equ 0040h ; ready/not ready bit +DHAT_CLEAN equ 0040h ; this bit CLEAR if dirty +DHAT_BIN equ 0020h ; raw/cooked bit +DHAT_DRVMSK equ 001Fh ; drive in bottom bits +DHAT_CLK equ 0008h ; -reserved- +DHAT_NUL equ 0004h ; handle is null device +DHAT_COT equ 0002h ; handle is console output device +DHAT_CIN equ 0001h ; handle is console input device + +DHNDL_DEVPTR equ dword ptr 07h ; 07 - pointer to device +DHNDL_DEVOFF equ word ptr 07h ; 07 - offset of device +DHNDL_DEVSEG equ word ptr 09h ; 09 - segment of device +DHNDL_BLK1 equ word ptr 0Bh ; 0B - first cluster in file +DHNDL_TIME equ word ptr 0Dh ; 0D - file time stamp +DHNDL_DATE equ word ptr 0Fh ; 0F - file date stamp +DHNDL_SIZE equ dword ptr 11h ; 11 - file length +DHNDL_SIZELO equ word ptr 11h +DHNDL_SIZEHI equ word ptr 13h +DHNDL_POS equ dword ptr 15h ; 15 - current file position +DHNDL_POSLO equ word ptr 15h +DHNDL_POSHI equ word ptr 17h +DHNDL_IDX equ word ptr 19h ; 19 - relative cluster within file of last read +DHNDL_DBLK equ word ptr 1Bh ; 1B - cluster # of dir entry +DHNDL_DCNTHI equ byte ptr 1Eh ; 1E - dir offset # within cluster +DHNDL_DCNTLO equ byte ptr 1Fh ; 1F - dir offset # within cluster +DHNDL_NAME equ byte ptr 20h ; 20 - File/Device Name +DHNDL_EXT equ byte ptr 28h ; 28 - File extension +DHNDL_SFT equ dword ptr 2Bh ; 2B - pointer to previous SFT +DHNDL_UID equ word ptr 2Fh ; 2F - Owning Machine ID +DHNDL_PSP equ word ptr 31h ; 31 - Owning PSP +DHNDL_SHARE equ word ptr 33h ; 33 - Offset of sharing record +DHNDL_BLK equ word ptr 35h ; 35 - absolute cluster of last read + ; 37 - dword reserved for IFS +DHNDL_LEN equ 3Bh + +; With DOS 3 structures _DBLK is a 16 bit + + +; Logical Drive Table format +LDT_NAME equ byte ptr 00h ; 00 - Ascii Name field +LDT_FLAGS equ word ptr 43h ; 43 - Flag field +LDT_PDT equ dword ptr 45h ; 45 - PDT for this drive +LDT_BLK equ word ptr 49h ; 49 - directory sector +LDT_ROOT equ word ptr 4bh ; 4B - virtual block root +LDT_DRV equ byte ptr 4dh ; 4D - physical drive +LDT_ROOTLEN equ word ptr 4fh ; 4F - Length of root portion +LDT_LEN equ 58h + +LFLG_NETWRKD equ 8000h +LFLG_PHYSICAL equ 4000h +LFLG_JOINED equ 2000h +LFLG_SUBST equ 1000h diff --git a/IBMDOS/DOSMEM.A86 b/IBMDOS/DOSMEM.A86 new file mode 100644 index 0000000..8d36943 --- /dev/null +++ b/IBMDOS/DOSMEM.A86 @@ -0,0 +1,521 @@ +; File : $DOSMEM.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; $Log$ +; DOSMEM.A86 1.13 94/12/01 10:05:21 +; now freeing UMBs also during program termination +; DOSMEM.A86 1.12 93/07/20 22:46:25 +; dmd_upper_root defaults to FFFF +; DOSMEM.A86 1.10 93/06/18 21:00:11 +; Remove historic CDOS comment +; ENDLOG +; + include pcmode.equ + include i:msdos.equ + include i:mserror.equ + +BEST_FIT equ 01h ; allocate BEST match memory block +LAST_FIT equ 02h ; allocate LAST matching memory block +UPPER_FIT equ 80h ; preferably allocate from upper memory +UPPER_ONLY_FIT equ 40h ; only allocate from upper memory + +FIRST_FIT equ 04h ; we use this internally... + +PCM_CODE CSEG BYTE + extrn error_exit:near ; Standard Error Handler + extrn return_AX_CLC:near + extrn return_BX:near + extrn reload_ES:near + extrn toupper:near + +; ***************************** +; *** DOS Function 48 *** +; *** Allocate Memory Block *** +; ***************************** +; + Public func48 +func48: ; bx = request size + callf lock_tables ; lock global tables + call search_mem ; look for block bx or bigger + jc memory_avbl_error ; skip on error + test mem_strategy,LAST_FIT ; is it last fit ? + jz f48_10 ; no, use from begining + mov ax,cx ; work out how much we have + sub ax,bx ; to leave free + je f48_10 + dec ax + mov bx,ax + call make_dmd ; allocate this DMD as free + mov bx,cx ; real block is the next one +f48_10: + mov ax,current_psp ; Change the Owner + mov DMD_PSP,ax ; we now own this block + + push es + call make_dmd ; make new DMD for allocated mem + pop ax + inc ax ; return starting segment + jmps memory_exit ; unlock global tables + + +; ***************************** +; *** DOS Function 49 *** +; *** Free Memory Block *** +; ***************************** +; + Public func49 +func49: + callf lock_tables ; lock global tables + call get_dmd ; es -> dmd + jc memory_error ; skip if block invalid + mov ax,DMD_PSP ; get owner field + cmp ax,dmd_owner + mov ax,es ; return DMD address in AX + jb func49_10 + mov dx,dmd_address ; nothing below this block get's freed + cmp ax,dx ; should we free it ? + jb func49_20 ; no, give it a new owner +func49_10: + xor dx,dx ; yes, owner = 0 means free block +func49_20: + mov DMD_PSP,dx ; free/set new owner +; jmps memory_exit + +; centralised exit point to unlock system tables + +memory_exit: +;----------- +; On Entry: +; AX = return value +; On Exit +; None +; + callf unlock_tables ; unlock global tables + jmp return_AX_CLC ; return DMD address + +memory_avbl_error: + mov bx,cx + call return_BX ; return biggest block available +memory_error: + callf unlock_tables ; unlock global tables + mov locus,LOC_MEMORY + jmp error_exit ; Jump to error handler + + +; ***************************** +; *** DOS Function 4A *** +; *** Alter Memory Block *** +; ***************************** +; + Public func4A +func4A: + callf lock_tables ; lock global tables + call get_dmd ; es -> dmd + jc memory_error ; skip if block invalid + + push DMD_LEN ; save the current DMD length + call merge_mem ; pick up unallocated blocks + pop ax ; return original DMD length + jc memory_error ; if dmd's destroyed + + mov ax,ED_MEMORY ; assume insufficient mem + mov cx,DMD_LEN ; cx = available size + cmp cx,bx ; if avail < req, then + jb memory_avbl_error ; return maximum possible + + mov ax,current_psp ; Force this block to be owned by the + mov DMD_PSP,ax ; current PSP. MACE Utilities + + call make_dmd ; new block on top + call reload_ES + mov ax,es + jmps memory_exit + +; ***************************** +; *** DOS Function 58 *** +; *** Get/Set Alloc Strategy*** +; ***************************** +; +; On Entry:- AL == 0 Get Allocation Strategy +; AL == 1 Set Allocation Strategy +; AL == 2 Get Upper Memory Link +; AL == 3 Set Upper Memory Link + Public func58 + +func58: + callf lock_tables ; lock global tables + cmp al,3 + ja f58_error ; Range Check Sub-Function + cbw ; AH = 0 + mov si,ax + add si,si ; SI = word offset of sub-function + call cs:f58_tbl[si] ; execute the sub-function + jnc memory_exit ; return the result + jmps memory_error ; or the error + + +f58_error: + mov ax,ED_FUNCTION + jmps memory_error + +f58_tbl dw f58_get_strategy + dw f58_set_strategy + dw f58_get_link + dw f58_set_link + +f58_get_strategy: +; mov ah,0 ; AX = subfunction = 0-3 + mov al,mem_strategy +; clc + ret + +f58_set_strategy: + mov ah,MS_M_STRATEGY + mov mem_strategy,bl +; clc + ret + +f58_get_link: + mov ah,MS_M_STRATEGY + mov al,dmd_upper_link +; clc + ret + +f58_set_link: + mov ax,ED_FUNCTION ; return function not implemented + mov cx,dmd_upper_root ; if no upper memory chain + inc cx ; CX = FFFF + stc + jcxz f58_set_link20 + dec cx + mov dmd_upper_link,bl ; set link field + mov ax,dmd_root ; now find dmd before upper memory root + mov dl,IDM ; assume we want to link + test bl,bl ; do we want to link/unlink UMBs? + jnz f58_set_link10 + mov dl,IDZ ; no, we want to unlink +f58_set_link10: + mov es,ax ; point to DMD + call check_dmd_id ; stop if id is invalid + jc f58_set_link20 ; and return an error + push es + call next_dmd ; does the next DMD match our + pop es + cmp ax,cx ; upper memory chain ? + jne f58_set_link10 + mov DMD_ID,dl ; set appropriate link type + mov ax,(MS_M_STRATEGY*256)+3; return AX unchanged +; clc +f58_set_link20: + ret + + + + +eject +;**************************************** +;* * +;* Memory Function Subroutines * +;* * +;**************************************** +; +; FREE_ALL takes the PSP passed in the BX register and free's all +; memory associated with that PSP. +; +; entry: bx = requested PSP +; +; exit: +; + Public free_all +free_all: + mov es,dmd_root ; es -> first dmd + +free_all_loop: + call check_dmd_id ; if block is invalid + jc free_all_fail ; then quit now + + mov dl,al ; dl = id code + cmp DMD_PSP,bx ; if block is owned by another + jnz free_all_next ; then check next + + and DMD_PSP,0 ; Free this partition + +free_all_next: + push es + call next_dmd ; es -> next block up + pop ax + cmp dl,IDM ; if previous block wasn't last + jz free_all_loop ; then keep going + cmp dmd_upper_root,ax + jbe free_all_end + mov ax,dmd_upper_root ; free UMBs as well + cmp ax,-1 ; if UMB head is valid + mov es,ax + jne free_all_loop +free_all_end: + xor ax,ax ; Otherwise Stop + +free_all_fail: + ret + +; +; SET_OWNER allows the OWNING PSP to specify the new owner of +; the partition. An error is returned if an incorrect partition address +; is given or the partition is not owned by the current PSP. +; +; Entry:- AX == New PSP +; BX == Partition Start +; +; Exit:- +; no carry AX == Unknown +; carry AX == Error Code +; + Public set_owner +set_owner: + push es + dec bx + mov es,bx ; ES points at DMD (We Hope) + xchg ax,bx ; Save the New PSP address in BX + call check_dmd_id ; Check for a valid DMD + jc s_o20 + mov ax,current_psp + cmp ax,DMD_PSP ; Check the Current PSP owns the memory + jnz s_o10 + mov DMD_PSP,bx ; Set the new owner and return + jmps s_o20 + +s_o10: + mov ax,ED_BLOCK + stc +s_o20: + pop es + ret + +; +; Search for a free memory block at least as big as bx +; entry: bx = requested size +; success exit: cf clear, es -> dmd +; cx = block size +; failure exit: cf set, ax = error code +; cx = biggest block available + +search_mem: + mov ax,ED_DMD ; assume bad DMD chain + mov cx,dmd_root ; start at the bottom + jcxz search_mem_exit + mov es,cx ; lets clean up memory list + or mem_strategy,FIRST_FIT ; grab 1st block we come to +search_mem_init: + xor si,si ; si = max mem available + mov di,0FFFFh ; di = size of candiate (FFFF=none) + ; dx = dmd of candidate +search_mem_loop: + call check_dmd_id ; if block is invalid + jc search_mem_exit ; then quit now + + cmp DMD_PSP,0 ; if block is owned + jnz search_mem_next ; then check another + + call merge_mem ; group with unallocated blocks + + mov ax,es ; AX = current DMD + mov cx,DMD_LEN ; cx = block length + + cmp cx,si ; is it the biggest block we + jb search_mem40 ; have found so far ? + mov si,cx ; if so then save the new size +search_mem40: + + cmp cx,bx ; if it's not long enough + jb search_mem_next ; then try the next block + + test mem_strategy,FIRST_FIT+LAST_FIT + jnz search_mem50 ; grab this block ? + + test mem_strategy,BEST_FIT ; if BEST FIT then we only save this + jz search_mem_next ; candidate if the previous + cmp cx,di ; candidate was bigger + jae search_mem_next +search_mem50: + mov dx,es ; save this DMD candidate + mov di,cx ; along with it's length + and mem_strategy,not FIRST_FIT +search_mem_next: + call search_next_dmd ; try for another DMD + mov ax,ED_MEMORY ; assume insufficient mem + jc search_mem_exit ; stop if it's true + + mov ax,es + cmp ax,dmd_upper_root ; if we reach the dmd upper root + jne search_mem_loop ; then we have a special case + or mem_strategy,FIRST_FIT ; grab 1st high memory block we find + test mem_strategy,UPPER_ONLY_FIT + jnz search_mem_init ; upper only is another special case + jmps search_mem_loop + +search_mem_exit: + and mem_strategy,not FIRST_FIT + mov cx,di ; DX&DI contain our best candidate + inc di ; if DI=FFFF then we don't have one + je search_mem_bad ; else we return with CX = size + mov es,dx ; and ES = DMD + clc ; clear the error flag + ret + +search_mem_bad: + mov cx,si ; no allocation made, so return +search_mem_error: ; biggest block and flag the error + stc + ret + +search_next_dmd: +; On Entry: +; ES = current DMD +; On Exit: +; ES = AX = next DMD +; DX/DI preserved +; + cmp DMD_ID,IDM ; do we have any more blocks ? + jne search_mem_error ; no, return CY set +; jmp next_dmd ; else try next DMD + +; Point to next DOS Memory Descriptor (dmd) in the chain +; entry: es -> current dmd +; exit: es -> next dmd + +next_dmd: + mov ax,es + add ax,DMD_LEN + inc ax ; allow for dmd itself + mov es,ax + ret + +; Increase the size of the current mem block +; by gobbling all adjacent unallocated blocks +; entry: es -> dmd +; exit: cf = 1, al = 7 if chain is broken +; ES,SI,DI,DX,BX preserved + +merge_mem: + push es + cmp DMD_ID,IDM ; if no more dmd's + jnz merge_mem_done ; then just quit + + call next_dmd + call check_dmd_id ; if id is invalid + jc merge_mem_quit ; then return an error + + cmp DMD_PSP,0 ; if next dmd is owned + jnz merge_mem_done ; then done + + mov cx,DMD_LEN ; if free, grab its length + pop es ; restore base dmd + + mov DMD_ID,al ; use next's id (in case of last) + inc cx + add DMD_LEN,cx ; add new memory to base + jmps merge_mem ; and try again + +merge_mem_done: + clc ; clear error flag +merge_mem_quit: + pop es ; restore base dmd + ret ; with cf and error flag + + +; If needed, create a new dmd on top of allocated memory +; entry: es -> current block +; bx = requested block size +; cx = current block size + +make_dmd: + cmp bx,cx ; if request and size match + jz make_dmd_done ; then that's all we need + + mov dl,DMD_ID ; get current block id + mov DMD_LEN,bx ; else shrink this block + mov DMD_ID,IDM ; not the last now + call next_dmd + mov DMD_ID,dl ; our old id for the new dmd + mov DMD_PSP,0 ; new block is free + sub cx,bx + dec cx + mov DMD_LEN,cx ; length is whatever is left + +make_dmd_done: + ret + +; Get passed value of memory block +; exit: es -> dmd +; al = DMD_ID, cf cleared if valid +; al = 7, cf set if invalid + +get_dmd: + call reload_ES + mov ax,es + dec ax ; back up to dmd + mov es,ax +; jmps check_dmd_id ; fall through + +; Check first byte in the dmd for a valid id code +; entry: es -> dmd +; exit: al = DMD_ID, cf cleared if valid +; al = 7, cf set if invalid + + Public check_dmd_id + +check_dmd_id: + mov al,DMD_ID + cmp al,IDM ; if not last + jz check_dmd_done ; then good + cmp al,IDZ ; if last + jz check_dmd_done ; also good + + mov ax,ED_BLOCK ; Invalid DMD +check_dmd_error: + stc ; flag the error +check_dmd_done: + ret + + +PCMODE_DATA DSEG + + extrn lock_tables:dword + extrn unlock_tables:dword + + extrn dmd_address:word ; don't free DMD's with segment under this value + extrn dmd_owner:word ; don't free DMD's with owner under this value + extrn dmd_upper_root:word + extrn dmd_upper_link:byte + extrn current_psp:word + extrn locus:byte + extrn mem_strategy:byte + extrn dmd_root:word + + end diff --git a/IBMDOS/DRIVER.EQU b/IBMDOS/DRIVER.EQU new file mode 100644 index 0000000..7497087 --- /dev/null +++ b/IBMDOS/DRIVER.EQU @@ -0,0 +1,60 @@ +; File : $DRIVER.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +; Device driver header offsets. + + +DH_NEXT equ es:dword ptr 0 ; Dword Pointer to Next DEV +DH_NEXTOFF equ es:word ptr 0 ; Offset of next device +DH_NEXTSEG equ es:word ptr 2 ; Segment of next device +DH_ATTRIB equ es:word ptr 4 ; device attribute bits +DH_STRATEGY equ es:word ptr 6 ; offset of strategy entry +DH_INTERRUPT equ es:word ptr 8 ; offset of interupt entry +DH_NAME equ es:byte ptr 10 ; 8-BYTE device name + +DA_CHARDEV equ 8000h ; 1=character device, 0=block device +DA_IOCTL equ 4000h ; device supports IOCTL string I/O +DA_NONIBM equ 2000h ; dosen't require FAT for login +DA_OTILBSY equ 2000h ; supports "output until busy" +DA_REMOVE equ 0800h ; supports "removable media" check +DA_QUERY equ 0080h ; supports query ioctl +DA_GETSET equ 0040h ; supports 3.2 level functionality +DA_SPECIAL equ 0010h ; fast console ouput via INT 29h +DA_ISCLK equ 0008h ; device is current clock device +DA_ISNUL equ 0004h ; device is NUL device (reserved) +DA_BIGDRV equ 0002h ; supports > 65535 sector per drive +DA_ISCOT equ 0002h ; device is standard output device +DA_ISCIN equ 0001h ; device is standard input device + +FASTCON_INT equ 29h ; fast console output interrupt + diff --git a/IBMDOS/ERROR.A86 b/IBMDOS/ERROR.A86 new file mode 100644 index 0000000..cc4e3b9 --- /dev/null +++ b/IBMDOS/ERROR.A86 @@ -0,0 +1,469 @@ +; File : $ERROR.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; $Log$ +; ERROR.A86 1.17 94/12/02 11:01:03 +; added logical error entry +; ERROR.A86 1.16 93/11/26 15:51:29 +; Update char_error so ES:SI -> device driver header itself +; ERROR.A86 1.14 93/09/09 22:36:26 +; Int 21/59 uses error stack (for benefit of Lantastic) +; ERROR.A86 1.13 93/09/03 20:28:11 +; Add "no critical errors" support (int 21/6C) +; ENDLOG +; +; This file contains the Error handling routines for PCMODE +; When a function encounters an error it jumps to the ERROR_EXIT +; function which will process the error consistantly. FCB_ERROR_EXIT +; is a special case of ERROR_EXIT where the error code is not returned +; directly to the user but is still saved for func59 +; + + include pcmode.equ + include fdos.def + include i:msdos.equ + include i:mserror.equ + include i:psp.def + include i:char.def + include i:reqhdr.equ + +; +ERR_TBL_CODE equ byte ptr 0 ; Error Code in Table +ERR_TBL_CLASS equ byte ptr 1 ; Error Class entry in Table +ERR_TBL_ACTION equ byte ptr 2 ; Error Action entry in Table +ERR_TBL_LOCUS equ byte ptr 3 ; Locus entry in table +ERR_TBL_LEN equ 4 ; 4 bytes per entry +; +PCM_CODE CSEG BYTE + extrn get_dseg:near + extrn do_int24:near + extrn reload_registers:near + extrn return_AX_CLC:near +; +; ***************************** +; *** DOS Function 59 *** +; *** Get Extended Error *** +; ***************************** +; + Public func59 + +func59: + les di,error_dev ; Return device driver address + mov bh,error_class ; return the Error Class + mov bl,error_action ; the Action Code + mov ch,error_locus ; the Locus Code + mov ax,error_code ; the Error Code + + lds si,int21regs_ptr ; point to user stack + mov reg_ES[si],es + mov reg_DI[si],di + mov reg_BX[si],bx + mov reg_CX[si],cx + push ss ! pop ds + jmp return_AX_CLC + +eject +; On Entry:- AX == Internal Error Number +; +; On Exit:- None +; CY set if error should be returned +; CY clear if it should be ignored +; + Public error_exit +error_exit: + cmp internal_flag,0 ; If this is an internal + jnz error_ret ; do not generate a critical + call disk_error ; error + jnz error_r10 ; No Error Occured or Ignored + ret ; in critcal error handler + +; +; Return the error code to the user and DO NOT generate any +; critical errors. +; +; On Entry:- AX == Internal Error Number +; +; On Exit:- None +; + Public error_ret +error_ret: + call set_error ; the internal error code +error_r10: ; otherwise negate + les di,int21regs_ptr + or es:reg_FLAGS[di],CARRY_FLAG ; set the "users" carry Flag + stc ; also set real one +if offset reg_AX EQ 0 + stosw ; save return code +else + mov es:reg_AX[di],ax +endif + ret + +; +; On Entry:- AX == Internal Error Number +; +; On Exit:- None +; + Public fcberror_exit +fcberror_exit: + call disk_error ; Process the error code generating + jz fe_e10 ; a critical error is required + mov al,0FFh ; on FCB error return AL = FF +fe_e10: + ret + +eject +; WARNING - may be called from FDOS with DS = SYSDAT +; +; CHAR_ERROR is called when any character device function generates +; an error. First CHAR_ERROR sets the correct parameters for Get +; Extended Error. Then it generates a Critical Error by calling +; DO_INT24. +; +; Entry:- ES:SI -> device driver header +; SS:BX -> RH_ +; AX = RH_STATUS +; +; Exit AL Error Action +; + Public char_error +char_error: + test ss:valid_flg,NO_CRIT_ERRORS + jz char_e10 + mov al,ERR_FAIL ; no critical errors allowed + ret ; so just fail things +char_e10: + push ds + push es + push bx + push cx + push dx + push si + push di + push ss ! pop ds ; DS -> our data now + mov word ptr error_dev+0,si ; save the device driver address + mov word ptr error_dev+2,es ; and then initialise the FUNC59 + push es ; data areas + and ax,007Fh ; Mask the Unused Bits + or ah,80h+OK_RIF ; Retry/Ignore/Abort/Fail allowable + cmp ss:RH_CMD,CMD_OUTPUT ; is this a read or write failure ? + jne char_e20 + inc ah ; 01 is a Write Failure +char_e20: + mov rwmode,ah ; + push ax ; save for int 24 + cbw ; zero AH again + neg ax ; convert to an internal error + add ax,ED_PROTECT ; code for set_error + mov cl,LOC_CHAR + call set_error + add ax,ED_PROTECT ; convert to hardware error + xchg ax,di ; DI == hardware error + pop ax + pop es + call do_int24 ; execute INT 24 + pop di + pop si + pop dx + pop cx + pop bx + pop es + pop ds + ret + +eject +; +; DISK_ERROR gains control after any DOS disk based function +; has been executed which generates an error. First ERROR set the +; correct parameters for Get Extended Error. Then it determines if +; the current error should generate a Critical Error and calls +; DO_INT24 if TRUE. +; +; +; On Entry: +; AX Internal Error Code +; +; On Exit: +; AX 0 if no error to return (Ignore) +; AX DOS Error Code +; ZF reflects AX +; +disk_error: + mov cl,LOC_CHAR ; assume character device + ; determine if the error is + test rwmode,80h ; caused by a character or + jnz disk_e10 ; block device and set the + mov cl,LOC_BLOCK ; the critical error locus +disk_e10: + call set_error ; record error information + jz disk_e50 ; just return a logical error. + + add ax,ED_PROTECT ; Convert to HardWare Error + mov di,ax ; DI == HardWare Error + ; Now get the information + mov ah,rwmode ; about the error location + + and ah,not OK_RIF ; mask the all responses +; mov al,valid_flg ; valid flag contains no crit +; and al,not NO_CRITICAL_ERRORS ; errors bit, but if that was +; or ah,al ; set we wouldn't be here + or ah,valid_flg ; or in valid responses + + cmp bx,ED_GENFAIL ; if it's general failure + jne disk_e20 ; we cannot Ignore the error + and ah,not OK_IGNORE ; but must Abort/Fail/Retry +disk_e20: ; as appropriate + + mov al,err_drv ; get the failing drive + mov error_drive,al ; and save locally + + les si,error_dev ; get device driver header + + ; are we are a character device + test ah,80h ; as these have handled at a + jnz disk_e40 ; lower level and just need + ; to be FAILed back to caller + + call do_int24 ; Execute INT 24 + + mov bl,al ; Copy reponse into BL + + xor ax,ax ; Assume Ignore Error + cmp bl,ERR_IGNORE ! jz disk_e50 ; Ignore the Error + + cmp bl,ERR_FAIL ! jz disk_e40 ; If not FAIL then RETRY + call reload_registers ; get back entry registers + mov FD_FUNC,ax ; save AX for a moment + mov al,ah ; set up function number + xor ah,ah ; in AX + xchg ax,FD_FUNC ; save for use by FDOS + xor ah,ah ; zero AH 'cause it's handy + mov sp,retry_sp ; Must be RETRY so reset the + jmp retry_off ; STACK and IP + +disk_e40: +; +; When a Critical Error is FAILED then we do the following +; if (extended error_code <= ED_SHAREFAIL) then +; ret = ED_ACCESS; +; else +; ret = ED_FAIL; +; extended error_code = ED_FAIL; +; return(ret); +; +; nb. above proto-code is at the request of ant +; + mov ax,-(ED_FAIL) ; always return ED_FAIL in the + xchg ax,error_code ; extended error_code + cmp ax,-(ED_SHAREFAIL) ; did we FAIL on sharing conflict ? + mov ax,-(ED_ACCESS) ; assume we did and prepare to return + jae disk_e50 ; ED_ACCESS + mov al,-(ED_FAIL) ; woops, return ED_FAIL after all +disk_e50: + or ax,ax ; NZ if error return required + ret + +eject +; +; On Entry:- AX Internal Error Code +; CL Critical Error Locus +; +; On Exit:- AX DOS Error Code +; BX Internal Error Code +; ZF set on logical error +set_error: + mov bx,ax ; by default we return the raw error + mov di,offset critical_error; Scan for critical Errors First + call scan_error_table ; look for a matching error + jc set_logical_error + mov locus,cl ; Save the critical error LOCUS + cmp ax,ED_SHAREFAIL ; watch out for SHAREFAIL - the action + jne set_e10 ; depends on the caller +; +; ED_SHAREFAIL will return ED_ACCESS if the result of an attempt to open +; a file in shared mode, otherwise (FCB's and compatibility) it will +; generate a critical error. +; + mov bx,ED_GENFAIL ; assume we want a critical error + cmp FD_FUNC,MS_X_OPEN ; is it a shared open ? + jnz set_error_data + test FD_MODE,0$111$0$000b ; mode + jz set_error_data + jmps set_e30 ; return a logical "access denied" + +set_e10: + cmp ax,ED_LOCKFAIL ; have we a lockfail error ? + jne set_e20 +; +; ED_LOCKFAIL returns ED_ACCESS if a lock attempt fails, but a critical error +; on an attempt to read/write a locked region. +; + cmp FD_FUNC,FD_LOCK ; was it a result of specific lock + je set_logical_error ; call ? yes, it's a logical error + mov bx,ED_GENFAIL ; no, generate a critical error + jmps set_error_data + +set_e20: + test valid_flg,NO_CRIT_ERRORS + jz set_error_data ; do we allow critical errors ? + mov ax,ED_ACCESS ; extended error code is Access Denied +set_e30: + mov bx,ED_ACCESS ; return access denied to caller +; jmps set_logical_error + +set_logical_error: + xor di,di + mov word ptr error_dev+0,di ; must be a logical error so force + mov word ptr error_dev+2,di ; the ERROR_DEV to 0000:0000 + mov di,offset logical_error ; scan the Logical error table + call scan_error_table + cmp ax,ED_NETACCESS ; if it's a networked access denied + jne set_error_data ; turn it into ordinary one + mov bx,ED_ACCESS ; return a logical "access denied" +; jmps set_error_data + +set_error_data: +; On Entry: +; AX = Internal Error Code for extended error +; BX = Internal Error Code for returned error +; CS:DI -> error table entry +; On Exit: +; AX = DOS Error Code +; BX = Internal Error Code +; ZF set on logical error +; + neg ax + mov error_code,ax ; Save the Error Code + mov al,cs:ERR_TBL_CLASS[di] + mov error_class,al ; Save the Class + mov al,cs:ERR_TBL_ACTION[di] + mov error_action,al ; Save the Action + mov al,cs:ERR_TBL_LOCUS[di] ; Get the Locus + mov error_locus,al ; Save the Locus and then check + test al,al ; if the function overrides + jnz set_d10 ; this value + mov al,locus ; Get the Global Locus value + mov error_locus,al ; set by the calling function +set_d10: ; and save for FUNC 59 + mov ax,bx ; Return to the caller with + neg ax ; the DOS error code. + mov di,word ptr error_dev ; set ZF if logical error + or di,word ptr error_dev+2 ; error_dev = 0:0 + ret + +scan_error_table: + cmp cs:ERR_TBL_CODE[di],0 + je scan_et10 ; Check for the end of the list + cmp al,cs:ERR_TBL_CODE[di] + je scan_et20 + add di,ERR_TBL_LEN + jmps scan_error_table +scan_et10: + stc +scan_et20: + ret + + +eject +PCM_RODATA CSEG WORD +logical_error rb 0 +; +; Internal Code Error Class Error Action Error Locus +; ============= =========== ============ =========== + db ED_FUNCTION, CLASS_APPLIC, ACT_ABORT, 00 + db ED_FILE, CLASS_LOST, ACT_USER, LOC_BLOCK + db ED_PATH, CLASS_LOST, ACT_USER, LOC_BLOCK + db ED_HANDLE, CLASS_RESOURCE, ACT_ABORT, LOC_UNKNOWN + db ED_ACCESS, CLASS_AUTHOR, ACT_USER, 00 + db ED_NETACCESS, CLASS_AUTHOR, ACT_USER, 00 + db ED_H_MATCH, CLASS_APPLIC, ACT_ABORT, LOC_UNKNOWN + db ED_DMD, CLASS_APPLIC, ACT_TERM, LOC_MEMORY + db ED_MEMORY, CLASS_RESOURCE, ACT_ABORT, LOC_MEMORY + db ED_BLOCK, CLASS_APPLIC, ACT_ABORT, LOC_MEMORY + db ED_ENVIRON, CLASS_APPLIC, ACT_ABORT, LOC_MEMORY + db ED_FORMAT, CLASS_FORMAT, ACT_USER, LOC_UNKNOWN + db ED_ACC_CODE, CLASS_APPLIC, ACT_ABORT, LOC_UNKNOWN + db ED_DATA, CLASS_FORMAT, ACT_ABORT, LOC_UNKNOWN + db ED_DRIVE, CLASS_LOST, ACT_USER, LOC_BLOCK + db ED_DIR, CLASS_AUTHOR, ACT_USER, LOC_BLOCK + db ED_DEVICE, CLASS_UNKNOWN, ACT_USER, LOC_BLOCK + db ED_ROOM, CLASS_LOST, ACT_USER, LOC_BLOCK + db ED_EXISTS, CLASS_EXISTS, ACT_USER, LOC_BLOCK + db ED_STRUCT, CLASS_RESOURCE, ACT_ABORT, 00 + db ED_PASSWORD, CLASS_AUTHOR, ACT_USER, LOC_UNKNOWN + db ED_MAKE, CLASS_RESOURCE, ACT_ABORT, LOC_BLOCK +;; db ED_NET, CLASS_FORMAT, ACT_USER, LOC_NET + db ED_ASSIGN, CLASS_EXISTS, ACT_USER, LOC_NET + db ED_PARAM, CLASS_FORMAT, ACT_USER, LOC_UNKNOWN + db ED_FAIL, CLASS_UNKNOWN, ACT_ABORT, LOC_UNKNOWN + db ED_SHAREFAIL, CLASS_LOCKED, ACT_DELAY, LOC_BLOCK + db ED_LOCKFAIL, CLASS_LOCKED, ACT_DELAY, LOC_BLOCK + db ED_NOLOCKS, CLASS_RESOURCE, ACT_ABORT, LOC_MEMORY + db 00, CLASS_SYSTEM, ACT_TERM, LOC_UNKNOWN + +critical_error rb 0 +; +; Internal Code Error Class Error Action Error Locus +; ============= =========== ============ =========== + db ED_PROTECT, CLASS_MEDIA, ACT_URETRY, LOC_BLOCK + db ED_BADUNIT, CLASS_INTERNAL, ACT_TERM, LOC_UNKNOWN + db ED_NOTREADY, CLASS_HARDWARE, ACT_URETRY, 00 + db ED_BADCMD, CLASS_INTERNAL, ACT_TERM, LOC_UNKNOWN + db ED_BADDATA, CLASS_MEDIA, ACT_ABORT, LOC_BLOCK + db ED_BADSEEK, CLASS_HARDWARE, ACT_RETRY, LOC_BLOCK + db ED_BADMEDIA, CLASS_MEDIA, ACT_URETRY, LOC_BLOCK + db ED_RNF, CLASS_MEDIA, ACT_ABORT, LOC_BLOCK + db ED_NOPAPER, CLASS_TEMP, ACT_URETRY, LOC_CHAR + db ED_WRFAIL, CLASS_HARDWARE, ACT_ABORT, 00 + db ED_RDFAIL, CLASS_HARDWARE, ACT_ABORT, 00 + db ED_GENFAIL, CLASS_UNKNOWN, ACT_ABORT, 00 + db ED_SHAREFAIL, CLASS_LOCKED, ACT_DELAY, LOC_BLOCK + db ED_LOCKFAIL, CLASS_LOCKED, ACT_DELAY, LOC_BLOCK + db ED_NOFCBS, CLASS_APPLIC, ACT_ABORT, LOC_UNKNOWN + +default_error rb 0 + db 00, CLASS_SYSTEM, ACT_TERM, LOC_UNKNOWN + +PCMODE_DATA DSEG WORD + extrn indos_flag:byte + extrn internal_flag:byte + extrn int21regs_ptr:dword + extrn current_psp:word + extrn retry_off:word, retry_sp:word + extrn valid_flg:byte + extrn error_locus:byte ; Error Locus + extrn error_code:word ; DOS format error Code + extrn error_action:byte ; Error Action Code + extrn error_class:byte ; Error Class + extrn error_dev:dword ; Failing Device Header + extrn error_drive:byte ; Failing Disk Drive + extrn err_drv:byte + extrn locus:byte + extrn rwmode:byte +end diff --git a/IBMDOS/EXE.DEF b/IBMDOS/EXE.DEF new file mode 100644 index 0000000..4120a76 --- /dev/null +++ b/IBMDOS/EXE.DEF @@ -0,0 +1,52 @@ +; File : $EXE.DEF$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +; +; This file defines the DOS .EXE file Header + + +EXE_SIGNATURE equ word ptr 0 ; 0000 Valid EXE contains 'MZ' +EXE_FINAL equ word ptr EXE_SIGNATURE+2; 0002 Image Length MOD 512 +EXE_SIZE equ word ptr EXE_FINAL+2 ; 0004 Image Length DIV 512 +EXE_RELCNT equ word ptr EXE_SIZE+2 ; 0006 No. of Relocation Items +EXE_HEADER equ word ptr EXE_RELCNT+2 ; 0008 Header Size in paragraphs +EXE_MINPARA equ word ptr EXE_HEADER+2 ; 000A Minimum No extra paragraphs +EXE_MAXPARA equ word ptr EXE_MINPARA+2 ; 000C Maximum No of extra paragraphs +EXE_SS equ word ptr EXE_MAXPARA+2 ; 000E Displacment of Stack Segment +EXE_SP equ word ptr EXE_SS+2 ; 0010 Initial SP +EXE_CHECKSUM equ word ptr EXE_SP+2 ; 0012 Negative CheckSum +EXE_IP equ word ptr EXE_CHECKSUM+2 ; 0014 Initial IP +EXE_CS equ word ptr EXE_IP+2 ; 0016 Code Segment displacement +EXE_RELOFF equ word ptr EXE_CS+2 ; 0018 Byte Offset of First REL item +EXE_OVERLAY equ word ptr EXE_RELOFF+2 ; 001A Overlay Number (0 == Resident) +EXE_LENGTH equ 001Ch diff --git a/IBMDOS/F52DATA.DEF b/IBMDOS/F52DATA.DEF new file mode 100644 index 0000000..42c12ab --- /dev/null +++ b/IBMDOS/F52DATA.DEF @@ -0,0 +1,90 @@ +; File : $Workfile$ +; +; Description : +; +; Original Author : +; +; Last Edited By : $Author$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +; +; The following equates define the Data Area whose address is +; returned by function 52. +; + + +F52_BCBBUF equ es:dword ptr -0008h[bx] ; current buffer +F52_BCBOFF equ es:word ptr -0008h[bx] ; current buffer +F52_BCBSEG equ es:word ptr -0006h[bx] ; current buffer +F52_DMDROOT equ es:word ptr -0002h[bx] ; Memory Descriptor Root (Seg) +F52_DDSCPTR equ es:dword ptr 0000h[bx] ; DDSC Table Address +F52_FILEPTR equ es:dword ptr 0004h[bx] ; File Handle Table Address +F52_CLKDEV equ es:dword ptr 0008h[bx] ; Clock Device Header +F52_CONDEV equ es:dword ptr 000Ch[bx] ; Console Device Header +F52_SECSIZE equ es:word ptr 0010h[bx] ; Maximum Sector Size +F52_BUFINFOPTR equ es:dword ptr 0012h[bx] ; Buffer Info pointer +F52_PATHPTR equ es:dword ptr 0016h[bx] ; Path Control Table Address +F52_PATHOFF equ es:word ptr 0016h[bx] +F52_PATHSEG equ es:word ptr 0018h[bx] +F52_FCBPTR equ es:dword ptr 001Ah[bx] ; FCB Table Address +; equ es:word ptr 001Eh[bx] ; #Entries in FCB Table +F52_PHYDRV equ es:byte ptr 0020h[bx] ; Last Physical Drive +F52_LASTDRV equ es:byte ptr 0021h[bx] ; Last Logical Drive +F52_DEVROOT equ es:dword ptr 0022h[bx] ; Root Device Header +F52_JOINDRV equ es:byte ptr 0034h[bx] ; Number of JOIN'd drives +F52_SETVER equ es:dword ptr 0037h[bx] ; SETVER table pointer +F52_NUM_BUF equ es:word ptr 003Fh[bx] ; number of disk buffers +F52_READ_AHEAD equ es:word ptr 0041h[bx] ; size of read-ahead buffer +F52_BOOTDRV equ es:byte ptr 0043h[bx] ; boot drive (1-26) +F52_CPU_TYPE equ es:byte ptr 0044h[bx] ; 01 if >= 386SX +F52_EXT_MEM equ es:word ptr 0045h[bx] ; Int 15h, AH=87h +F52_BUF_INFO equ es:dword ptr 0047h[bx] ; points at Buffer Info +F52_HMAFLAG equ es:byte ptr 0053h[bx] ; 1 if buffers in HMA +F52_DEBLOCK equ es:word ptr 0056h[bx] ; deblock if buffers in HMA +F52_DMD_UPPER equ es:word ptr 0066h[bx] ; upper memory chain +F52_SHARE_STUB equ es:dword ptr 006Ah[bx] ; Share Stub Entries*15 + +;DRDOS Specific + +DRDOS_CRITSTUBS equ es:word ptr 0000h[bx] ; Offset of end of instance data +DRDOS_HIST1CTL equ es:word ptr 0004h[bx] ; History 1 Control +DRDOS_HIST2CTL equ es:word ptr 0006h[bx] ; History 2 Control +DRDOS_HISTFLG equ es:byte ptr 0008h[bx] ; History Buffer Flag +DRDOS_DUAL_LANG equ es:byte ptr 0009h[bx] ; Utils Dual Language Support +DRDOS_CUR_LANG equ es:byte ptr 000Ah[bx] ; Current Language +DRDOS_EXT_MEM equ es:word ptr 000Bh[bx] ; Total Extended Memory +DRDOS_HIMEM_ROOT equ es:word ptr 0010h[bx] ; High memory chain +DRDOS_ENVSEG equ es:word ptr 0012h[bx] ; Seg of environment +DRDOS_DMD_BASE equ es:word ptr 0016h[bx] ; base memory freed at +DRDOS_DMD_UPPER equ es:word ptr 0018h[bx] ; upper memory chain +DRDOS_MACHINE_ID equ es:word ptr 001Ah[bx] ; local machine ID +DRDOS_COUNTRY_FILE equ es:word ptr 001Eh[bx] ; offset of filename +DRDOS_HASHOFF equ es:word ptr 0020h[bx] ; fastopen hash root +DRDOS_HASHSEG equ es:word ptr 0022h[bx] ; pointer +DRDOS_HASHMAX equ es:word ptr 0024h[bx] ; max # dir entries +DRDOS_DEBLOCK equ es:word ptr 0026h[bx] ; himem deblock buffer +DRDOS_INT2F equ es:word ptr 002Ch[bx] ; internal Int 2F hook diff --git a/IBMDOS/FCBS.A86 b/IBMDOS/FCBS.A86 new file mode 100644 index 0000000..dfa3eaa --- /dev/null +++ b/IBMDOS/FCBS.A86 @@ -0,0 +1,960 @@ +title 'FCB - DOS file system FCB support' +; File : $FCBS.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; $Log$ +; FCBS.A86 1.10 93/11/11 15:38:14 +; Chart Master fix - fcb_readblk over > 64k is truncated to 64k and +; error 2 (Segment boundry overlap) is returned +; FCBS.A86 1.9 93/10/18 17:37:06 +; fix for >255 open files (PNW Server) +; ENDLOG + + eject ! include i:fdos.equ + eject ! include i:msdos.equ + eject ! include i:mserror.equ + eject ! include i:doshndl.def ; DOS Handle Structures + eject + + +BDOS_DATA dseg word + +BDOS_CODE cseg + + extrn ifn2dhndl:near + extrn parse_one:near + extrn fdos_entry:near + + Public fdos_exit + +eject +; TERMINATE CHILD (EXIT) + +; +----+----+ +; | 24 | +; +----+----+ + +; entry: +; ------ +; -none- + +; exit: +; ----- +; -none- + +; Close down all FCB handles associated with the current PSP +; +fdos_exit: +;--------- + push ds + push ss ! pop ds ; DS -> PCM_DSEG + sub ax,ax ; start with first DHNDL_ +fdos_exit10: + call ifn2dhndl ; get DHNDL_ + jc fdos_exit40 ; stop if we have run out + mov fcb_pb+2,ax ; we may close this IFN + push ax + mov cx,es:DHNDL_COUNT[bx] ; get the open count + jcxz fdos_exit30 ; skip if nothing to do + mov ax,current_psp ; get current PSP + cmp ax,es:DHNDL_PSP[bx] ; does it belong to this PSP + jne fdos_exit30 + mov ax,ss:machine_id ; get current process + cmp ax,es:DHNDL_UID[bx] + jne fdos_exit30 + test es:DHNDL_MODE[bx],DHM_FCB + jz fdos_exit20 ; skip close if not FCB + push es + push bx ; save the DHNDL + mov ax,MS_X_CLOSE + call fcb_fdos ; make the FDOS do the work + pop bx + pop es ; recover the DHNDL +fdos_exit20: + mov es:DHNDL_COUNT[bx],0 ; always free the handle if it's ours +fdos_exit30: + pop ax + inc al ; onto next IFN + jnz fdos_exit10 +fdos_exit40: + pop ds + ret + + + + + + Public fdos_fcb + +eject +; GENERIC FCB FUNCTION (FCB) + +; +----+----+----+----+----+----+----+----+ +; | 22 | fcbadr | count | +; +----+----+----+----+----+----+----+----+ +; | func | +; +----+----+ + +; entry: +; ------ +; fcbadr: FCB address +; count: multi-sector count for read/write +; func: FCB sub-function + +; exit: +; ----- +; AX: return code or error code ( < 0) + +fdos_fcb: +;-------- + mov bx,2[bp] ; BX -> parameter block + mov bx,8[bx] ; get subfunction code + shl bx,1 ; make it word index + sub bl,15*WORD ; adjust to base address + jc fcb_error ; reject if too low + cmp bl,FCB_MAX1 ; is it in 1st block + jb fdos_fcb10 + sub bl,(33-24)*WORD ; adjust for gap + jc fcb_error + cmp bl,FCB_MAX2 ; is it in 2nd block + jb fdos_fcb10 + sub bl,(39-37)*WORD ; adjust for gap + jc fcb_error +fdos_fcb10: + cmp bx,FCB_MAX3 ; check the range + jae fcb_error ; skip if invalid function + jmp fcb_table[bx] ; call the right function + +fcb_error: + mov bx,ED_FUNCTION + ret + +fcb_table dw fcb_open ; 15-open file + dw fcb_close ; 16-close file + dw fcb_first ; 17-find first + dw fcb_next ; 18-find next + dw fcb_delete ; 19-delete file + dw fcb_read ; 20-read from file + dw fcb_write ; 21-write to file + dw fcb_make ; 22-make file + dw fcb_rename ; 23-rename file +FCB_MAX1 equ (offset $ - offset fcb_table) + dw fcb_readrand ; 33-read from file + dw fcb_writerand ; 34-write to file + dw fcb_size ; 35-compute file size + dw fcb_setrecord ; 36-set relative record +FCB_MAX2 equ (offset $ - offset fcb_table) + dw fcb_readblk ; 39-read from file + dw fcb_writeblk ; 40-write to file +FCB_MAX3 equ (offset $ - offset fcb_table) + +fcb_make: +;-------- + call fcb_path_prep ; build pathname + mov ax,MS_X_CREAT + jmps fcb_open_make_common + +fcb_open: +;-------- + call fcb_path_prep ; build pathname + mov ax,MS_X_OPEN +fcb_open_make_common: + mov fcb_pb+6,DHM_RW+DHM_FCB ; open as an FCB for read/write + call fcb_fdos ; lets try and open the file + jnc fcb_open10 ; skip if we can't + ret +fcb_open10: + call ifn2dhndl ; ES:BX -> DHNDL_ we have opened + push ds + push es ! push bx ; save DHNDL_ + call fcb_point ; ES:BX = FCB + pop si ! pop ds ; DS:SI -> DHNDL_ + mov es:MSF_IFN[bx],al ; store IFN away + mov es:MSF_BLOCK[bx],0 ; current block number + mov es:MSF_RECSIZE[bx],128 ; current logical record size + call fcb_update ; update misc changing fields + mov ax,ds:DHNDL_DEVOFF[si] + mov es:word ptr MSF_DEVPTR[bx],ax + mov ax,ds:DHNDL_DEVSEG[si] + mov es:word ptr MSF_DEVPTR+2[bx],ax + mov ax,ds:DHNDL_BLK1[si] + mov es:MSF_BLOCK1[bx],ax + mov al,ds:DHNDL_ATTR[si] + mov es:MSF_IOCTL[bx],al + mov al,es:MSF_DRIVE[bx] ; get drive from FCB + dec al ; was absolute drive specified ? + jns fcb_open20 ; if so use it + mov al,ss:current_dsk ; else use default drive +fcb_open20: + inc al ; make drive 1 rather than 0 based + mov es:MSF_DRIVE[bx],al ; drive code +if 0 + test ds:DHNDL_DATRB[si],DA_VOLUME +else + test ss:fcb_pb+8,DA_VOLUME +endif + pop ds + jnz fcb_close ; don't leave VOL label's open + xor bx,bx ; no errors ! + ret + + +fcb_update: +;---------- +; On Entry: +; DS:SI -> DHNDL_ +; ES:BX -> FCB +; On Exit: +; DATE/TIME/SIZE/DBLK/DCNT fields updated +; + mov ax,ds:DHNDL_TIME[si] + mov es:MSF_TIME[bx],ax + mov ax,ds:DHNDL_DATE[si] + mov es:MSF_DATE[bx],ax + mov ax,ds:DHNDL_SIZELO[si] + mov es:MSF_SIZE[bx],ax + mov ax,ds:DHNDL_SIZEHI[si] + mov es:MSF_SIZE+2[bx],ax + mov ax,ds:DHNDL_DBLK[si] + mov es:MSF_DBLK[bx],ax + mov al,ds:DHNDL_DCNTLO[si] + mov ah,ds:DHNDL_DCNTHI[si] + mov es:MSF_DCNT[bx],ax + ret + +fcb_close: +;--------- +; close file (DOS function 10h) + call fcb_point ; ES:BX -> FCB + mov al,0FFh + cmp al,es:MSF_IFN[bx] ; is it a multiple close ? + je fcb_fdos_common10 ; don't re-open for this... + call fcb_handle_vfy ; verify we have a sensible handle + mov es:MSF_IFN[bx],al ; mark FCB as closed (it will be) + mov ax,MS_X_CLOSE ; now close it +; jmps fcb_fdos_common + +fcb_fdos_common: +;--------------- + call fcb_fdos ; make the FDOS do the work + jc fcb_fdos_common20 ; return any error codes +fcb_fdos_common10: + xor bx,bx ; else return zero +fcb_fdos_common20: + ret + + + +fcb_rename: +;---------- + call fcb_path_prep + call fcb_path2_prep + mov ax,MS_X_RENAME ; it's a rename + jmps fcb_fdos_common + +fcb_delete: +;---------- + call fcb_path_prep + mov ax,MS_X_UNLINK ; it's a delete + jmps fcb_fdos_common + + +fcb_first: +;--------- + call fcb_path_prep ; prepare pathname + mov ax,MS_X_FIRST ; we want to search 1st + jmps fcb_search_common + +fcb_next: +;-------- + call fcb_restore_search_state + mov ax,MS_X_NEXT +fcb_search_common: + call fcb_search ; 0 of OK, otherwise ED_.. + jc fcb_search_common10 + call fcb_save_search_state ; save sucessful state + xor bx,bx ; return code in BX +fcb_search_common10: + ret + + +fcb_setrecord: +;------------- + call fcb_point ; ES:BX -> FCB + mov ax,128 ; multiply current block by 128 + mul es:MSF_BLOCK[bx] ; to give current record number + xor cx,cx + mov cl,es:MSF_CR[bx] ; Add in the current record + add ax,cx ; to DX:AX to give the + adc dx,0 ; relative record + mov es:MSF_RR[bx],ax ; save the result + mov es:MSF_RR2[bx],dl + xor bx,bx ; we did OK + ret + +fcb_write: +;--------- + mov ax,MS_X_WRITE ; make it a write + jmps fcb_seq_rw + +fcb_read: +;-------- + mov ax,MS_X_READ ; make it a read +fcb_seq_rw: + call fcb_handle_vfy ; verify we have a sensible handle + push ax ; save the operation + call fcb_get_count ; AX = bytes to read + push ax ; save byte count + call fcb_seek_seq ; Seek to position in the file + pop cx ; recover byte to xfer + pop ax ; and the Operation Code + jc fcb_seq_rw10 + call fcb_rw ; do the Op + jc fcb_seq_rw10 + push bx ; save the error code + call fcb_update_seq ; update FCB filepos + pop bx ; recover error +fcb_seq_rw10: + ret + +fcb_rw: +; On Entry: +; AX = operation code +; CX = count +; fcb_pb+2 = IFN +; On Exit: +; BX = error code + les dx,ss:dword ptr dma_offset + add cx,dx ; see if we overflow + jc fcb_rw20 + sub cx,dx ; count back to normal + push cx ; save target count + mov fcb_pb+4,dx + mov fcb_pb+6,es ; setup buffer address + mov fcb_pb+8,cx ; and target count + call fcb_fdos ; ask the FDOS to do the read/write + jc fcb_rw10 ; we got a real error... + push ds + push es + mov ax,fcb_pb+2 ; get IFN + call ifn2dhndl ; ES:BX -> DHNDL_ we have open + push es ! push bx ; save DHNDL_ + call fcb_point ; ES:BX = FCB + pop si ! pop ds ; DS:SI -> DHNDL_ + call fcb_update ; update file size/time-stamp + pop es + pop ds + pop ax ; recover target count + mov cx,fcb_pb+8 ; we xfered this much + cmp cx,ax ; did we xfer enough + jb fcb_rw30 ; nope.. + xor bx,bx ; xfer went OK + ret + +fcb_rw10: + pop ax ; discard target count + ret + +fcb_rw20: +; Our DTA is too small - return 2 + mov bx,2 ; indicate the DTA is too small +; stc ; error - don't update FCB + ret + +fcb_rw30: +; We have some form of EOF - lets look into it + call fcb_point ; ES:BX = FCB + mov bx,es:MSF_RECSIZE[bx] ; BX = record size + mov ax,cx + xor dx,dx ; DX:AX = bytes xfer'd + div bx ; did we xfer a complete + test dx,dx ; number of records ? + jz fcb_rw40 ; if so return 1 +; Partial data was read - fill out with zero's and return 3 + inc ax ; allow for incomplete record + push ax ; save rounded up xfer count + les di,ss:dword ptr dma_offset + add di,cx ; point to 1st byte after xfer + mov cx,bx ; this many in a record + sub cx,dx ; so this many weren't xfer'd + xor ax,ax ; fill them with zero's + rep stosb ; zap the bytes we didn't xfer to + pop ax ; recover xfer count + mul bx ; and work out # bytes xfered + xchg ax,cx ; return bytes in CX + mov bx,3 ; indicate EOF (partial read) +; clc ; update FCB + ret + +fcb_rw40: +; No Data was xfered - return 1 + mov bx,1 ; indicate EOF (no data read) +; clc ; update FCB + ret + +fcb_writerand: +;------------- + mov ax,MS_X_WRITE ; make it a write + jmps fcb_random_rw + +fcb_readrand: +;------------ + mov ax,MS_X_READ ; make it a read +fcb_random_rw: + call fcb_handle_vfy ; check the handle is OK + push ax ; save the code + call fcb_get_count ; AX = bytes to read + push ax ; save byte count + xor cx,cx ; cause update of seq posn from + call fcb_update_rr ; random record position + call fcb_seek_rr ; Seek to position in the file + pop cx ; recover byte to xfer + pop ax ; and the Operation Code + jc fcb_random_rw10 + call fcb_rw ; do the Op +fcb_random_rw10: + ret + + +fcb_writeblk: +;------------ + mov ax,MS_X_WRITE ; make it a write + jmps fcb_block_rw + +fcb_readblk: +;----------- + mov ax,MS_X_READ ; make it a read +fcb_block_rw: + call fcb_handle_vfy ; check the handle is OK + push ax ; save the code + call fcb_get_count ; AX = bytes per record, CX = # records + xchg ax,cx ; CX = bytes per record + mul cx ; AX = bytes to xfer + test dx,dx ; more than 64K ? + jz fcb_block_rw10 ; then we should truncate it + mov ax,15 ; AX = handy mask + cwd ; DX = 0 + and ax,ss:dma_offset ; get dma offset for para + not ax ; DX/AX = maximum bytes we can xfer + div cx ; AX = maximum blocks we can xfer + mul cx ; AX = bytes to xfer (now < 64K) +fcb_block_rw10: + push ax ; save byte count + call fcb_seek_rr ; Seek to position in the file + pop cx ; recover byte to xfer + pop ax ; and the Operation Code + jc fcb_block_rw20 + call fcb_rw ; do the Op + jc fcb_block_rw20 + push bx ; save the error code + call fcb_update_rr ; update FCB filepos, get records xferd + mov bx,2[bp] ; BX -> parameter block + xchg cx,6[bx] ; update amount xfered + sub cx,6[bx] ; CX = # we didn't xfer (normally 0) + pop bx ; recover (possible) error + jcxz fcb_block_rw20 ; skip if we read all we wanted to + test bx,bx ; did we have a partial read for + jnz fcb_block_rw20 ; a reason like EOF ? + mov bx,2 ; no, we must have truncated it +fcb_block_rw20: + ret + + +fcb_size: +;-------- + call fcb_path_prep + mov ax,MS_X_CHMOD ; it's a get info + mov fcb_pb+6,0 + call fcb_fdos + jc fcb_size40 + call fcb_point ; ES:BX = FCB + mov cx,es:MSF_RECSIZE[bx] ; get the record size + test cx,cx ; is it non-zero ? + jnz fcb_size10 ; if not + mov cx,128 ; make it 128 bytes +fcb_size10: + mov ax,fcb_pb+10 + mov dx,fcb_pb+12 ; DX:AX = file length in bytes + call div_32 ; DX:AX = file length in records + jcxz fcb_size20 ; was there an overflow + add ax,1 + adc dx,0 ; include an extra record +fcb_size20: + call fcb_point ; ES:BX = FCB + mov es:MSF_RR[bx],ax ; low word of size + mov es:MSF_RR2[bx],dl ; hi byte of size + cmp es:MSF_RECSIZE[bx],64 ; if record size < 64 bytes + jae fcb_size30 ; then we use a 4 byte + mov es:MSF_RR2+1[bx],dh ; random record position +fcb_size30: + xor bx,bx ; good return +fcb_size40: + ret + + +; Utility FCB subroutines +;======================== + +fcb_handle_vfy: +;-------------- +; Verify FCB is valid and open, do not return if it isn't +; nb. Called with nothing on stack +; +; On Entry: +; FCB address in parameter block +; On Exit: +; AX preserved +; ES:BX -> FCB (skipping EXT bit if present) +; fcb_pb+2 = IFN of handle +; On Error - blow away caller and return error in BX +; + +; DEBUG - on reopen we could do more checks to ensure we are re-opening the +; same file + push ax + call fcb_point + cmp es:MSF_RECSIZE[bx],0 + jne fcb_handle_vfy10 + mov es:MSF_RECSIZE[bx],128 +fcb_handle_vfy10: + mov al,es:MSF_IFN[bx] ; get IFN + call ifn2dhndl ; ES:BX -> DHNDL_ + jc fcb_handle_vfy20 ; it must be a valid IFN + test es:DHNDL_MODE[bx],DHM_FCB + jz fcb_handle_vfy20 ; it must be an FCB.. + cmp es:DHNDL_COUNT[bx],0 + jne fcb_handle_vfy30 ; it must also be open.. +fcb_handle_vfy20: + call fcb_point + push es:MSF_RECSIZE[bx] ; save current record size + push es:MSF_BLOCK[bx] ; save current block number + push es ! push bx + call fcb_open ; try to re-open the file + pop bx ! pop es ; point back at FCB + pop es:MSF_BLOCK[bx] ; restore current block number + pop es:MSF_RECSIZE[bx] ; restore record size + jc fcb_handle_err + mov al,es:MSF_IFN[bx] ; get new IFN +fcb_handle_vfy30: + xor ah,ah + mov fcb_pb+2,ax ; set parameter block accordingly + call fcb_point ; ES:BX -> MSF_ + pop ax + clc + ret + +fcb_handle_err: + add sp,2*WORD ; discard AX and near return address + cmp ax,ED_HANDLE ; if we have run out of handles then + jne fcb_handle_err10 ; say no FCB's, else return error + mov ax,ED_NOFCBS +fcb_handle_err10: + xchg ax,bx ; error code in BX + stc + ret + + +fcb_path2_prep: +;-------------- +; On Entry: +; FCB address in parameter block +; On Exit: +; ES:BX -> FCB (skipping EXT bit if present) +; fcb_pb+6/8 -> unparse name from FCB +; + call fcb_point ; point at the FCB + mov al,es:MSF_DRIVE[bx] ; get drive + add bx,16 ; point at 2nd name in FCB + mov di,offset fcb_path2 + mov fcb_pb+6,di + mov fcb_pb+8,ds ; point at buffer we want + jmps fcb_path_prep_common + +fcb_path_prep: +;------------- +; On Entry: +; FCB address in parameter block +; On Exit: +; ES:BX -> FCB (skipping EXT bit if present) +; fcb_pb+2/4 -> unparse name from FCB +; + xor ax,ax ; assume no attribute + mov bx,2[bp] ; BX -> parameter block + les bx,2[bx] ; ES:BX -> FCB + cmp es:MSF_EXTFLG[bx],0ffh ; is it an extended FCB + jne fcb_path_prep10 + or al,es:MSF_ATTRIB[bx] ; we can use file mode from XFCB + add bx,7 ; skip EXT bit of FCB +fcb_path_prep10: + mov fcb_pb+8,ax ; remember the attribute + mov al,es:MSF_DRIVE[bx] ; get drive + mov di,offset fcb_path + mov fcb_pb+2,di + mov fcb_pb+4,ds ; point at buffer we want +fcb_path_prep_common: + dec al ; 0 = default drive + jns fcb_path_prep20 + mov al,current_dsk ; use default drive +fcb_path_prep20: + push ds + push ds ! push es + pop ds ! pop es ; ES:DI -> name buffer + add al,'A' ; make drive ASCII + stosb + mov al,':' + stosb ; now we have 'd:' + lea si,MSF_NAME[bx] ; DS:SI -> source name + movsw ! movsw + movsw ! movsw ; copy the name leaving spaces intact + mov al,'.' + stosb + movsw ! movsb ; copy the extention + pop ds +; jmps fcb_point ; point ES:BX at FCB again + + +fcb_point: +;--------- +; On Entry: +; FCB address in parameter block +; On Exit: +; ES:BX -> FCB (skipping EXT bit if present) +; (All other regs preserved) +; + mov bx,2[bp] ; BX -> parameter block + les bx,2[bx] ; ES:BX -> FCB + cmp es:MSF_EXTFLG[bx],0ffh ; is it an extended FCB + jne fcb_point10 + add bx,7 ; skip EXT bit of FCB +fcb_point10: + ret + +fcb_get_count: +;------------- +; On Entry: +; none +; On Exit: +; AX = bytes per record +; CX = callers CX count +; All regs fair game +; + call fcb_point ; ES:BX -> FCB + mov si,2[bp] ; SI -> parameter block + mov cx,6[si] ; CX = count + mov ax,es:MSF_RECSIZE[bx] ; get record size + ret + +fcb_update_seq: +;-------------- +; On Entry: +; CX = byte count actually transferred +; On Exit: +; CX = record count transferred +; All other regs fair game +; CR/BLOCK updated with new value +; + mov ax,cx + xor dx,dx ; DX:AX = byte count transfered + call fcb_point ; ES:BX -> FCB + div es:MSF_RECSIZE[bx] ; make records xfered + push ax ; save records xfered + xchg ax,cx ; also in CX for later + mov ax,128 + mul es:MSF_BLOCK[bx] ; DX:AX = record of block + add ax,cx + adc dx,0 ; add in amount just xfered + mov cl,es:MSF_CR[bx] + xor ch,ch ; now add in CR as a word + add ax,cx + adc dx,0 ; DX:AX = record + mov dh,dl ; DH:AX = record for common code + jmps fcb_update_common + + +fcb_update_rr: +;------------- +; On Entry: +; CX = byte count actually transferred +; On Exit: +; CX = record count transferred +; All other regs fair game +; Random Record and CR/BLOCK updated with new value +; + xchg ax,cx + xor dx,dx ; DX:AX = byte count transfered + call fcb_point ; ES:BX -> FCB + div es:MSF_RECSIZE[bx] ; make records xfered + push ax ; save records xfered + add es:MSF_RR[bx],ax ; update the RR field + adc es:MSF_RR2[bx],0 ; and the overflow + mov ax,es:MSF_RR[bx] ; get low part of RR + mov dh,es:MSF_RR2[bx] ; and the hi part +fcb_update_common: + mov dl,ah ; DX will be block number + shl al,1 ; get top bit of CR into CY + adc dx,dx ; then into DX + shr al,1 ; AL = CR (remember mod 128) + mov es:MSF_CR[bx],al ; set the CR field + mov es:MSF_BLOCK[bx],dx ; and the block field + pop cx ; recover records xfered + ret + + +fcb_seek_seq: +;------------ +; Seek to position in file indicated by the RR position +; On Entry: +; ES:BX -> FCB_ +; On Exit: +; CY clear if no problem, fcb_pb+2=IFN +; else +; CY set, AX = BX = error code +; All other regs fair game +; + call fcb_point ; ES:BX -> FCB_ + mov ax,128 + mul es:MSF_BLOCK[bx] ; get record in DX:AX + mov cl,es:MSF_CR[bx] + xor ch,ch + add ax,cx ; add in CR + adc dx,0 ; so DX:AX is really the record + push ax ; save low word of record + mov ax,dx + mul es:MSF_RECSIZE[bx] ; DX:AX = byte offset in file/10000h + mov cx,ax ; save the important word + pop ax ; recover low word of record + jmps fcb_seek_common + +fcb_seek_rr: +;----------- +; Seek to position in file indicated by the RR position +; On Entry: +; ES:BX -> FCB_ +; On Exit: +; CY clear if no problem, fcb_pb+2=IFN +; else +; CY set, AX = BX = error code +; All other regs fair game +; + call fcb_point ; ES:BX -> FCB_ + mov al,es:MSF_RR2[bx] + xor ah,ah + mul es:MSF_RECSIZE[bx] ; DX:AX = byte offset in file/10000h + mov cx,ax ; save the important word + mov ax,es:MSF_RR[bx] +fcb_seek_common: + mul es:MSF_RECSIZE[bx] ; DX:AX = byte offset in file + add dx,cx ; add the two bits together + mov fcb_pb+4,ax + mov fcb_pb+6,dx ; save position + mov fcb_pb+8,0 ; seek from start + xor ax,ax + mov al,es:MSF_IFN[bx] ; AX = IFN + mov fcb_pb+2,ax ; save IFN + mov ax,MS_X_LSEEK + jmp fcb_fdos ; try and seek to this position + + +fcb_search: +;---------- +; On Entry: +; AX = operation to perform +; On Exit: +; AX = 0, or ED_ error code (CY set if error) + push dma_offset + push dma_segment + mov dma_offset,offset fcb_search_buf + mov dma_segment,ds + call fcb_fdos ; do the search + pop dma_segment + pop dma_offset + test ax,ax ; was there an error + stc ; assume there was + js fcb_search10 ; return the error + xor ax,ax ; no problems +fcb_search10: + ret + +fcb_save_search_state: +;--------------------- +; On entry DS=PCMODE + + call fcb_point + lea di,MSF_NAME[bx] ; ES:DI -> FCB name + mov si,offset fcb_search_buf + lodsb ; get 1st byte = drive info + mov cx,20/WORD ; copy 20 bytes to FCB + rep movsw ; (the rest of the search template) + stosb ; drive info byte follow them + + les di,dword ptr dma_offset ; ES:DI -> search state in DMA address + mov si,2[bp] ; SI -> parameter block + lds si,2[si] ; DS:SI -> FCB_ + cmp ds:MSF_EXTFLG[si],0ffh ; extended FCB ? + jne fcb_sss10 + mov cx,7 ; copy extended FCB portions too + rep movsb ; we have copied up to name +fcb_sss10: + stosb ; save drive byte info + push di + mov al,' ' ; space fill name + mov cx,11 + rep stosb ; all blanks now + pop di + push ss ! pop ds ; DS:SI -> pathname + mov si,offset fcb_search_buf+1Eh + + push di ; unparse knowing name is good + mov cx,8 ; length of name field +fcb_sss20: + lodsb ; treat '.' and '..' specially + cmp al,'.' ; is either possible ? + jne fcb_sss30 ; no, continue as normal + stosb ; copy the '.' + loop fcb_sss20 ; go around for another '.' + jmps fcb_sss40 ; this name is rubbish!! +fcb_sss30: + dec si ; forget the non '.' + call parse_one ; parse just the name +fcb_sss40: + pop di + add di,8 ; di -> fcb ext field + cmp al,'.' ; do we have an extention ? + jne fcb_sss50 + mov cx,3 ; length of ext field + push di + call parse_one ; parse just extension + pop di +fcb_sss50: + add di,3 ; di -> rest of fcb + mov si,offset fcb_search_buf+15h + movsb ; copy the attribute field + xor ax,ax + mov cx,10/WORD + rep stosw ; 10 bytes of zeros + movsw ; copy time + movsw ; copy date + mov ax,word ptr srch_buf+21+DBLOCK1 + stosw ; 1st block + movsw ! movsw ; copy filesize + ret + +fcb_restore_search_state: +;------------------------ +; On entry DS=PCMODE + push ds + call fcb_point ; ES:BX -> FCB_ + push es ! push ds + pop es ! pop ds ; swap DS/ES + mov di,offset fcb_search_buf+1 + ; ES:DI -> internal state + lea si,1[bx] ; DS:SI -> FCB+1 + mov cx,10 + rep movsw ; copy info from FCB + lodsb ; get "drive" info + mov es:fcb_search_buf,al ; it's the 1st byte in the srch state + pop ds + ret + +fcb_fdos: +;-------- +; Make an FDOS call (NB. We don't have MX here, so it's OK) +; Set top bit of remote_call flag so we use IFN's not XFN's +; On Entry: +; AX = FDOS operation +; fcb_pb -> FDOS parameter block +; On Exit: +; As FDOS call +; + mov fcb_pb,ax ; save operation type + or remote_call,DHM_FCB ; forget about PSP during FCB call + mov dx,offset fcb_pb ; DS:DX -> parameter block + push ds + push bp + call fdos_entry ; call the FDOS + pop bp + pop ds + and remote_call,not DHM_FCB ; FCB operation over + cmp ax,ED_LASTERROR + cmc ; CY set if an error occurred + ret + +div_32: +; Entry: DX,AX = long dividend +; CX = word divisor +; Exit: DX,AX = long result +; CX = remainder + + jcxz div0 ; divide by 0 + cmp cx,1 + je div1 ; divide by 1 + push di + push bx + xor bx,bx ; BX = 0 + xchg ax,bx ; low word in BX, AX = 0 + xchg ax,dx ; high word in DX:AX + push ax ; save high word + div cx ; divide high part + mov di,ax ; save result + mul cx ; AX = even divisor part + pop dx ; old high in DX + sub dx,ax ; eliminate even part + xchg ax,bx ; AX = low word + div cx ; low part in AX + mov cx,dx ; CX = remainder + mov dx,di ; high result in DX + pop bx + pop di + ret + +div0: + mov ax,-1 + mov dx,ax + ret +div1: + dec cx ; CX = remainder = 0 + ret + + +PCMODE_DATA DSEG WORD + +extrn fcb_pb:word +extrn fcb_path:byte +extrn fcb_path2:byte +extrn fcb_search_buf:byte + +extrn current_dsk:byte +extrn current_psp:word +extrn dma_offset:word +extrn dma_segment:word +extrn machine_id:word +extrn remote_call:word +extrn srch_buf:byte + +end diff --git a/IBMDOS/FDOS.A86 b/IBMDOS/FDOS.A86 new file mode 100644 index 0000000..0fa5a1f --- /dev/null +++ b/IBMDOS/FDOS.A86 @@ -0,0 +1,425 @@ +title 'F_DOS - DOS file system' +; File : $FDOS.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; $Log$ +; FDOS.A86 1.23 93/12/15 03:07:08 +; New ddioif entry point so Int 25/26 bypasses address normalisation +; FDOS.A86 1.20 93/09/03 20:25:47 +; Add "no critical errors" support (int 21/6C) +; ENDLOG +; +; This is the DOS support function of Concurrent DOS 6.0 +; It is called via BDOS function #113, with DS:DX pointing +; to a parameter block. The first word of the parameter +; block is the subfunction number, the remainder are +; parameters or return values, depending on the function. + +; Date Who Modification +; --------- --- --------------------------------------- +; ?? Feb 86 Initial version +; 7 May 86 speedup MXdisk handling +; ?? Oct 86 used separate file handle & descriptors +; 5 Nov 86 combined with 5.1 BDOS; +; 7 Nov 86 added multiple file search +; 8 Nov 86 added open file checking +; 9 Nov 86 added lock/unlock code +; 14 Nov 86 converted to use new deblocking code +; 17 Nov 86 use RWXIOSIF code, select drive for flush +; 18 Nov 86 first attempt to support character devices +; on WRITE, CLOSE, LSEEK, DATTIM +; 19 Nov 86 some WRITE bugs fixed, MOVE implemented +; RMDIR redone locally (previously BLACK) +; 24 Nov 86 made changes for linked CDOS.CON +; 27 Nov 86 added FCB function entries for BLACK.A86 +; 30 Nov 86 added code to support FUNC13 (DRV_RESET) +; 3 Dec 86 added support for CHDIR ("l:=d:\path"); +; 16 Dec 86 update file time stamp on any write +; 23 Jan 86 added support for passwords +; 6 Feb 87 added support for IOCTL status +; 27 Feb 87 updated FCB r/w code to latest spec +; fixed FDOS_CREAT to truncate size to 0L +; 2 Mar 87 Changed FUNC62 to BDOS62 to avoid conflict +; with the linked PCMODE +; 7 Mar 87 changed MF_READ to 0-pad partial FCB records +; 17 Mar 87 fixed ES corruption in FCB_TERM code +; 29 Apr 87 Fixed CHDIR bug which failed to return an error when +; attempting to change to a filename. +; May 87 fixed some FCB bugs +; 19 May 87 changed password mode for FlexOS compatibility +; added IOCTL functions +; 4 Jun 87 zeroed current block on DOS FCB open +; 14 Jun 87 round up writes at end if > 1 sector and rt. fringe +; 19 Jun 87 supported freeing up floating drives +; 28 Jul 87 MX moved into individual funcs for DR NET support +; 29 Jul 87 WRITE_DEV moved to outside MXdisk +; 6 Aug 87 fix some password & partial close problems +; IOCTL(0) bug fixed +; 10 Aug 87 fixed CURDIR path too long problem +; 13 Aug 87 F1',F2' compatibility modes supported +; 20 Aug 87 LOCK_REGION fixed +; 5 Sep 87 lower case DOS FCBs converted to upper case +; 6 Sep 87 free up locked drives on process terminate +; 23 Sep 87 support \path1\path2\devname in DEVICE_ASCIZ: +; 28 Sep 87 use international upper case on ASCIZ paths +; 29 Sep 87 support IOCTL(4), IOCTL(5) +; 7 Oct 87 re-init dir entry on CREAT even if existing file +; return error if CURDIR can't find parent +; 8 Oct 87 don't release handles on disk change +; check OPEN_MAX and LOCK_MAX in SYSDAT +; 13 Oct 87 allow reduced F_OPEN if W,D password not supplied +; 22 Oct 87 support pseudo-networked drives via NET_VEC +; 26 Oct 87 use CBLOCK instead of HDSBLK for CP/M FCB check +; (can now CHDIR between F_OPEN and F_READ) +; 27 Oct 87 reject ".", ".." and " " names on MKDIR, CREAT, MKNEW +; 28 Oct 87 fixed OMODE_COMPAT compatibility checks, +; call SELECT_HANDLE in VFY_DOS_FCB to support +; FCB close after CHDIR +; 29 Oct 87 create label in root only, update VLDCNT in DPH +; delete label in root only, update VLDCNT in DPH +; also update VLDCNT in CREAT and UNLINK +; find labels in root if label only search +; 2 Nov 87 return ED_PATH if level doesn't exist in PATH_PREP +; reject "/path/" as legal ASCIZ specification +; 4 Nov 87 fix release_locks -- didn't work if any locks there +; test F6' on F_LOCK for file size check +; 10 Nov 87 fix F1' compatibility -- test 80h in P_CMOD +; support CREAT on file open in compatibility mode +; by the calling process +; 11 Nov 87 attempt to support multiple compatibility opens +; by several processes in read access mode or +; deny write/read access modes and still have the +; rest of the file sharing working... +; use PCM_ROUT as BIN flag for console handles +; 12 Nov 87 fix file sharing test on MF_OPEN (HM_FCB) +; fix DOS FCB rename of open file (WS 3.x) + +; 19 Nov 87 Release 6.0/2.0 +; --------- --------------- + +; 21 Nov 87 make NUL device first device in the list +; 1 Dec 87 various network fixes (dup, exec, exit, etc.) +; 2 Dec 87 implement DOS FCB calls across DR Net +; 3 Dec 87 fix CHECK_NOT_OPEN (CALL FILE_UPDATE) (fixes CB86) +; 4 Dec 87 pass drive on network FCB calls +; 7 Dec 87 supported FCB reads/writes across network (via handles) +; 10 Dec 87 fixed month dependant MKDIR bug. +; 11 Dec 87 fixed networked CURDIR bug (for SUBST) +; 5 Jan 88 don't delete labels via FDOS_UNLINK, +; don't access labels via FDOS_CHMOD +; 7 Jan 88 make NUL device first device in chain, in SYSDAT +; 12 Jan 88 setup MAKE_FLAG in FCB_MAKE_TEST +; 15 Jan 88 prevent SUBSTitution of networked drives +; 9 Feb 88 temporarily force door open interrupts +; add GET_FHND, FREE_FHND for dynamic handle create +; 10 Feb 88 update file size in DOS FCB for AutoCAD +; 15 Feb 88 update CUR_IFN in OPEN_HANDLE for MF_OPEN FCB setup +; 25 Feb 88 pass correct unit to driver on generic IOCTL request +; fix removable media check with DOS drivers +; 3 Mar 88 permit multiple compatibility mode opens +; 9 Mar 88 CHDIR ("d:=") always handled locally +; reject CHMOD on character devices +; use LUL_ALLOC for lock list allocation +; 10 Mar 88 Get PSP_XFNMAX before corrupting ES (RMCOBOL) +; 15 Mar 88 split file into three include files +; 28 Jul 88 Support PCMODE Private Device List +; 29 Jul 88 make PRN=LPT1, AUX=COM1 +; 27-Feb-89 change PID equate for CDOS, work around RASM bug +; ("PID equ RLR" would cause external ref's to PID!) +; 29-Jun-89 Split off IOCTL into seperate module +; 11-Sep-89 Split off MSNET into seperate module + + eject ! include i:psp.def + eject ! include i:modfunc.def + eject ! include i:fdos.equ + eject ! include rh.equ + eject ! include i:msdos.equ + eject ! include i:mserror.equ + eject ! include i:doshndl.def ; DOS Handle Structures + eject ! include i:driver.equ + eject ! include i:f52data.def ; DRDOS Structures + eject ! include bdos.equ + eject + +FD_EXPAND equ 55h + +PCMODE_DATA dseg + + extrn current_ddsc:dword + extrn current_device:dword + extrn current_dhndl:dword + extrn current_dsk:byte ; default drive + extrn current_ifn:word + extrn current_ldt:dword + extrn current_psp:word ; PSP segment + extrn dev_root:dword + extrn dma_offset:word ; DTA offset + extrn dma_segment:word ; DTA segment + extrn file_ptr:dword + extrn fdos_stub:dword + extrn internal_flag:byte + extrn ioexerr:byte + extrn join_drv:byte + extrn last_drv:byte + extrn ldt_ptr:dword ; Pointer to LDT's for the drives + extrn lock_tables:dword + extrn machine_id:word ; remote process + extrn name_buf:byte ; 32 byte name buffer + extrn nul_device:dword ; NUL in PCMODE data segment + extrn owning_psp:word ; remote PSP segment + extrn phys_drv:byte + extrn remote_call:word ; remote machine flag + extrn share_stub:dword + extrn srch_buf:byte + extrn pri_pathname:byte + extrn sec_pathname:byte + extrn temp_ldt:byte + extrn unlock_tables:dword + extrn WindowsHandleCheck:byte + extrn net_delay:word + +if KANJI + extrn DBCS_tbl:word ; Double Byte Character Table +endif + +BDOS_DATA dseg word + + extrn adrive:byte + extrn cur_dma:word + extrn cur_dma_seg:word + extrn mult_sec:word + extrn rwmode:byte + extrn valid_flg:byte + +NO_CRIT_ERRORS equ 0100$0000b ; critical error shouldn't be generated + ; warning - must match PCMODE.EQU + + extrn fdrwflg:byte + extrn chdblk:word + extrn dcnt:word + extrn dirp:word + extrn dirperclu:word + extrn finddfcb_mask:word + extrn hdsaddr:word + extrn intl_xlat:dword + extrn lastcl:word + extrn logical_drv:byte + extrn pblock:dword + extrn physical_drv:byte + extrn req_hdr:byte + + + extrn yearsSince1980:word + extrn month:byte + extrn dayOfMonth:byte + extrn hour:byte + extrn minute:byte + extrn second:byte + +orig_drive dw 0 +path_drive dw 0 + + + Public fdos_hds_blk, fdos_hds_root, fdos_hds_drv + +fdos_hds rw 0 ; temporary HDS that we make up +fdos_hds_blk dw 0 +fdos_hds_root dw 0 +fdos_hds_drv db 0 + +HDS_LEN equ offset $ - offset fdos_hds + +saved_hds rw 0 ; saved HDS on F_DOS rename +saved_hds_blk dw 0 +saved_hds_root dw 0 +saved_hds_drv db 0 + +saved_dcnt dw 0 ; saved DCNT on F_DOS rename + +dta_ofl db 0 ; non-zero if read/write > DTA size + +extflg dw 0 ; DOS FCB was extended FCB + +blk dw 0 ; temp variable for cluster # + +attributes db 0 ;fcb interface attributes hold byte + + public info_fcb +info_fcb rb 1+8+3 ;local user FCB drive+name+ext + +save_area rb 32 ;save area for dirbuf during rename and + ;info_fcb during create(mustbe_nolbl) + ;parental name during chdir + +; local variables for fdos operations + +sp_save dw 0 + +fdos_addr dw 0 ; address of F_DOS function + + Public fdos_info, fdos_pb, fdos_ret + +fdos_info rw 3 ; off, seg, size of parameter block +fdos_pb rw 7 ; copy of parameter block +fdos_ret dw 0 ; return value for function + +if PASSWORD +; Password support uses the following data stuctures: +; +; The global_password field is set by an IOCTL call and remains constant. +; +; When a password is encountered during parsing a path the ASCII form is +; copied into the password_buffer. It is then encrypted and stored in the +; local_password field. If a password protected file is encountered then +; it's encrypted password is compared with both the global and local passwords. +; +; During a file/directory create the local_password field is examnined. If +; non-zero then this encrypted password is applied to the file, which is given +; full protection. +; + Public global_password +global_password dw 0 +local_password dw 0 +password_buffer rb 8 + +endif + +eject +BDOS_CODE cseg + + + extrn pcmode_dseg:word ; Pointer to System Data Page + + extrn get_ldt:near + extrn get_ldt_raw:near + extrn islocal:near ; redirector support + extrn redir_asciiz_offer:near + extrn redir_asciiz_dev_offer:near + extrn redir_asciiz_file_offer:near + extrn redir_drv_offer:near + extrn redir_dhndl_offer:near + extrn redir_move_offer:near + extrn redir_snext_offer:near + + extrn alloc_cluster:NEAR + extrn allocdir:NEAR ; will extend subdirectory if full + extrn buffers_check:near + extrn discard_all:near + extrn close_dev:near ; close character device handle + extrn delfat:NEAR + extrn fdosrw:near ; read/write from/to disk file + extrn finddfcb:NEAR ; find next matching directory entry + extrn finddfcbf:NEAR ; find first matching directory entry + extrn first_dev:near ; find first matching character device + extrn fill_dirbuf:near + extrn flush_dirbuf:near + extrn flush_drive:near + extrn get_ddsc:near + extrn getdir:NEAR + extrn getnblk:NEAR + extrn hshdscrd:near ; discard hashing for drive AL + + extrn mark_ldt_unsure:near + extrn redir_build_path:near ; build ASCII path + + extrn open_dev:near ; open character device handle + extrn dup_dev:near ; call device driver on handle dup + extrn read_dev:near ; read from character device + extrn ReadTimeAndDate:near ; read date/time from CLOCK driver + extrn blockif:near + extrn ddioif:near + extrn select_logical_drv:near + extrn select_physical_drv:near + extrn setenddir:NEAR + extrn update_dat:NEAR ; flush dirty data buffers + extrn update_ddsc_free:NEAR ; count free blocks on drive + extrn update_dir:NEAR ; flush modified directory buffer + extrn update_fat:NEAR + extrn write_dev:near ; write to character device + extrn zeroblk:near ; fill cluster with 0's + + +eject + public bpb2ddsc ; build DDSC from a BPB + Public check_slash + public dbcs_lead + public discard_files ; discard open files (unconditional) + public fdos_ED_DRIVE ; Return ED_DRIVE error + public fdos_ED_FUNCTION ; Return ED_FUNCTION error + public find_dhndl + public find_xfn + public get_pb2_drive + public release_handle ; release file handle + public toupper ; upper case a character + Public unparse + public update_dir_fat ; flush DIR then FAT to disk + + public fdos_getdpb ; 0-disk information + public fdos_mkdir ; 1-make directory + public fdos_rmdir ; 2-remove directory + public fdos_chdir ; 3-change directory + public fdos_creat ; 4-create file + public fdos_open ; 5-open file + public fdos_close ; 6-close file + public fdos_read ; 7-read from file + public fdos_write ; 8-write to file + public fdos_unlink ; 9-delete file + public fdos_lseek ; 10-set file pointer + public fdos_chmod ; 11-get/set file attributes + public fdos_curdir ; 12-get current directory + public fdos_first ; 13-find first matching file + public fdos_next ; 14-find next matching file + public fdos_move ; 15-rename file + public fdos_dattim ; 16-get/set file name + public fdos_flush ; 17-flush buffers + public fdos_mknew ; 18-make new file + public fdos_lock ; 19-lock/unlock block + public fdos_dup ; 20-duplicate handle + public fdos_fdup ; 21-force duplicate handle + extrn fdos_fcb:near ; 22-FCB emulation + public fdos_exec ; 23-create child PSP + extrn fdos_exit:near ; 24-FCB close for PSP + public fdos_ddio ; 25-direct disk access + extrn fdos_ioctl:near ; 26-IOCTL emulation + public fdos_commit ; 27-commit file + public fdos_expand ; 28-expand file name + public fdos_mkddsc ; 29-build DDSC from BPB + public fdos_select ; 30-select drive + +if JOIN + Public check_join + Public mv_join_root +endif + +eject + +eject ! include funcs.fdo +eject ! include utils.fdo + + + END diff --git a/IBMDOS/FDOS.DEF b/IBMDOS/FDOS.DEF new file mode 100644 index 0000000..a0af919 --- /dev/null +++ b/IBMDOS/FDOS.DEF @@ -0,0 +1,126 @@ +; File : $FDOS.DEF$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG + +FD_DISKINFO equ 48h +FD_FLUSH equ 49h +FD_SELECT equ 4Ah +FD_EXEC equ 4Bh +FD_EXIT equ 4Ch +FD_FCB equ 4Dh +FD_COMMIT equ 50H +FD_NEW equ 51h +FD_LOCK equ 52h +FD_DDIO equ 54h +FD_EXPAND equ 55h +FD_REOPEN equ 58h + +FDOS_MAXPARM equ 7 ; Maximum FDOS Parameter Length (WORDS) + +FD_FUNC equ fdos_data + +FD_DRIVE equ fdos_data + 2 +FD_DPB equ dword ptr fdos_data + 4 +FD_DPBOFF equ fdos_data + 4 +FD_DPBSEG equ fdos_data + 6 +FD_ADJUST equ fdos_data + 8 + +FD_NAME equ dword ptr fdos_data + 2 +FD_NAMEOFF equ fdos_data + 2 +FD_NAMESEG equ fdos_data + 4 + +FD_MODE equ fdos_data + 6 + +FD_HANDLE equ fdos_data + 2 + +FD_BUF equ dword ptr fdos_data + 4 +FD_BUFOFF equ fdos_data + 4 +FD_BUFSEG equ fdos_data + 6 + +FD_COUNT equ fdos_data + 8 + +FD_OFFSET equ dword ptr fdos_data + 4 + +FD_METHOD equ fdos_data + 8 + +FD_FLAG equ fdos_data + 6 + +FD_ATTRIB equ fdos_data + 8 + +FD_PATH equ dword ptr fdos_data + 4 +FD_PATHOFF equ fdos_data + 4 +FD_PATHSEG equ fdos_data + 6 + +FD_ONAME equ dword ptr fdos_data + 2 +FD_ONAMEOFF equ fdos_data + 2 +FD_ONAMESEG equ fdos_data + 4 + +FD_NNAME equ dword ptr fdos_data + 10 +FD_NNAMEOFF equ fdos_data + 10 +FD_NNAMESEG equ fdos_data + 12 + +FD_SFLAG equ fdos_data + 4 +FD_DATE equ fdos_data + 6 +FD_TIME equ fdos_data + 8 + +FD_LENGTH equ dword ptr fdos_data + 8 +FD_LFLAG equ word ptr fdos_data + 12 + +FD_NEWHND equ fdos_data + 4 + +FD_FCBADR equ dword ptr fdos_data + 2 +FD_FCBOFF equ fdos_data + 2 +FD_FCBSEG equ fdos_data + 4 + +FD_FCBCNT equ fdos_data + 6 +FD_FCBFUNC equ fdos_data + 8 + +FD_PSPSEG equ fdos_data + 2 + +FD_BPBOFF equ fdos_data + 2 +FD_BPBSEG equ fdos_data + 4 +FD_DDSCOFF equ fdos_data + 6 +FD_DDSCSEG equ fdos_data + 8 + +FD_IOCTLFUNC equ fdos_data + 4 +FD_IOCTLSTAT equ fdos_data + 6 + +FD_NUMOPEN equ fdos_data + 2 + +FD_DDIO_DRV_OP equ fdos_data + 2 +FD_DDIO_NSECTORS equ fdos_data + 4 +FD_DDIO_STARTLOW equ fdos_data + 6 +FD_DDIO_STARTHIGH equ fdos_data + 8 +FD_DDIO_DMAOFF equ fdos_data + 10 +FD_DDIO_DMASEG equ fdos_data + 12 + diff --git a/IBMDOS/FDOS.EQU b/IBMDOS/FDOS.EQU new file mode 100644 index 0000000..f918335 --- /dev/null +++ b/IBMDOS/FDOS.EQU @@ -0,0 +1,227 @@ +; File : $FDOS.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +; +; Structure of Buffer Control Blocks +; ---------------------------------- +; These BCBs immediately preceed the data buffers. BCBs are +; always shared for all drives and therefore must be big +; enough for the largest drive. +; + +BCB_NEXT equ word ptr 00h ; link to next buffer +BCB_PREV equ word ptr 02h ; link to previous buffer +BCB_DRV equ byte ptr 04h ; drive of this buffer or 0FFh +BCB_FLAGS equ byte ptr 05h ; buffer flags +BCB_REC equ word ptr 06h ; low 16 bits of sector address +BCB_REC2 equ byte ptr 08h ; top 8 bits of record address +BCB_COPIES equ byte ptr 0Ah ; number of copies to write +BCB_SEPARATION equ word ptr 0Bh ; # sectors copies are apart +BCB_DDSC equ dword ptr 0Dh ; DWORD ptr to DDSC_ +BCB_REMOTE equ word ptr 11h ; remote in-use count +BCB_DATA equ byte ptr 14h ; buffer data + +BF_ISFAT equ 0002h ; buffer marked as FAT sector +BF_ISDIR equ 0004h ; buffer marked as Directory sector +BF_ISDAT equ 0008h ; buffer marked as Data sector +BF_DIRTY equ 0040h ; buffer marked as modified +BF_REMOTE equ 0080h ; buffer is remote + +MAX12 equ 0FF6h ; max. disk size w/ 12-bit media + +; Structure of Hash Control Block +; ------------------------------- +; Each hash control block refers to the hash codes of one +; disrectory cluster or a root directory. + +HCB_LINK equ word ptr 0 ; link to next control block +HCB_DRV equ byte ptr 2 ; drive for this entry or 0FFh +HCB_CLU equ word ptr 4 ; cluster number or 0000 if root +HCB_CNT equ word ptr 6 ; number of hashed entries +HCB_DATA equ word ptr 8 ; hash buffer data + + +; Structure of DOS FCB +; -------------------- +; This is hopefully consistent with what DOS stores in an +; open file control block for DOS 1.x functions + +MSF_EXTFLG equ byte ptr 0 ; if this is 0xFF, skip 1st 7 byte +MSF_ATTRIB equ byte ptr 6 ; file attributes if MSF_EXTFLG +MSF_DRIVE equ byte ptr 0 ; 1st byte normally drive code +MSF_NAME equ byte ptr 1 ; 8-bit ASCII file name, 11 characters +MSF_BLOCK equ word ptr 12 ; current block number +MSF_RECSIZE equ word ptr 14 ; current logical record size +MSF_SIZE equ word ptr 16 ; 32-bit file size +MSF_DATE equ word ptr 20 ; last date stamp +MSF_TIME equ word ptr 22 ; last time stamp +MSF_IFN equ byte ptr 24 ;; internal file number +MSF_IOCTL equ byte ptr 25 ;; file status +MSF_BLOCK1 equ word ptr 26 ;; 1st block of file +MSF_DBLK equ word ptr 28 ;; directory block +MSF_DEVPTR equ dword ptr 28 ;; address of device driver +MSF_DCNT equ word ptr 30 ;; directory count +MSF_CR equ byte ptr 32 ; current sequential record +MSF_RR equ word ptr 33 ; random record address (3 or 4 byte) +MSF_RR2 equ byte ptr 35 ; random record overflow + + +; Structure of DOS DPB +; -------------------- +; The layout of this structure is a guess based on +; examples. It is returned by PC MODE on functions 1Fh and +; 32h and is required by various disk-related utilities +; like disk editors and CHKDSK. + +DDSC_UNIT equ byte ptr 0 ; absolute drive number +DDSC_RUNIT equ byte ptr 1 ; relative unit number +DDSC_SECSIZE equ word ptr 2 ; sector size in bytes +DDSC_CLMSK equ byte ptr 4 ; sectors/cluster - 1 +DDSC_CLSHF equ byte ptr 5 ; log2 (sectors/cluster) +DDSC_FATADDR equ word ptr 6 ; sector address of FAT +DDSC_NFATS equ byte ptr 8 ; # of FAT copies +DDSC_DIRENT equ word ptr 9 ; size of root directory +DDSC_DATADDR equ word ptr 11 ; sector address of cluster #2 +DDSC_NCLSTRS equ word ptr 13 ; # of clusters on disk +DDSC_NFATRECS equ word ptr 15 ; # of sectors per FAT +DDSC_DIRADDR equ word ptr 17 ; sector address of root dir +DDSC_DEVHEAD equ dword ptr 19 ; device driver header +DDSC_DEVOFF equ word ptr 19 +DDSC_DEVSEG equ word ptr 21 +DDSC_MEDIA equ byte ptr 23 ; current media byte +DDSC_FIRST equ byte ptr 24 ; "drive never accessed" flag +DDSC_LINK equ dword ptr 25 ; next drive's DDSC +DDSC_BLOCK equ word ptr 29 ; next block to allocate +DDSC_FREE equ word ptr 31 ; total free clusters on drive +DDSC_LEN equ 33 + + + +; DELWATCH hooks called by OS + +DELW_RDMASK equ 0 ; delete dir search mask +DELW_DELETE equ 2 ; delete this dir entry +DELW_FREECLU equ 3 ; free some clusters +DELW_FREERD equ 4 ; free root dir entry +DELW_SPACE equ 5 ; add "deletes" to free space +DELW_NEWDISK equ 7 ; new disk logged in +DELW_PURGE equ 14 ; perge pd file +DELW_UNDEL equ 15 ; undelete pd file + +; SuperStore hook called by OS + +SSTOR_SPACE equ 10h ; enquire # physical free space + +; Password hooks called by OS + +PASSWD_CREAT equ 20h ; initialise an entry +PASSWD_CHMOD equ 21h ; change an entry +PASSWD_CHECK equ 22h ; check an entry + +; Share hooks in PCMODE data segment +; +; These point to a stub which does a "STC, RETF" +; + +NUM_SHARE_STUB_ENTRIES equ 15 + +S_LOCKS equ DWORD*0 ; share lock/unlock region +S_UPDATE equ DWORD*1 ; update DHNDL from share +S_RECORD equ DWORD*2 ; update share from DHNDL +S_FDOSRW equ DWORD*3 ; validate proposed operation +S_DISCARD equ DWORD*4 ; discard all files on drive +S_OPEN equ DWORD*5 ; files is opening, remember it +S_CLOSE equ DWORD*6 ; files is closing, forget it +S_OM_COMPAT equ DWORD*7 ; check open mode compatible +S_CLOSE_IF_OPEN equ DWORD*8 ; close if compat open, else deny +S_DENY_IF_OPEN equ DWORD*9 ; deny if open shared/by others +S_GET_LIST_ENTRY equ DWORD*10 ; get open file list entry +S_CLOSE_FILES equ DWORD*11 ; close all files for given PSP/UID + +; struct dirfcb + +DNAME equ byte ptr 0 ;file name & type +DATTS equ byte ptr 11 + DA_RO equ 01h ; 0x01 - read/only + DA_HIDDEN equ 02h ; 0x02 - hidden + DA_SYSTEM equ 04h ; 0x04 - system + DA_VOLUME equ 08h ; 0x08 - volume label + DA_DIR equ 10h ; 0x10 - sub-directory + DA_ARCHIVE equ 20h ; 0x20 - archive + DA_CLUSTER equ 80h ; 0x80 - return starting cluster from search (API extention) + DA_DELWATCH equ 80h ; 0x88 - return pending delete files + DA_FIXED equ 11011000b ; can't CHMOD label, dir, unused bits + DA_CHANGE equ not DA_FIXED ; all others are changeable + +;DATTS2 equ 12 ;CP/M attributes +; ; 0x80 - f1' modify default open rules +; ; 0x40 - f2' partial close default +; ; 0x20 - f3' ignore close checksum errors +; ; 0x10 - f4' disable checksums +; ; 0x08 - (reserved) +; ; 0x04 - DELETE password +; ; 0x02 - WRITE password +; ; 0x01 - READ password +DUNDEL equ 13 ;1st letter of deleted file +DPWD equ word ptr 14 ;16-bit password hash code +DMODTIME equ word ptr 16 ;delwatch time (hhhhhmmmmmmsssss) +DMODDATE equ word ptr 18 ;delwatch date (yyyyyyymmmmddddd) +;DRECSIZE equ 16 ;FlexOS record size +;DUSER equ 18 ;FlexOS user ID of creator +;DGROUP equ 19 ;FlexOS group ID of creator +DPWM equ word ptr 20 ;FlexOS access rights +DTIME equ 22 ;time (hhhhhmmmmmmsssss) +DDATE equ 24 ;date (yyyyyyymmmmddddd) +DBLOCK1 equ 26 ;first block in file +DSIZE equ 28 ;current file size + +; DOS Media Password Definitions +; ------------------------------ + +PWM_OWNER equ 000Fh ; PWD Owner mask +PWM_GROUP equ 00F0h ; PWD Group mask +PWM_WORLD equ 0F00h ; PWD World mask +PWM_R equ 0888h ; PWD required for reading +PWM_W equ 0444h ; PWD required for writing +PWM_E equ 0222h ; PWD req'd for executing +PWM_D equ 0111h ; PWD required for deleting +PWM_ANY equ PWM_R+PWM_W+PWM_D ; PWD required for anything + + +; literal constants + +FAT12 equ 00fffh ; 12 bit fat +FAT16 equ 0ffffh ; 16 bit fat + +ENDDIR equ 0ffffh ;end of directory + diff --git a/IBMDOS/FIOCTL.A86 b/IBMDOS/FIOCTL.A86 new file mode 100644 index 0000000..adcd351 --- /dev/null +++ b/IBMDOS/FIOCTL.A86 @@ -0,0 +1,503 @@ +title 'FDOS IOCTL - DOS file system input/output control' +; File : $FIOCTL.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; $Log$ +; FIOCTL.A86 1.18 93/12/09 23:39:17 +; Move non-inherited bit to correct place in file handle +; FIOCTL.A86 1.17 93/11/03 13:38:29 +; Int 21 4409 return 0x0080 if drive is joined +; FIOCTL.A86 1.16 93/11/02 18:04:17 +; Int21/4400 from file returns AH=0 +; FIOCTL.A86 1.15 93/09/14 20:03:15 +; Trust LFLG_PHYSICAL +; FIOCTL.A86 1.12 93/06/17 22:11:50 +; support for ioctl 10/11 query ioctl support +; FIOCTL.A86 1.11 93/06/16 16:21:37 +; Codepage preparation bug fixed +; ENDLOG + +; Date Modification +; --------- --------------------------------------- +; 29 Jun 89 Initial version splits from FDOS +; 21 Nov 89 iocE/F use relative unit number +; 12 Dec 89 ioc2/3 zero the unused portions of req hdr +; save a few bytes in other ioc's while I'm here +; 4 Jun 90 default file access permissions and user group support +; 5 Jun 90 ioc0/1 tidied up +; 12 Jun 90 get_doshndl parameter in BX not AX +; 2 Oct 90 net_vec moves to per-VC basis (info held in CCB_) +; 13 feb 91 ioc1 tests FHIO_DEV, not HM_DEV, (123 MSNet printing) +; 7 may 91 ioc2,ioc3,ioc6,ioc7,iocC destabilised for Lanstatic +; by-product is ioc6 for disks returns read-ahead char +; in AH +; 28 feb 92 ioctl C checks bit 6 not bit 14 in DH_ATTRIB +; 3 aug 92 ioctl C/D pass thru' SI/DI +; 5 aug 92 substatial ioctl rework saves a few bytes - ioctl +; request header now built by PCMODE + + eject ! include i:fdos.equ + eject ! include rh.equ + eject ! include i:msdos.equ + eject ! include i:mserror.equ + eject ! include i:doshndl.def ; DOS Handle Structures + eject ! include i:driver.equ + eject ! include i:f52data.def ; DRDOS Structures + eject + + +PCMODE_DATA dseg BYTE + extrn ioctlRH:byte ; request header is build in PCMODE + ; data area + +BDOS_DATA dseg word + extrn fdos_pb:word + extrn fdos_ret:word + extrn last_drv:byte + extrn req_hdr:byte +if PASSWORD + extrn global_password:word +endif + +BDOS_CODE cseg + + extrn local_disk:near + extrn device_driver:near + extrn block_device_driver:near + extrn fdos_error:near + extrn fdos_ED_DRIVE:near + extrn fdos_ED_FUNCTION:near + extrn fdos_read:near + extrn get_ddsc:near + extrn vfy_dhndl_ptr:near + extrn get_pb2_drive:near + extrn ioc6_dev:near ; IOCTL(6): input status for device + extrn ioc7_dev:near ; IOCTL(7): output status for device + extrn vfy_dhndl_ptr:near + extrn verify_handle:near + extrn reload_registers:near +if JOIN + extrn get_ldt:near +endif +if PASSWORD + extrn hash_pwd:near +endif + + public fdos_ioctl + +eject +; INPUT/OUTPUT CONTROL (IOCTL) + +; +----+----+----+----+----+----+----+----+----+----+ +; | 26 | param | func | request header | +; +----+----+----+----+----+----+----+----+----+----+ + + +; entry: +; ------ +; param: handle/drive on some functions +; func: sub function (0-A) +; request header: far pointer to IOCTL request header + +; exit: +; ----- +; AX: return code or error code ( < 0) +; param: return value from some functions + + + +ioctl_tbl dw ioctl0 ; 0-get handle status + dw ioctl1 ; 1-set handle status + dw ioctl2 ; 2-receive control string (handle) + dw ioctl3 ; 3-send control string (handle) + dw ioctl4 ; 4-receive control string (drive) + dw ioctl5 ; 5-send control string (drive) + dw ioctl6 ; 6-input status + dw ioctl7 ; 7-output status + dw ioctl8 ; 8-removable media check + dw ioctl9 ; 9-networked drive check + dw ioctlA ; A-networked handle check +if PASSWORD + dw ioctl54 ; B-set global password +else + dw device_ED_FUNCTION +endif + dw ioctlC ; C-code page support + dw ioctlD ; D-generic IOCTL disk i/o + dw ioctlE ; E-get logical drive + dw ioctlF ; F-set logical drive + dw ioctl10 ; 10-query IOCTL for char devs + dw ioctl11 ; 11-query IOCTL for disks + +NUM_IOCTL equ (offset $ - offset ioctl_tbl)/WORD + + + +fdos_ioctl: +;---------- + mov bx,2[bp] ; BX -> parameter block + mov bx,4[bx] ; get I/O control subfunction + cmp bx,NUM_IOCTL ; is it in the supported range? + jae device_ED_FUNCTION ; skip if value too large + shl bx,1 ; else make it word index + jmp ioctl_tbl[bx] ; call the right function +device_ED_FUNCTION: + mov bx,ED_FUNCTION ; "invalid function" + ret + + + +ioctl0: ; get device status +;------ +; Note: We store the binary flag for the standard console +; handles in the console mode, not in the file handle, +; as the handles are shared across all consoles... + + call vfy_dhndl_ptr ; check if good handle + mov ax,es:DHNDL_WATTR[bx] ; get attrib from doshndl + test ah,DHAT_REMOTE/256 + mov ah,0 ; files/networks return 0 in AH/DH + jnz device_OK ; return attrib if network device + test al,DHAT_DEV ; or a file + jz device_OK + les bx,es:DHNDL_DEVPTR[bx] ; get real device driver address + mov ah,es:byte ptr 5[bx] ; get device driver attribute +; jmp device_OK + +device_OK: +;--------- + mov bx,2[bp] ; get parameter block address + mov 6[bx],ax ; save returned status + xor bx,bx ; successful return code + ret + +ioctl1: ; set device status +;------ + call vfy_dhndl_ptr ; make sure this is an open handle + test es:DHNDL_WATTR[bx],DHAT_DEV + jz device_ED_FUNCTION ; can't set status of disk files + mov ax,word ptr ioctlRH+14 + ; pick up new device status + test ah,ah ; test if high byte is zero + jnz device_ED_FUNCTION ; skip if O.K. + or al,DHAT_DEV ; make sure it stays a device + mov es:DHNDL_ATTR[bx],al ; store ioctl state in doshndl + jmps device_OK ; success + + +ioctl2: ; receive control string (devicehandle) +;------ +ioctl3: ; send control string (device handle) +;------ +ioctlC: ; generic ioctl (device handle) +;------ +ioctl10: ; query ioctl support (device handle) +;------- + call vfy_dhndl_ptr ; check file handle # + call local_disk ; get MXdisk + call verify_handle ; make sure the handle is good + jnc short_fdos_ED_FUNCTION ; and is for a DEVICE + xor cx,cx ; device relative unit # always zero + les si,es:DHNDL_DEVPTR[bx] ; ES:SI -> device driver + jmps ioc2345CDcommon ; now use common code + +ioctl4: ; receive control string (drive) +;------ +ioctl5: ; send control string (drive) +;------ +ioctlD: ; generic ioctl (drive) +;------ +ioctl11: ; query ioctl support (drive) +;------- + call local_disk ; get MXdisk, switch stack + call get_pb2_ddsc ; get drives DDSC_ + mov cl,es:DDSC_RUNIT[bx] ; get relative unit # + les si,es:DDSC_DEVHEAD[bx] ; ES:SI -> device header +; jmps ioctl2345Common ; now use common code + +ioc2345CDcommon: +;--------------- +; On Entry: +; ES:SI -> device driver header +; CL = media byte (0 if character device) +; CH = relative unit (0 if character device) +; MXDisk obtained +; On Exit: +; IOCTL performed +; + mov ax,fdos_pb+6 ; device driver support required + test es:DH_ATTRIB[si],ax ; does device driver support function ? + jz short_fdos_ED_FUNCTION + push ds + push es ! pop ds ; DS:SI -> device driver + push ss ! pop es + mov bx,offset ioctlRH ; ES:BX -> request header + mov es:RH_UNIT[bx],cl ; set relative unit for block devices + call device_driver ; call the device driver + pop ds ; check for errors on return +; jmp fdos_error_check + +fdos_error_check: +;------------- +; On Entry: +; AX = Req Status +; On Exit: +; SIGN set if an error, AX&BX = Internal DOS error code +; + test ax,ax ; top bit == 1 if error + jns fdos_ioc_ec10 ; skip if no errors + xor ah,ah + add ax,-ED_PROTECT + neg ax + jmp fdos_error ; return critical error +fdos_ioc_ec10: + ret + +; IOCTL subfunctions: + + +get_pb2_ddsc: +;------------ +; On Entry: +; local_disk called, pick us drive from pb2 +; On Exit: +; ES:BX -> DDSC_ for the drive +; + call get_pb2_drive ; get specified drive + cmp al,last_drv ; is it a valid drive + ja bad_drive + call get_ldt ; ES:BX -> LDT for this drive + jc get_pb2_ddsc10 ; no LDT, physical=logical + mov ax,es:LDT_FLAGS[bx] + test ah,LFLG_NETWRKD/256 + jnz short_fdos_ED_FUNCTION ; reject network drives + test ah,LFLG_PHYSICAL/256 + jz bad_drive + test ah,LFLG_JOINED/256 + jnz bad_drive ; reject JOIN'd drives + mov al,es:LDT_NAME[bx] ; get physical drive from LDT + and al,1Fh ; convert to 1 based drive + dec ax ; make that zero based +get_pb2_ddsc10: + call get_ddsc ; ES:BX -> DDSC_ + jc bad_drive ; or does it? + ret + +bad_drive: + jmp fdos_ED_DRIVE ; invalid drive specified + +short_fdos_ED_FUNCTION: + jmp fdos_ED_FUNCTION + + +ioctl8: ; removable media check +;------ + call local_disk ; get MXdisk, switch stack + call get_pb2_ddsc ; get drives DDSC_ + push ds + lds si,es:DDSC_DEVHEAD[bx] ; DS:SI -> device driver + test ds:DH_ATTRIB[si],DA_REMOVE + pop ds ; do we support the check ? + jz short_fdos_ED_FUNCTION ; if we don't then don't ask + mov req_hdr,RH15_LEN + mov req_hdr+2,CMD_FIXED_MEDIA + call block_device_driver ; call the device driver + js short_fdos_ED_FUNCTION + and ax,RHS_BUSY ; BUSY bit set if permanent - we just + xchg ah,al ; need to get bit in the right place + shr ax,1 ; now 1 if permanent media + mov fdos_pb+6,ax ; return status removable (=0) +ioctl8_10: + ret + + + +ioctl6: ; file input status +;------ + call vfy_dhndl_ptr ; make sure this is an open handle + mov ax,es:DHNDL_WATTR[bx] + test ax,DHAT_REMOTE + jnz ioctl6_10 ; always ask networked handles + test ax,DHAT_DEV + jz ioctl6_10 ; files are always askable + jmp ioc6_dev + +ioctl6_10: ; disk files/network devices + push es:DHNDL_POSLO[bx] ; save current position in file + push es:DHNDL_POSHI[bx] ; so we can read ahead + push es + push bx ; save DHNDL_ too.. + push bp ; save stack frame + mov si,2[bp] ; SI -> parameter block + mov ax,1 + push ax ; read 1 byte ahead + push ds ; use fdos_pb as read-ahead + lea ax,6[si] ; buffer + push ax + push ds:word ptr 2[si] ; user file number + mov ax,MS_X_READ ; READ function #, so we create + push ax ; a dummy fdos_pb + mov bx,sp ; SS:BX -> dummy fdos_pb + mov cx,offset ioctl6_20 ; CX -> return address + push cx ; Return to here + push ss ; save parameter segment + push bx ; save parameter offset + push ax ; save sub-function + mov bp,sp ; SS:BP -> working variables + call fdos_read ; make FDOS_READ do the hard word + add sp,4*WORD ; discard param's on stack +ioctl6_20: + add sp,4*WORD ; discard most of dummy fdos_pb + pop cx ; return # read + cmp bx,ED_LASTERROR ; did we succeed ? + jb ioctl6_30 ; if so we can trust # read + xor cx,cx ; else in error assume nothing +ioctl6_30: + pop bp ; recover stack frame + pop bx ; rewind DHNDL_POS to where + pop es + pop es:DHNDL_POSHI[bx] ; it was before we started + pop es:DHNDL_POSLO[bx] + mov ax,1a00h ; assume not ready + jcxz ioctl6_40 + dec ax ; AL = FF, ie. ready + mov si,2[bp] ; SI -> parameter block + mov ah,ds:byte ptr 6[si] ; get character we read +ioctl6_40: + jmp device_OK + + +ioctl7: ; file output status +;------ + call vfy_dhndl_ptr ; make sure this is an open handle + mov ax,0FFh ; assume it's networked/disk + mov dx,es:DHNDL_WATTR[bx] + test dx,DHAT_REMOTE + jnz ioctl6_40 ; networked handles are always ready + test dx,DHAT_DEV + jz ioctl6_40 ; files are always ready + jmp ioc7_dev ; devices we ask... + + + +ioctl9: ; networked drive check +;------ + call local_disk ; get disk semaphore + call get_pb2_drive ; get specified drive + call get_ldt ; ES:BX -> LDT for this drive + jc ioctl940 + mov ax,es:LDT_FLAGS[bx] + test ah,LFLG_NETWRKD/256 + jz ioctl910 +if 1 + mov ax,1000h ; return drive as remote +else + les di,es:LDT_PDT[bx] ; pick up network internal pointer + mov ax,es:4[di] ; pick up garbage + or ah,10h ; return drive as remote +endif + jmps ioctl930 + +ioctl910: + test ah,LFLG_PHYSICAL/256 + jz ioctl940 + test ah,LFLG_SUBST/256 + xchg ax,dx ; save flags + mov ax,8000h ; assume it's SUBST'd + jnz ioctl920 + test dh,LFLG_JOINED/256 + xchg al,ah ; assume it's JOIN'd + jnz ioctl930 + xor ax,ax ; clear if not +ioctl920: + push ax + call get_pb2_ddsc ; get drives DDSC_ + pop ax + les si,es:DDSC_DEVHEAD[bx] ; ES:SI -> device driver + or ax,es:4[si] ; get device attributes +ioctl930: + mov fdos_pb+6,ax ; return updated status + ret + +ioctl940: + jmp fdos_ED_DRIVE ; return ED_DRIVE error + + +ioctlA: ; networked handle check +;------ + call vfy_dhndl_ptr + mov ax,es:DHNDL_WATTR[bx] + jmp device_OK ; return attributes + + +ioctlE: +;------ + call local_disk + mov al,CMD_GET_DEVICE ; get logical device + jmps iocEFcommon ; common code for IOCTL(E)/IOCTL(F) + +ioctlF: +;------ + call local_disk + mov al,CMD_SET_DEVICE ; set logical device +iocEFcommon: + mov req_hdr,RH24_LEN + mov req_hdr+2,al + call get_pb2_ddsc ; get drives DDSC_ + inc ax ; make drive one-relative + mov req_hdr+13,al ; set this as new drive + xor ax,ax ; assume not supported + push ds + lds si,es:DDSC_DEVHEAD[bx] ; does device driver support function ? + test ds:DH_ATTRIB[si],DA_GETSET + pop ds + jz iocF_single ; skip if not supported + call block_device_driver ; call the device driver + call fdos_error_check ; return any errors + mov al,req_hdr+1 ; get returned drive +iocF_single: ; AX = return value + mov ah,7 + mov fdos_pb+6,ax ; return the drive + ret + +if PASSWORD + +ioctl54: ; set global password +;------- + call local_disk ; get the MX disk + push ds + lds si,dword ptr ioctlRH+14 + call hash_pwd ; encrypt new default password + pop ds + mov global_password,ax + ret + +endif + +end diff --git a/IBMDOS/FUNCS.FDO b/IBMDOS/FUNCS.FDO new file mode 100644 index 0000000..1a3f7f8 --- /dev/null +++ b/IBMDOS/FUNCS.FDO @@ -0,0 +1,2394 @@ +; File : $FUNCS.FDO$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History ***; +; $Log$; +; ENDLOG +; General function include module for FDOS.A86 + +BDOS_CODE cseg + + public fdos_entry + +;========== +fdos_entry: ; FDOS module entry point +;========== +; On Entry: +; DS:DX -> parameter block +; On exit: +; AX = BX = return code +; (DS/ES corrupted) +; entry: DS:DX = argument +; +; exit: AX,BX = return code + + mov si,dx + lodsw ; AX = FDOS number + sub ax,39h ; base it at zero + jc fd_error ; stop if too low + cmp ax,FDOS_MAX ; check if function in range + jae fd_error ; yes, continue + + push ds ; save parameter segment + push dx ; save parameter offset + push ax ; save sub-function + mov bp,sp ; SS:BP -> working variables + mov bx,ax + add bx,ax + add bx,ax + call fdos_tbl[bx] + add sp,3*WORD ; clean up stack + mov ax,bx + ret + +fd_error: + mov ax,ED_FUNCTION ; return "invalid function" + mov bx,ax + ret + + +fdos_tbl dw fdos_mkdir ; 39-make directory + db 2 + dw fdos_rmdir ; 3A-remove directory + db 2 + dw fdos_chdir ; 3B-change directory + db 2 + dw fdos_creat ; 3C-create file + db 4 + dw fdos_open ; 3D-open file + db 4 + dw fdos_close ; 3E-close file + db 1 + dw fdos_read ; 3F-read from file + db 4 + dw fdos_write ; 40-write to file + db 4 + dw fdos_unlink ; 41-delete file + db 4 + dw fdos_lseek ; 42-set file pointer + db 4 + dw fdos_chmod ; 43-get/set file attributes + db 6 + dw fdos_ioctl ; 44-IOCTL emulation + db 3 + dw fdos_dup ; 45-duplicate handle + db 2 + dw fdos_fdup ; 46-force duplicate handle + db 2 + dw fdos_curdir ; 47-get current directory + db 3 + dw fdos_getdpb ;*48*disk information + db 4 + dw fdos_flush ;*49*flush buffers + db 0 + dw fdos_select ;*4A*drive select + db 1 + dw fdos_exec ;*4B*create child PSP + db 1 + dw fdos_exit ;*4C*close child PSP + db 0 + dw fdos_fcb ;*4D*generic FCB call + db 5 + dw fdos_first ; 4E-find first matching file + db 4 + dw fdos_next ; 4F-find next matching file + db 0 + dw fdos_commit ;*50*commit file + db 1 + dw fdos_mknew ;*51*make new file + db 4 + dw fdos_lock ;*52*lock/unlock block + db 6 + dw fdos_mkddsc ; 53 build DDSC from BPB + db 4 + dw fdos_ddio ;*54*Int 25/26 emulation + db 6 + dw fdos_expand ;*55*expand file name + db 6 + dw fdos_move ; 56-rename file + db 6 + dw fdos_dattim ; 57-get/set file name + db 4 + dw fdos_reopen_fcb ; 58-FCB reopen support function + db 5 + +FDOS_MAX equ (offset $ - offset fdos_tbl) / 3 + + Public local_disk + +local_disk: ; continue execution within MXdisk semaphore +;---------- +; This function will make local copies of the parameters +; and continue + + callf ss:lock_tables + pop fdos_addr ; return address + add sp,2*WORD ; discard return from call fdos_tbl[bx] + ; and function # + pop si ; get parameter offset + pop ax ; get parameter segment + mov sp_save,sp ; save for re-entry/errors + mov ds,ax ; DS:SI -> paremeter block +fdos_reenter: + push ss ! pop es ; ES = local data segment + mov di,offset fdos_pb ; ES:DI -> local parameter block copy + lodsw ! stosw ; load subfunction number + mov es:fdos_info,si ; save it for BDOS return + mov es:fdos_info+WORD,ds ; save parameter segment for return + mov bx,ax + add bx,ax + add bx,ax ; BX = function # * 3 + mov cl,byte ptr fdos_tbl-(39h*(WORD+BYTE))+WORD[bx] + mov ch,0 + ; get table of # of parameters + mov es:fdos_info+2*WORD,cx ; save the parameter count + rep movsw ; copy parameter block + push es ! pop ds ; DS = SYSDAT + mov ioexerr,0FFh ; assume default error code + mov rwmode,0 + + mov finddfcb_mask,DA_VOLUME*256 + + xor ax,ax + mov fdos_ret,ax ; assume success unless proven otherwise + call fdos_addr ; call code following "call local_disk" + mov ax,fdos_ret ; get return code, fall thru to exit + + Public fdos_error + +fdos_error: +;---------- +; AX = return code + mov sp,sp_save ; stack to entry value (for errors) + mov si,offset fdos_pb+2 ; get local copy + les di,dword ptr fdos_info ; get parameter block address + mov cx,fdos_info+2*WORD ; get parameter block size + rep movsw ; copy return values + mov bx,ax + callf ss:unlock_tables + ret ; return to BDOS, which copies BX to AX + + Public fdos_restart + +fdos_restart: ; we want to restart the function after an error +;------------ ; we already have MXdisk +; + mov sp,sp_save ; break out from low levels + lds si,dword ptr fdos_info + dec si ! dec si ; DS:SI -> parameter block + jmps fdos_reenter ; try from scratch + +fdos_ED_ROOM: +;----------- + mov ax,ED_ROOM ; no more files + jmps fdos_error + +fdos_ED_DRIVE: +;----------- + mov ax,ED_DRIVE ; bad drive + jmps fdos_error + +fdos_ED_PATH: + mov ax,ED_PATH ; invalid path or drive + jmps fdos_error + +fdos_ED_PROTECT: + mov ax,ED_PROTECT ; write protect error + jmps fdos_error + + Public fdos_ED_ACCESS + +fdos_ED_ACCESS: + mov ax,ED_ACCESS ; access denied error + jmps fdos_error + +eject +; MAKE DIRECTORY (MKDIR) + +; +----+----+----+----+----+----+ +; | 39 | name | +; +----+----+----+----+----+----+ + +; entry: +; ------ +; name: segmented address of ASCIIZ name + +; exit: +; ----- +; AX: 0000 or error code ( < 0) + +fdos_mkdir: +;---------- + call redir_asciiz_offer + call local_disk ; get MXdisk, switch stack + call path_prep_chk ; parse path, walk down the tree + call finddfcbf ; find matching FCB + jnz mkdir_access ; file/dir exists, "access denied" + call allocdir ; allocate a directory entry + + push ax ; save pointer to directory entry + lea si,info_fcb+1 ; SI -> file name + xchg ax,di ; DI -> DNAME + mov cx,11 + rep movsb ; copy file name into directory buffer +; lea di,DATTS[si] + mov al,DA_DIR + stosb ; mark it as a directory + xor ax,ax + mov cx,(32-12) + rep stosb ; zero remainder of new FCB + pop si ; SI -> directory + + call stamp_dir_entry ; set time and date in FCB + xor ax,ax + call alloc_cluster ; Allocate a block + jc mkdir_err ; Report Error(no room on disk) + mov si,dirp + mov DBLOCK1[si],ax ; Initialize 1st block of fcb + push ax ; save block + call update_fat ; Write the fat to disk + call update_dir ; Write the directory to disk + pop ax ; now initialise the sub-directory + call mkdir_init ; '.' and '..' entries + call update_dir ; update directory entry + mov ax,5 ; return a magic value for some + mov fdos_ret,ax ; PD expansion program + ret + +mkdir_err: +;--------- + mov bx,dirp ; can't make dir, no data space + mov DNAME[bx],0E5h ; so release our directory entry + call update_dir ; release this entry +mkdir_access: + jmp fdos_ED_ACCESS ; return "access denied" error + +chk_no_dot: ; reject "." and ".." names + cmp info_fcb+1,'.' + je mkdir_access + ret + +eject +; REMOVE DIRECTORY (RMDIR) + +; +----+----+----+----+----+----+ +; | 3A | name | +; +----+----+----+----+----+----+ + +; entry: +; ------ +; name: segmented address of ASCIIZ name + +; exit: +; ----- +; AX: 0000 or error code ( < 0) + +fdos_rmdir: +;---------- + call redir_asciiz_offer + call local_disk ; get MXdisk, switch stack + call path_prep_chk ; parse path to bottom level + call finddfcbf ; try to locate directory entry + jz fdos_rmdir20 ; skip if we can't find it + test DATTS[bx],DA_DIR ; check directory attribute + jz fdos_rmdir30 ; O.K. if a directory + call chkcds ; make sure no-where current + jnc fdos_rmdir40 + call path_prep ; redo as rmdir_ok may destroy info + call finddfcbf ; find the entry again + call rmdir_ok ; make sure not in use + call finddfcbf ; find the entry again +if PASSWORD + call check_pwd_any +endif +kill_entry: + call kill_file ; actually delete entry +update_dir_fat: + call update_dir ; update directory entry + jmp update_fat ; update file allocation table + +fdos_rmdir20: + jmp fdos_ED_PATH ; "invalid path" + +fdos_rmdir30: + jmp fdos_ED_ACCESS ; "access denied" + +fdos_rmdir40: + mov ax,ED_DIR + jmp fdos_error + +eject +; CHANGE DIRECTORY (CHDIR) + +; +----+----+----+----+----+----+ +; | 3B | name | +; +----+----+----+----+----+----+ + +; entry: +; ------ +; name: segmented address of ASCIIZ name + +; exit: +; ----- +; AX: 0000 or error code ( < 0) + + +chdir_ED_PATH: + jmp fdos_ED_PATH ; all logical errors give "no path" + +chdir_ED_DRIVE: + mov ax,ED_DRIVE ; bad drive error message +chdir_err: + jmp fdos_error + +fdos_chdir: +;---------- + call redir_asciiz_offer + call local_disk ; get MXdisk, switch stack +fdos_move_chdir: +;--------------- + mov orig_drive,0FFFFh ; set drive to invalid + les di,dword ptr fdos_pb+2 ; get string address + call get_path_drive ; from asciiz or default + jc chdir_ED_DRIVE ; continue if drive A: - Z: + call islocal ; reject networked drives + jc chdir_ED_DRIVE ; as bad drives + call path_prep_cont ; continue if drive legal + jc chdir_err ; return error to application + call chk_no_dev ; no devices allowed + call chk_no_wild ; no wild cards allowed here + cmp orig_drive,0FFFFh ; check if assign to specified drive + jne chdir10 ; skip drive specified + mov ax,path_drive ; else same as path drive + mov orig_drive,ax +chdir10: +if JOIN + call offer_join ; are we opening a JOIN'd drive ? + jnc chdir30 ; if so move to it and skip open_dir +endif + call chk_for_root ; check if we are in the root + je chdir30 ; if so, just skip the open_dir + call finddfcbf ; try to locate directory entry + jz chdir_ED_PATH ; skip if no valid directory + test DATTS[bx],DA_DIR ; check directory attribute + jz chdir_ED_PATH ; return if not a directory +if PASSWORD + call check_pwd_any ; check if PW prot'd & wrong PW +endif + call open_dir ; else open last directory + jc chdir_ED_PATH ; return an error if we can't +chdir30: + mov ax,orig_drive ; get logical drive + call get_ldt ; ES:BX -> LDT_ + jc chdir10 ; no LDT_, must be init time... + mov si,es:LDT_FLAGS[bx] ; normally we inherit parents + mov cx,es:LDT_ROOTLEN[bx] ; root block and drive + mov dx,es:word ptr LDT_NAME[bx] + mov bx,es:LDT_ROOT[bx] ; if it's a "SUBST I: C:\PATH" form + cmp ax,path_drive ; we pick up new root and drive + je chdir50 ; like this + mov ax,path_drive ; ASCII drive from path drive + mov dx,'A'+256*':' ; make it into ASCII "C:" + add dx,ax ; in case LDT does not exist + call get_ldt ; get LDT_ in case it's subst'd + jc chdir40 + mov dx,es:word ptr LDT_NAME[bx] +chdir40: + mov bx,fdos_hds_blk ; root block from fdos_hds +chdir50: + mov di,offset pri_pathname ; build new LDT_ here + or si,LFLG_PHYSICAL ; drive is always physical + mov LDT_FLAGS[di],si + mov LDT_ROOTLEN[di],cx ; inherit rootlen from parent + mov LDT_ROOT[di],bx ; root as above + mov ax,fdos_hds_blk ; current block from HDS + mov LDT_BLK[di],ax + mov al,fdos_hds_drv ; current drive we from HDS + mov LDT_DRV[di],al + mov ax,word ptr current_ddsc + mov word ptr LDT_PDT[di],ax + mov ax,word ptr current_ddsc+WORD + mov word ptr LDT_PDT+WORD[di],ax + push ss ! pop es ; now build ASCII path +; lea di,LDT_NAME[di] ; ES:DI -> name + xchg ax,dx + stosw ; plant 'A:' + mov ax,'\' + stosw ; make that 'A:\',0 + dec di ; point at NUL + mov fdos_hds_root,0 ; we want to go back to root + mov fdos_pb+6,di ; rebuild into LDT_ at the address + mov fdos_pb+8,es + push ds ! pop es +chdir60: + call hdsblk ; get current block +if JOIN + jnz chdir65 ; if not at root unparse + call check_join ; check if drive is joined to another + jz chdir80 ; at root, unJOIN'd, so exit + ; we are at the root of this drive + xchg al,fdos_hds_drv ; update HDS drive so we can force + push es ; an exit next time round + call get_ldt ; now copy the JOIN'd name + push ds ! push es ! pop ds ! pop es + lea si,LDT_NAME+3[bx] ; point to my JOIN data + mov di,offset save_area + call copy_asciiz + push es ! pop ds + pop es + jmps chdir70 ; copy this into place +chdir65: +else + jz chdir80 ; if at root, we're done +endif + call parent2save_area ; parental name written in save_area +chdir70: + dec di ; DI -> '\0' at end + mov al,'\' ! stosb ; add a trailing backslash + sub di,offset save_area+1 + mov dx,di ; DX = length of name + + push es ; insert name into user buffer + les di,dword ptr fdos_pb+6 + mov al,0 ! scasb ; check if first directory + je chdir75 ; if not 1st in path + inc dx ; we need space for '\' +chdir75: + dec di ; adjust for scan + call mkspace_parent ; move ES:DI up by DX bytes + mov di,fdos_pb+6 ; ES:DI -> user buffer + rep movsb ; copy directory into user buffer + pop es ; ES = local segment again + jmp chdir60 ; try again til root + +chdir80: ; arrive here when root reached + mov ax,orig_drive ; get logical drive + call get_ldt ; ES:BX -> LDT_ + jc chdir85 ; no LDT_, what happended ? + push ds + mov di,bx ; ES:DI -> destination LDT_ + push ss ! pop ds + mov si,offset pri_pathname ; DS:SI -> new LDT_ we just built + mov cx,LDT_LEN + rep movsb ; copy the new LDT_ into place + pop ds + cmp ax,path_drive ; if the drive's are same + je chdir85 ; "CD" or "SUBST d:=d:path" + or es:LDT_FLAGS[bx],LFLG_SUBST + lea di,LDT_NAME[bx] ; ES:DI -> name + xor ax,ax + mov cx,LDT_FLAGS-LDT_NAME ; name can be this long + repne scasb ; look for terminating NUL + sub di,bx ; get # chars skipped + dec di ; forget the NUL + cmp di,3 ; root is special case again ! + jbe chdir85 + mov es:LDT_ROOTLEN[bx],di ; set new root position +chdir85: + ret + +eject +; CREATE FILE (CREAT) + +; +----+----+----+----+----+----+----+----+----+----+ +; | 3C | name | mode | attrib | +; +----+----+----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; name: segmented address of ASCIIZ name +; mode: open mode for handle +; attrib: attribute for file + +; exit: +; ----- +; AX: file handle or error code ( < 0) + +fdos_creat: +;---------- + call redir_asciiz_dev_offer ; offer it as a network device + call asciiz_dev_offer ; offer it as a local device + call redir_asciiz_file_offer ; offer it as a network file + call local_disk ; get MXdisk, switch stack + call mustbe_free_handle ; make sure we have spare handle + call path_prep ; parse path, walk down the tree + call check_device ; is it a device ? + jc creat_disk + jmp open_dev ; open as a device handle +creat_disk: + call chk_no_dot_or_wild + test byte ptr fdos_pb+8,DA_VOLUME + jz creat_nolbl ; skip if not volume label + call mustbe_nolbl ; do we have an existing label ? + jmps creat_new_file ; no, create one +creat_nolbl: + call finddfcbf ; find entry, ignore labels + jz creat_new_file ; skip if it doesn't exist yet + + call check_no_dir ; make sure not a directory + call check_ro ; check if file is read/only + call close_if_open ; make sure not open by any process +if PASSWORD + call check_pwd_d ; check if PW req'd & supplied +endif + mov bx,dirp + mov ax,DBLOCK1[bx] ; release all blocks of the file + call delfat ; so it is truncated to zero size + call update_fat ; update file allocation table + jmps creat2 ; reinitialize directory entry + +creat_new_file: ; create new file - shared by MKNEW + call allocdir ; allocate a directory entry +creat2: + mov bx,dirp ; BX -> directory entry + lea di,DNAME[bx] ; DI -> name offset in dir buffer + mov si,offset info_fcb+1 ; SI -> name offset in FCB + mov cx,11 + rep movsb ; copy name into directory + mov ax,fdos_pb+8 ; get creation file attribute + mov dx,fdos_pb+6 ; open in r/w, compatibilty mode + test al,not (DA_RO+DA_SYSTEM+DA_HIDDEN+DA_ARCHIVE) + jz creat5 ; allow r/o, hidden, system, archive + test al,DA_VOLUME ; failure as file, creating a label? + jz creat_access_err ; no, then it's really a problem + mov dl,DHM_RO+DHM_LOCAL ; open in compatibility mode +creat5: + or al,DA_ARCHIVE ; always create as new file + stosb ; update directory attributes + sub ax,ax ; zero out remainder of entry + mov cx,32-12 + rep stosb ; zero remainder of entry + + push bx ; save dirp + push dx ; save the open mode + call stamp_dir_entry ; set time and date in FCB + call update_dir ; update directory + pop ax ; restore open mode + pop bx ; restore dirp + jmp creat_handle ; now allocate file handle + +creat_access_err: + jmp fdos_ED_ACCESS ; return "access denied" + + +eject +; OPEN FILE (OPEN) + +; +----+----+----+----+----+----+----+----+----+----+ +; | 3D | name | mode | attrib | +; +----+----+----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; name: segmented address of ASCIIZ name +; mode: open mode +; attrib: file attrib for search (default = 16h) + +; exit: +; ----- +; AX: file handle or error code ( < 0) + +fdos_open: +;--------- + call redir_asciiz_dev_offer ; offer it as a network device + call asciiz_dev_offer ; offer it as a local device + call redir_asciiz_file_offer ; offer it as a network file + call local_disk ; get MXdisk, switch stack + call mustbe_free_handle ; make sure we have spare handle + call path_prep ; parse the path, go to bottom level + call check_device + jc open_disk + jmp open_dev ; open as a device +open_disk: + call chk_no_wild ; we don't allow no wild cards here + call finddfcbf ; search by name + jz open8 ; bail out if not found + mov al,byte ptr fdos_pb+8 ; check requested attributes +if PASSWORD + cmp word ptr DPWD[bx],0 + je open1 + or al,DA_HIDDEN +open1: +endif + not al + and al,DA_HIDDEN+DA_SYSTEM + or al,DA_DIR+DA_VOLUME + test DATTS[bx],al + jnz open9 ; error if attrib not as requested + mov ax,fdos_pb+6 ; determine open mode +if PASSWORD + sub dx,dx ; assume no PW conflicts +endif + test al,DHM_RW+DHM_WO ; test if read/only access + jz open2 +if PASSWORD ; if write or r/w check writes + or dx,PWM_W ; check for write password +endif +; mov bx,dirp ; get directory pointer + test DATTS[bx],DA_RO ; read/only file? + jz open2 ; no, skip FCB check + test ax,DHM_FCB ; if FCB open of read-only file + jz open9 ; allow it, but adjust to read-only + and al,not DHM_RWMSK ; open mode and proceed +open2: +if PASSWORD + test al,DHM_WO ; will we try to read? + jnz open3 ; skip if not open for reading + or dx,PWM_R + PWM_E ; else check for read/exec password +open3: + push ax ; save the open mode + xchg ax,dx ; AX = password modes to check for + call check_pwd ; check for r/w passwords + pop ax +endif + jmp open_handle ; now allocate file handle + +open8: + jmp fdos_ED_FILE ; "file not found" +open9: + jmp fdos_ED_ACCESS ; return "access denied" error + + +eject +; CLOSE FILE (CLOSE) + +; +----+----+----+----+ +; | 3E | handle | +; +----+----+----+----+ + +; entry: +; ------ +; handle: open file handle to be closed + +; exit: +; ----- +; AX: 3Exx (where xx = # time it was open) or error code ( < 0) + +fdos_close: +;---------- + call vfy_dhndl_ptr ; check file handle # + call redir_dhndl_offer + call local_disk ; get MXdisk, switch stack + call check_handle ; check if legal file handle + mov ax,es:DHNDL_COUNT[bx] ; return # times file WAS open + mov ah,3Eh ; AH = MS_X_CLOSE + mov fdos_ret,ax ; return 3Exx if successful + jc close20 ; skip if character device close +close_dhndl: + call release_handle ; release file handle into pool + callf ss:share_stub+S_CLOSE ; call the fdos stub routine + dec es:DHNDL_COUNT[bx] ; one less XFN refers to this IFN + test es:DHNDL_WATTR[bx],DHAT_REMOTE+DHAT_CLEAN + jnz close10 ; skip update if not dirty local file + call select_handle ; select the disk + call file_update ; update directory & FAT if written +close10: + ret + +close20: ; handle refers to character device + jmp close_dev ; close the device handle + +eject +; READ FROM FILE (READ) + +; +----+----+----+----+----+----+----+----+----+----+ +; | 3F | handle | buffer | count | +; +----+----+----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; handle: open file handle +; buffer: buffer to read into +; count: max. number of bytes to read + +; exit: +; ----- +; AX: byte count or error code ( < 0) + +fdos_read: +;--------- + call vfy_dhndl_ptr ; check file handle # + test es:DHNDL_MODE[bx],DHM_WO + jnz rw_ED_ACCESS ; fail if open write only + call redir_dhndl_offer + test es:DHNDL_WATTR[bx],DHAT_DEV + jnz fdos_read_dev ; skip if character device + call local_disk ; get MXdisk, switch stack + call verify_handle ; check if legal file handle + mov cx,fdos_pb+8 ; get requested transfer length + mov ax,es:DHNDL_POSLO[bx] ; If we get an error we want to have + mov dx,es:DHNDL_POSHI[bx] ; xfer len adjusted for EOF (CopyIIpc) + sub ax,es:DHNDL_SIZELO[bx] ; are we beyond EOF ? + sbb dx,es:DHNDL_SIZEHI[bx] +; jb read2 ; beyond EOF already, no action required +; ja read2 ; more the 64K to go, no problems + jnz read2 + cmp ax,cx ; do we want more than there is? + jae read2 ; yes, shorten the fdos_pb count + sub fdos_pb+8,ax ; in case of a critical error +read2: + mov fdrwflg,1 ; we're reading + les di,dword ptr fdos_pb+4 ; get disk transfer address + call fdosrw ; read from file + xor ax,ax ; return OK + xchg ax,fdos_ret ; get returned byte count + mov fdos_pb+8,ax ; return in requested count + ret + +fdos_read_dev: + jmp read_dev ; read from character device + +rw_ED_ACCESS: + mov bx,ED_ACCESS ; return access denied + ret + +eject +; WRITE TO FILE (WRITE) + +; +----+----+----+----+----+----+----+----+----+----+ +; | 40 | handle | buffer | count | +; +----+----+----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; handle: open file handle +; buffer: buffer to be wriiten +; count: max. number of bytes to write + +; exit: +; ----- +; AX: byte count or error code ( < 0) + +fdos_write: +;---------- + call vfy_dhndl_ptr ; check file handle # + test es:DHNDL_MODE[bx],DHM_WO+DHM_RW + jz rw_ED_ACCESS ; fail if not open in r/w or w mode? + call redir_dhndl_offer + test es:DHNDL_WATTR[bx],DHAT_DEV + jnz fdos_write_dev ; skip if not character device + call local_disk ; get MXdisk, switch stack + call verify_handle ; check if legal file handle + mov fdrwflg,0 ; we're writing + les di,dword ptr fdos_pb+4 ; get disk transfer address + mov cx,fdos_pb+8 ; get requested transfer length + call fdosrw ; write to file file + + xor ax,ax ; return OK + xchg ax,fdos_ret ; get returned byte count + mov fdos_pb+8,ax ; return in requested count + ret + +fdos_write_dev: + jmp write_dev ; write to character device + +eject +; DELETE FILE (UNLINK) + +; +----+----+----+----+----+----+----+----+----+----+ +; | 41 | name | ***** | attrib | +; +----+----+----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; name: segmented address of ASCIIZ name +; attrib: delete mask (FCB only..) + +; exit: +; ----- +; AX: 0000 or error code ( < 0) + + +fdos_unlink: +;----------- + call redir_asciiz_offer + call local_disk ; get MXdisk, switch stack + call path_prep ; parse the path, go to bottom level + call chk_no_dev ; can't be a device + ; look to see is the call is a remote + cmp ss:remote_call,0 ; a 21/5D00 one or a local FCB one + jz unlink1 ; neither, no wild cards allowed + jns unlink2 ; if it's an FCB call we need to check + test fdos_pb+8,DA_VOLUME ; for deleting a VOLUME label + jz unlink2 + call find_labelf ; lets find the volume label + jz unlink4 ; reporting error if we don't match + jmp kill_entry ; found it - delete it + +unlink4: + jmp fdos_ED_FILE ; return "file not found" + +unlink1: + call chk_no_wild ; make sure not a wild card +unlink2: + call setenddir ; search from the start + +; We now skip any labels/dirs, returning ED_FILE if no other matches +unlink3: + call finddfcb ; try to locate directory entry + jz unlink4 ; returning an error on failure + test DATTS[bx],DA_DIR+DA_VOLUME + jnz unlink3 ; make sure it isn't a label/directory + +unlink5: +; we have a match, so return ED_ACCESS if we can't find a file we can delete + call unlink_attribs ; AL = attribs we can't delete + jz unlink7 ; yes, go for it + call finddfcb ; look for another entry + jnz unlink5 ; try this one instead + jmp fdos_ED_ACCESS ; "access denied" if nothing deleted + ; since we found at least 1 file + +; we will delete at least one file, so now we succeed +unlink6: + call unlink_attribs ; AL = attribs we can't delete + jnz unlink8 ; yes, go for it +unlink7: + call close_if_same_psp ; make sure not open by any process +if PASSWORD + call check_pwd_d ; check for password +endif + call kill_file ; delete file +unlink8: + call finddfcb ; look for another entry + jnz unlink6 ; try and delete it if we find one + jmp update_dir_fat ; write out dirty directories/FAT + + +unlink_attribs: +; On Entry: +; BX -> directory entry +; On Exit: +; AL = attribute mask which prevents deletion +; ZF = 1 if delete OK, ZF = 0 if file should be skipped +; + mov al,byte ptr fdos_pb+8 ; check attributes +if PASSWORD + cmp word ptr DPWD[bx],0 + je unlink_attribs10 + or al,DA_HIDDEN +unlink_attribs10: +endif + not al + and al,DA_HIDDEN+DA_SYSTEM+DA_RO + or al,DA_DIR+DA_VOLUME + test DATTS[bx],al ; should we delete this entry ? + ret + + +eject +; GET/SET FILE POSITION (LSEEK) + +; +----+----+----+----+----+----+----+----+----+----+ +; | 42 | handle | offset ! method | +; +----+----+----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; handle: open file handle +; offset: long integer offset +; method: 0 = begin, 1 = current, 2 = end of file + +; exit: +; ----- +; AX: 0000 or error code ( < 0) +; offset: new offset + +fdos_lseek: +;---------- + call vfy_dhndl_ptr ; check file handle # + call redir_dhndl_offer + test es:DHNDL_ATTR[bx],DHAT_DEV + jnz lseek_dev ; skip if character device + call local_disk ; get MXdisk, switch stack + call check_handle ; check if legal file handle + mov ax,fdos_pb+4 ; get 32-bit file offset + mov dx,fdos_pb+6 ; into AX,DX + mov cx,fdos_pb+8 ; get seek mode + jcxz lseek4 ; seek from beginning + dec cx + jz lseek2 ; seek from current position + dec cx + jz lseek3 ; seek from end + mov ax,ED_DATA ; else invalid seek mode + jmp fdos_error ; return error code +lseek1: + ret ; return error code + +lseek2: ; seek mode 1: relative to position + add ax,es:DHNDL_POSLO[bx] + adc dx,es:DHNDL_POSHI[bx] + jmps lseek4 ; update new position + +lseek3: ; seek mode 2: relative to end + add ax,es:DHNDL_SIZELO[bx] + adc dx,es:DHNDL_SIZEHI[bx] ; add file size + offset +lseek4: ; seek mode 0: set absolute position + mov es:DHNDL_POSLO[bx],ax + mov es:DHNDL_POSHI[bx],dx + mov fdos_pb+4,ax ; set return values + mov fdos_pb+6,dx + ret + +lseek_dev: ; jump here if character device + mov si,2[bp] ; SI -> parameter block + xor bx,bx + mov 4[si],bx ; always return result of 0000h + mov 6[si],bx + ret + +eject +; GET/SET FILE ATTRIBUTES (CHMOD) + +; +----+----+----+----+----+----+----+----+----+----+ +; | 43 | name | flag | attrib | +; +----+----+----+----+----+----+----+----+----+----+ +; | size | +; +----+----+----+----+ + +; entry: +; ------ +; name: pointer to ASCIIZ file name +; flag: 00 = get attrib/size +; 01 = set attrib +; attrib: file attribute if flag=1 +; +; exit: +; ----- +; AX: 0000 or error code ( < 0) +; attrib: file attribute if flag=0 +; size: file size if flag=0 +; +if PASSWORD +; entry: +; ------ +; name: pointer to ASCIIZ file name +; flag: 02 = get password mode +; 03 = set pw mode/password +; 04 = get encrypted password +; 05 = set encrypted password +; attrib: password mode if flag = 3,5 +; dma: ascii password if flag = 3 +; encrypted password if flag = 5 +; +; exit: +; ----- +; AX: 0000 or error code ( < 0) +; attrib: file's attribute if flag = 0 +; password mode if flag = 2 +; encrypted password if flag = 4 +endif +if UNDELETE +; entry: +; ------ +; name: pointer to ASCIIZ file name +; flag: 80 = undelete file +; 81 = purge file +; dma: result of sucessful search +; +; exit: +; ----- +; AX: 0000 or error code ( < 0) +; +endif + +fdos_chmod: +;---------- +if UNDELETE + mov si,2[bp] ; SI -> parameter block + mov al,6[si] ; AX = flag + sub al,80h ; is it undelete or purge + jb fdos_chmod_path ; if so set + cmp al,1 + ja fdos_chmod_path + call local_disk ; get MXdisk, switch stack + call select_from_DTA ; prepare for the search + mov chdblk,0 ; don't assume sequential access + dec dcnt ; retract so we find the same entry + call find_pending_delete ; did we find it ? + jz chmod_notfound ; No, then skip + call hdsblk ; AX = directory root cluster + xchg ax,dx ; DX = dir cluster + mov cx,dcnt ; CX = directory index for entry + mov ax,fdos_pb+6 ; get operation type + mov ah,DELW_UNDEL ; assume we are about to undelete + cmp al,80h ; is it undelete ? + je fdos_undelete_purge + mov ah,DELW_PURGE ; no, it must be purge entry +fdos_undelete_purge: + mov al,physical_drv ; give delwatch a chance to do it + callf ss:fdos_stub + jc fdos_ED_FUNCTION ; return error if DELWATCH not there + mov fdos_ret,ax ; else return result + ret +fdos_chmod_path: +endif + call redir_asciiz_offer + call local_disk ; get MXdisk, switch stack + + call path_prep ; parse the path, go to bottom level + call chk_no_wild ; can't have wildcards + call finddfcbf ; find first matching FCB + jnz chmod10 ; if we can't find a file/dir + call chk_for_root ; check if we are in the root + jnz chmod_notfound ; if so return directory attribute + mov cx,fdos_pb+6 ; but only for get attributes + jcxz chmod_root ; other fall through to not found +chmod_notfound: + jmp fdos_ED_FILE +chmod_root: + mov fdos_pb+8,DA_DIR ; return directory attribute + ret + +fdos_ED_FUNCTION: + mov ax,ED_FUNCTION ; invalid subfunction + jmp fdos_error + +chmod10: + mov bx,dirp ; BX -> matching directory entry + mov ax,DSIZE[bx] + mov fdos_pb+10,ax + mov ax,DSIZE+WORD[bx] + mov fdos_pb+12,ax + xor ax,ax + mov al,DATTS[bx] ; get directory attributes + mov cx,fdos_pb+6 ; get function # + jcxz chmod30 ; always allow get attribs +if PASSWORD + cmp cl,5 ; validate sub-function number + ja chmod15 + mov ax,DPWM[bx] ; assume return password mode + and ax,PWM_ANY ; isolate password mode bits + cmp cl,2 ; is it get mode ? + je chmod30 ; yes, just return it + push ax + push cx + call check_pwd_any ; check the password + pop cx + pop ax + mov dx,fdos_pb+8 ; DX = new attributes + cmp cl,2 ; is it get mode ? + ja chmod20 ; how about other password functions? +else + cmp cl,1 ; validate sub-function number + ja chmod15 + mov dx,fdos_pb+8 ; DX = new attributes +endif +; Set new file attrib +; BX = DIRP +; DX = attrib +; + test dl,DA_DIR ; directory bit not allowed + jnz chmod12 + xor dl,DATTS[bx] ; check which bits are changed + and dl,not DA_DIR ; don't check or flip directory bit + test dl,DA_FIXED ; trying to change the unchangeable? + jz chmod13 +chmod12: + jmp fdos_ED_ACCESS ; return "access denied" +chmod13: + xor DATTS[bx],dl ; set new attributes +if PASSWORD + jmps chmod90 +else + jmp update_dir ; update directory +endif + +chmod15: + mov ah,PASSWD_CHMOD ; call out to SECURITY TSR + callf ss:fdos_stub + jc fdos_ED_FUNCTION + jmps chmod90 + +if PASSWORD +chmod20: +; Password support for functions 3-5 +; BX = DIRP +; CX = flag +; DX = attrib +; + push bx + push cx + push dx + mov di,S_DENY_IF_OPEN ; check if file already open + call check_with_share ; and stop if it is + pop dx + pop cx + pop bx + mov ax,DPWD[bx] ; assume get encrypted password + cmp cl,4 ; was it ? + jne chmod50 +endif ; yes, return encrypted password +chmod30: + mov fdos_pb+8,ax + ret + + +if PASSWORD +; Password support for functions 3/5 +; BX = DIRP +; CX = flag +; DX = attrib +; +chmod50: ; set password/password mode + test dh,80h ; assign new password? + jz chmod70 ; skip if mode change only + mov di,offset save_area ; ES:DI -> local structure + push ds + call lds_si_dmaptr ; DS:SI -> users DMA address + lodsw ; AX = possible encrypted password + cmp cl,5 ; was it set encrypted password ? + je chmod60 + dec si ; no, the DMA buffer contains + dec si ; an 8 character password so we + call hash_pwd ; compute password hash code +chmod60: + pop ds + or DATTS[bx],DA_HIDDEN ; file will be hidden + mov DPWD[bx],ax ; set new file password + test ax,ax ; null password? + jnz chmod70 + xor dx,dx ; can't be protected.... +chmod70: + mov ax,not PWM_ANY ; clear existing file + and DPWM[bx],ax ; password mode bits + not ax ; isolate password mode bits + and dx,ax ; in new password mode + jz chmod80 ; if no protection, leave them off + test DATTS[bx],DA_DIR ; directories protected in all modes + jz chmod80 ; skip if not a directory + xchg ax,dx ; force all modes on +chmod80: + or DPWM[bx],dx ; set password mode bits + test dx,dx ; test if protection enabled + jnz chmod90 ; skip if any protection still active + mov DPWD[bx],dx ; remove the password and hidden bit + and DATTS[bx],not DA_HIDDEN ; as file is no longer protected +endif +chmod90: + jmp update_dir ; now update the directory + + + + + + +eject +; DUPLICATE FILE HANDLE (DUP) + +; +----+----+----+----+----+----+ +; | 45 | handle | newhnd | +; +----+----+----+----+----+----+ + +; entry: +; ------ +; handle: open file handle + +; exit: +; ----- +; newhnd: new file handle +; AX: duplicate file handle or error code ( < 0) + +fdos_dup: +;-------- + call find_xfn ; find new external file # + mov si,2[bp] ; SI -> parameter block + mov ds:4[si],di ; save new handle # + jnc fdos_fdup ; share the code with DUP2 + mov bx,ED_HANDLE ; can't find a handle + ret +eject +; FORCE DUPLICATE FILE HANDLE (DUP2) + +; +----+----+----+----+----+----+ +; | 46 | handle | newhnd | +; +----+----+----+----+----+----+ + +; entry: +; ------ +; handle: open file handle +; newhnd: new file handle + +; exit: +; ----- +; AX: duplicate file handle or error code ( < 0) + +fdos_fdup: +;--------- + call vfy_dhndl_ptr ; check file handle # + call local_disk ; get critical section locks + call get_xftptr ; ES:DI -> XFN table + jc dup_err ; we need one.. + mov bx,fdos_pb+4 ; get user file number (0-19) + cmp bx,cx ; is it sensible ? + jae dup_err + cmp es:byte ptr [di+bx],0FFh + jne dup_err ; handle should be closed by PCMODE.. + call check_handle ; check if legal file handle + inc es:DHNDL_COUNT[bx] ; another user + call dup_dev ; inform device driver it's happened + call get_xftptr ; ES:DI -> XFT's + mov bx,fdos_pb+2 ; get XFN to dup from + mov al,es:[di+bx] ; get it's IFN + mov bx,fdos_pb+4 ; BX = XFN to dup to + mov es:[di+bx],al ; it gets same IFN + mov fdos_ret,bx ; return XFN to caller + ret + +dup_err: ; complain someone stole my handle + jmp fdos_ED_H_MATCH + +eject +; GET CURRENT DIRECTORY +; +; +----+----+----+----+----+----+----+----+ +; | 47 | drive | path | +; +----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; drive: drive to get path for +; path: address of 64 byte path buffer to be +; filled in with current path + +; exit: +; ----- +; BX: 0100 or error code + +fdos_curdir: +;----------- + call local_disk ; it's a disk function + call get_pb2_drive ; get specified drive in AL + call get_ldt ; ES:BX -> LDT_ for drive + jc fdos_curdir30 + mov dx,es:LDT_FLAGS[bx] + test dx,LFLG_NETWRKD + jnz fdos_curdir10 + test dx,LFLG_PHYSICAL + jz fdos_curdir30 + call select_unique ; select the drive for media changes + les bx,ss:current_ldt ; ES:BX -> LDT_ for this drive + cmp es:LDT_BLK[bx],0FFFFh ; is LDT valid + jne fdos_curdir10 + call rebuild_ldt_curdir ; no, better rebuild it +fdos_curdir10: + push ds + push es ! push bx ; save LDT + les di,dword ptr fdos_pb+4 ; ES:DI -> destination buffer + pop si ! pop ds ; DS:SI -> LDT + add si,ds:LDT_ROOTLEN[si] ; skip the '\\server\dir' + lodsb ; eat the slash + call check_slash ; if it is one.. + je fdos_curdir20 + dec si ; I didn't mean it! +fdos_curdir20: + call copy_asciiz ; copy the string + pop ds + mov fdos_ret,100h ; return 100h for success + ret + +fdos_curdir30: + jmp fdos_ED_DRIVE ; naughty - it's a bad drive + + +eject +; GET DISK PARAMETER BLOCK + +; +----+----+----+----+----+----+----+----+----+----+ +; | 48 | drive | dpb | adjust | +; +----+----+----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; drive: drive to get information about +; (top bit of word set if free space not required) + +; exit: +; ----- +; AX: 0000 or error code ( < 0) +; dpb: address of DOS DPB (offset/segment) +; adjust: delwatch adjustment of free space + +fdos_getdpb: +;----------- + call redir_drv_offer + call local_disk ; get MXdisk, switch stack + call get_pb2_drive ; get drive from parameter block + call logical2physical ; AX = physical drive + call select_physical_drv + test fdos_pb+2,8000h ; free space required ? + jnz fdos_getdpb10 + call update_ddsc_free ; then make sure it is up to date +if DELWATCH + xor cx,cx ; assume no adjustment + mov ah,DELW_SPACE + mov al,physical_drv ; now we call DELWATCH to + callf fdos_stub ; add pending deletes + mov fdos_pb+8,cx ; return free space adjust value +endif +fdos_getdpb10: + les ax,ss:current_ddsc + mov fdos_pb+4,ax + mov fdos_pb+6,es + ret + +eject +; FLUSH BUFFERS + +; +----+----+ +; | 49 | +; +----+----+ + +; entry: +; ------ +; none + +; exit: +; ----- +; none + +fdos_flush: +;---------- + call local_disk ; be alone... +fdos_flush_local: +; Entry point for people who already have the MX disk + xor dx,dx ; starting with drive A +fdos_flush10: + push dx + call mark_ldt_unsure ; ask for LDT's to be relogged + xchg ax,dx ; AL = drive to check + mov ah,BF_DIRTY + call buffers_check ; any buffers on this drive? + jz fdos_flush20 ; skip flush if none + call select_physical_drv ; select drive in AL + call update_fat ; flush all FAT buffers +; call update_dir ; dir always up to date + call update_dat ; flush all data buffers +fdos_flush20: + pop dx + xchg adrive,dl + call discard_all ; discard all buffers + xchg adrive,dl + inc dx ; onto next drive + cmp dl,phys_drv + jb fdos_flush10 + mov al,0FFh ; AL = all drives + jmp hshdscrd ; forget about our hashing +; ret + + +eject +; SELECT DRIVE + +; +----+----+----+----+ +; | 4A | drive | +; +----+----+----+----+ + +; entry: +; ------ +; drive: drive (zero based) to select as default drive + +; exit: +; ----- +; current_dsk: drive (if legal) + +fdos_select: +;----------- + call local_disk ; cheap way to get MX + mov ax,fdos_pb+WORD ; AL = drive + call get_ldt ; ES:BX -> LDT for drive A + mov dx,ax ; DL = logical drive + jc fdos_select10 ; no LDT, treat as physical=logical + mov ax,es:LDT_FLAGS[bx] ; get the LDT_FLAGS + test ax,LFLG_NETWRKD ; NETWORK drives are OK, but we must + jnz fdos_select20 ; skip physical selection bit + test ax,LFLG_PHYSICAL + jz fdos_select30 ; skip physical selection bit +if JOIN + test ax,LFLG_JOINED ; JOINed drives are bad news + jnz fdos_select30 ; so don't select one +endif + mov al,es:LDT_NAME[bx] ; get ASCII drive letter + call toupper ; it was ascii + sub al,'A' ; make it zero based +fdos_select10: + call get_ddsc ; ES:BX -> DDSC_ for drive + jc fdos_select30 ; no, don't select +fdos_select20: + mov ss:current_dsk,dl ; new logical disk selected +fdos_select30: + ret + +eject +; EXECUTE CHILD (EXEC) + +; +----+----+----+----+ +; | 4B | pspseg | +; +----+----+----+----+ + +; entry: +; ------ +; pspseg: segment of child PSP + +; exit: +; ----- +; AX: 0000h + +fdos_exec: +;--------- + call local_disk ; get MXdisk, switch stack + mov cx,fdos_pb+2 + jcxz exec30 ; no duplicate handles if no new PSP + mov di,offset PSP_XFT + mov es,cx ; get child PSP + mov cx,XFNMAX ; get # of handles in child PSP + mov PSP_XFNMAX,cx + mov PSP_XFTOFF,di + mov PSP_XFTSEG,es + mov al,0FFh ; assume all handles closed + rep stosb + xor si,si ; start with XFN 0 +exec10: + call get_xftptr ; ES:DI -> XFN table + jc exec30 ; stop if none + add di,si + mov al,es:[di] ; get IFN of old handle + call ifn2dhndl ; ES:BX -> DHNDL_ + jc exec20 + mov cx,es:DHNDL_COUNT[bx] ; skip files that aren't open + jcxz exec20 + test es:byte ptr DHNDL_WATTR+1[bx],DHAT_LOCAL/100h + jnz exec20 ; don't inherit private files + test es:byte ptr DHNDL_MODE+1[bx],DHM_FCB/100h + jnz exec20 ; don't inherit FCB's + inc cx + mov es:DHNDL_COUNT[bx],cx ; increment in-use count + push ax + call dup_dev ; inform device driver it's happened + pop ax + mov es,fdos_pb+2 ; get child PSP + mov es:PSP_XFT[si],al ; inherit this IFN +exec20: + inc si ; next file handle + cmp si,XFNMAX + jb exec10 ; inherit all file handles +exec30: + ret + + +eject +; FIND FIRST FILE + +; +----+----+----+----+----+----+----+----+----+----+ +; | 4E | name | ***** | attrib | +; +----+----+----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; name: pointer to ASCIIZ file name +; attrib: attribute to be used in search +; nb. API addition - attrib bit 7 set returns starting cluster +; +; exit: +; ----- +; AX: 0000 or error code ( < 0) + +; Note: This call returns matching files in +; the current DMA address and also saves +; the BDOS state in the there. +; + +fdos_first: +;---------- + call redir_asciiz_dev_offer ; offer it as a network device + call asciiz_dev_offer ; offer it as a local device + call redir_asciiz_file_offer ; offer it as a network file + call local_disk ; get MXdisk, switch stack + call path_prep ; parse path, walk down the tree + call check_device ; if it a device + jnc fdos_first10 + mov ax,fdos_pb+8 ; get search attribute + mov attributes,al ; set for attribute match + mov dcnt,0FFFFh ; search from beginning + jmps search_next ; find next matching file + +fdos_first10: + jmp first_dev ; return device name + +next_deverr: ; NEXT after FIRST on device: + mov bx,ED_FILE ; "no more files" + ret + +eject +; FIND NEXT FILE + +; +----+----+ +; | 4F | +; +----+----+ + +; entry: +; ------ +; +; exit: +; ----- +; AX: 0000 or error code ( < 0) + +; Note: This call returns matching files in +; the current DMA address and also saves +; the BDOS state in the there. +; + +fdos_next: +;--------- + push ds + call lds_si_dmaptr ; DS:SI -> users DMA address + lodsw + xchg ax,dx ; DH = local drive + pop ds + cmp dh,0FFh ; check if FIRST was character device + je next_deverr ; "no more files" if device + call redir_snext_offer + call local_disk ; get MXdisk, switch stack + call select_from_DTA ; prepare for the search +; jmp search_next ; now go and look for next file + +search_next: +;----------- + mov chdblk,0 ; don't assume sequential access + mov al,attributes ; are we looking for a VOL label? + test al,DA_DIR+DA_SYSTEM+DA_HIDDEN + jnz search_n10 ; these bits take precedence + test al,DA_VOLUME ; searching for label? + jz search_n10 ; search for directory label only +if UNDELETE + cmp al,DA_DELWATCH+DA_VOLUME + jne search_vol ; searching for pending delete entries? + call find_pending_delete ; did we find it ? + jz search_next_err ; No, then skip + jmps search_n30 ; save search state for user +search_vol: +endif + call find_label ; did we find it ? + jnz search_n30 ; save search state for user +search_next_err: + jmp fdos_ED_ROOM ; else end of directory + +search_n10: + call finddfcb ; find next matching entry + jz search_next_err ; if not found + mov al,attributes ; get attributes that we support +if PASSWORD + cmp word ptr DPWD[bx],0 ; does it have a password? + jz search_n20 ; skip if not + or al,DA_HIDDEN ; else include hidden files +search_n20: +endif + not al ; attributes we don't support + and al,DA_DIR+DA_HIDDEN+DA_SYSTEM+DA_VOLUME + test DATTS[bx],al ; any attributes we don't support + jnz search_n10 ; then don't count this one +search_n30: + push ss ! pop es + mov di,offset srch_buf ; ES:DI -> DMA search address + push di ; save for later +if JOIN + mov al,fdos_hds_drv ; save the PHYSICAL drive +else + mov al,byte ptr path_drive ; save the specified drive +endif + inc al + stosb + mov dx,di ; remember start of name field + mov si,offset info_fcb+1 ; point at search FCB + mov cx,11 + rep movsb ; save name for search + mov al,attributes ; get search attribute + stosb + + mov ax,dcnt + stosw ; save directory count + mov ax,fdos_hds_blk ; get the directory block + stosw ; save the current block + + add di,4 ; skip 4 reserved bytes + + mov si,dirp ; point to directory name + test attributes,DA_CLUSTER ; is the caller requesting + jz search_n35 ; the starting cluster ? + mov ax,DBLOCK1[si] ; pick it up from dir entry + dec di ; and return at offset 13h + dec di ; in DTA (WARNING - Lantastic + stosw ; server uses these bytes too..) +search_n35: + mov cx,32/WORD + rep movsw ; location (also used by FCB search) + + pop si ; SI = offset srch_buf + call les_di_dmaptr ; ES:DI -> DMA address + push ss ! pop ds ; DS:SI -> srch_buf + mov cx,21 + rep movsb ; copy from buffer to user DMA + mov bx,dirp ; BX -> matching entry + mov al,DATTS[bx] + stosb ; return directory attribute + lea si,DTIME[bx] + movsw ! movsw ; return time, date + inc si + inc si ; skip starting cluster + movsw ! movsw ; return file size + jmp unparse ; return file name + +eject +; COMMIT FILE (COMMIT) + +; +----+----+----+----+ +; | 50 | handle | +; +----+----+----+----+ + +; entry: +; ------ +; handle: open file handle to be flushed + +; exit: +; ----- +; AX: 0000 or error code ( < 0) + +file_updt20: ; NO-OP for clean files +commit_dev: ; NO-OP on character devices + ret + +fdos_commit: +;----------- + call vfy_dhndl_ptr ; check file handle + call redir_dhndl_offer + call local_disk ; get MXdisk, switch stack + call verify_handle ; check if legal file handle + jc commit_dev +; jmp file_update ; update directory & FAT if written + +; Update directory & File Allocation Table (partial close) +; entry: ES:BX -> DHNDL_ +; exit: ES:BX preserved + + Public file_update + +file_update: +;----------- + test es:DHNDL_ATTR[bx],DHAT_CLEAN + jnz file_updt20 ; skip if file is clean + mov al,es:DHNDL_DCNTLO[bx] ; get directory count + mov ah,es:DHNDL_DCNTHI[bx] + dec ax + mov dcnt,ax ; set search position + xor cx,cx ; find any entry + mov chdblk,cx ; non-sequential access + push es ! push bx + call getdir ; read the directory entry + pop bx ! pop es + test ax,ax ; did we find something? + jz file_updt10 ; skip if directory entry lost + xchg ax,di ; DI -> directory entry in buffer + or DATTS[di],DA_ARCHIVE ; mark file as modified +;;; call timestamp_dhndl ; record the current time + mov ax,es:DHNDL_BLK1[bx] ; AX = 1st block in file + lea di,DTIME[di] ; DI -> [time,date,block1,size] + push es ! push bx + push ds + lea si,DHNDL_TIME[bx] + push ds ! push es + pop ds ! pop es ; swap ES and DS + movsw ! movsw ; copy time then date + stosw ; now 1st cluster + movsw ! movsw ; finally file size + pop ds + call update_dir ; update directory + call update_fat ; flush dirty FAT + call update_dat ; flush all dirty data buffers + pop bx ! pop es + or es:DHNDL_ATTR[bx],DHAT_CLEAN + ret ; only mark as clean AFTER it's written + +file_updt10: + mov ax,ED_H_MATCH ; can't find open file + mov fdos_ret,ax ; save error code + ret + + + +eject +; CREATE NEW FILE + +; +----+----+----+----+----+----+----+----+ +; | 51 | name | mode | +; +----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; name: segmented address of ASCIIZ name +; mode: attribute for file + +; exit: +; ----- +; AX: file handle or error code ( < 0) + +; Note: The function is identical to CREATE FILE +; with the exception that an error is returned +; if the specified file already exists. + +fdos_mknew: +;---------- + call redir_asciiz_offer + call local_disk ; get MXdisk, switch stack + call mustbe_free_handle ; make sure we have spare handle + call path_prep_chk ; parse path, walk down the tree + call finddfcbf ; check if we can find this one + jnz mknew10 + test byte ptr fdos_pb+8,DA_VOLUME + jz mknew_nolbl ; skip if not volume label + call mustbe_nolbl ; do we have an existing label ? +mknew_nolbl: + jmp creat_new_file ; go ahead and create the file +mknew10: + mov ax,ED_EXISTS + jmp fdos_error + +eject +; LOCK/UNLOCK FILE DATA (LOCK/UNLOCK) + +; +----+----+----+----+----+----+----+----+ +; | 52 | handle | offset | +; +----+----+----+----+----+----+----+----+ +; | length | lock | +; +----+----+----+----+----+----+ + +; entry: +; ------ +; handle: open file handle +; offset: long integer offset +; length: long integer byte count +; lock: 0 = lock, 1 = unlock + +; exit: +; ----- +; AX: byte count or error code ( < 0) + +fdos_lock: +;--------- + call vfy_dhndl_ptr ; check file handle # + test es:DHNDL_WATTR[bx],DHAT_DEV + jnz lock_dev ; skip if character device + call redir_dhndl_offer + call local_disk ; get MXdisk, switch stack + call check_handle ; check if legal file handle + mov ax,ED_ACCESS ; assume a problem + jc lock_error ; can't lock/unlock device handles + mov di,offset fdos_pb + callf ss:share_stub+S_LOCKS ; call the stub routine + jnc lock_ret ; return error if we got one +lock_error: + jmp fdos_error ; can't do locking + +lock_dev: + mov bx,ED_ACCESS +lock_ret: + ret + +eject +; BUILD DDSC FROM BPB + +; +----+----+----+----+----+----+----+----+----+----+ +; | 53 | bpbptr ! ddscptr | +; +----+----+----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; bpbptr: address of BPB +; ddscptr: address of DDSC to be built + +; exit: +; ----- +; 0000 or error code ( < 0) + +fdos_mkddsc: +;----------- + push ds + mov si,2[bp] ; SI -> parameter block + les di,6[si] ; ES:DI -> DDSC + lds si,2[si] ; DS:SI -> BPB + + call bpb2ddsc ; convert BPB to DDSC + xor bx,bx ; no error + pop ds ; restore segment register + ret + + +bpb2ddsc: +;-------- +; build a DDSC from a BPB, leavinf UNIT, RUNIT, DEVICE, FIRST, and LINK fields +; unchanged +; On Entry: +; DS:SI -> source BPB +; ES:DI -> destination DDSC +; On Exit: +; None + lodsw ; get sector size in bytes + mov es:DDSC_SECSIZE[di],ax + + lodsb ; get sectors/allocation unit + dec ax ; get cluster mask + mov es:DDSC_CLMSK[di],al ; store cluster mask + lodsw ; get FAT address + mov es:DDSC_FATADDR[di],ax + + lodsb ; get # of fats + mov es:DDSC_NFATS[di],al + cbw ; make it a word value + xchg ax,dx ; and keep in DX + + lodsw ; get # of directory entries + mov es:DDSC_DIRENT[di],ax + + lodsw ; get # of sectors total in image + push ax ; save disk size for later + + lodsb ; get FAT id byte + mov es:DDSC_MEDIA[di],al ; set media byte + + lodsw ; get # of sectors in a fat +if DOS5 + mov es:DDSC_NFATRECS[di],ax ; set FAT size +else + mov es:DDSC_NFATRECS[di],al ; set FAT size +endif + + mul dx ; AX = FAT size + add ax,es:DDSC_FATADDR[di] ; AX = 1st directory sector + mov es:DDSC_DIRADDR[di],ax ; set root directory address + + add si,word+word+dword ; skip SPT, NHEADS, BIGHIDDEN + + mov cx,es:DDSC_SECSIZE[di] + mov ax,32 ; size of single directory entry + mul es:DDSC_DIRENT[di] ; AX/DX = root directory bytes + add ax,cx ; round up sector size + dec ax ; in case of odd number + div cx ; convert to whole sectors + add ax,es:DDSC_DIRADDR[di] ; add in base of root directory + mov es:DDSC_DATADDR[di],ax ; set this as first cluster address + + pop ax ; recover total disk size + xor dx,dx ; assume 16 bit number + test ax,ax ; test for big drive + jnz bpb2ddsc10 ; skip if not large drive + lodsw ; get low word of size + mov dx,[si] ; get high word of size +bpb2ddsc10: ; AX/DX = disk size in sectors + sub ax,es:DDSC_DATADDR[di] ; subtract non-data portion + sbb dx,0 + + xor cx,cx ; CL = cluster shift + mov ch,es:DDSC_CLMSK[di] ; CH = cluster mask +bpb2ddsc20: ; count # of 1 bits + shr ch,1 ; shift right mask + jnc bpb2ddsc30 ; skip if all 1 bits shifted out + inc cx ; count another 1 bit + shr dx,1 + rcr ax,1 ; div by two + jmps bpb2ddsc20 ; repeat until all 1's counted +bpb2ddsc30: ; CL = log2 (CH) + mov es:DDSC_CLSHF[di],cl ; set cluster shift + inc ax ; clusters 0/1 reserved (+2), and we + mov es:DDSC_NCLSTRS[di],ax ; want max (-1), so +1 + xor ax,ax + mov es:DDSC_BLOCK[di],ax ; next block = 0 + dec ax + mov es:DDSC_FREE[di],ax ; free space = -1 (unknown) + ret + +eject +; DIRECT DISK IO + +; +----+----+----+----+----+----+ +; | 54 |drv | op |nsectors | +; +----+----+----+----+----+----+----+----+ +; | startsec | dma address | +; +----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; param block set up for direct disk IO + +; exit: +; ----- +; AX = 0, or error code +; + +DIO_25_READ_OP equ 1 +DIO_26_WRITE_OP equ 2 + +fdos_ddio: +;--------- +; Used by emulator for Int 25H/26H disk calls to BIOS +; +; entry: dio = offset of parameter block in user data segment +; +; exit: AX = return code from BIOS + + call local_disk ; get the MX + mov ax,fdos_pb+WORD ; AX = logical drive + call logical2physical ; AX = physical drive + call get_ddsc ; make sure this drive is valid + jc fdos_ddio30 ; bail if not + mov adrive,al ; remember this unit + mov ax,CMD_INPUT+0*256 ; disk read operation of system area + cmp byte ptr fdos_pb+3,DIO_26_WRITE_OP + jne fdos_ddio10 + mov ax,0FFFFh + mov es:DDSC_FREE[bx],ax ; free space = -1 (unknown) + call hshdscrd ; discard hashing info for all drives (AL=FF) + mov ax,CMD_OUTPUT+1*256 ; disk write operation of system area +fdos_ddio10: + mov rwmode,ah ; save read/write of system area + mov req_hdr+5,ah ; (so driver can get the hint) + mov bx,offset req_hdr ; we will build request here + mov RH_CMD[bx],al ; save the command + mov ax,fdos_pb+4 ; AX = # sectors + mov RH4_COUNT[bx],ax ; set requested sector count + les ax,dword ptr fdos_pb+6 ; pick up 32-bit record address + mov word ptr pblock,ax + mov word ptr pblock+WORD,es + les ax,dword ptr fdos_pb+10 ; ES:AX -> DMA seg + mov RH4_BUFOFF[bx],ax + mov RH4_BUFSEG[bx],es + call ddioif ; go do it + jns fdos_ddio20 ; did we have a problem ? + cbw ; AX = base error + add ax,ED_PROTECT ; "add" in BIOS error code + mov fdos_ret,ax ; save return code +fdos_ddio20: + ret + +fdos_ddio30: + jmp fdos_ED_DRIVE ; return bad drive error + +eject +; EXPAND FILE NAME + +; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+ +; | 55 | relative name | | absolute name | +; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; relative name: segmented address of ASCIIZ name +; absolute name: segmented address of ASCIIZ name + +; exit: +; ----- +; AX = BX: 0000 or error code ( < 0) + +fdos_expand: +;----------- + call redir_asciiz_dev_offer ; is it a networked device ? + call asciiz_dev_offer ; see it we are expanding a device name + call local_disk ; get MXdisk, switch stack + push ds + les si,dword ptr fdos_pb+2 ; get relative name buffer + mov ax,es:[si] ; get 1st two chars of path + call check_dslash ; is it a '\\' form ? + je fdos_expand10 + mov bx,ED_FILE + test al,al + jz fdos_expand60 + call toupper ; work on premise we have drive + sub al,'A' ; specified in relative name + sub ah,':' ; did we have ? + je fdos_expand20 ; if so use it +fdos_expand10: + mov al,current_dsk ; use current drive +fdos_expand20: + cmp al,last_drv ; is it a legal drive + jae fdos_expand50 + +; we should check for a media change so select_logical_drv seems to be +; a better solution +; call get_ldt ; ES:BX -> LDT_ for drive +; jc fdos_expand40 ; no LDT at init - copy relative path +; mov word ptr current_ldt,bx +; mov word ptr current_ldt+WORD,es + call select_logical_drv + les bx,current_ldt + + test es:LDT_FLAGS[bx],LFLG_PHYSICAL + jz fdos_expand50 ; make sure it's a valid drive + push ss ! pop es + mov di,offset pri_pathname ; build name in pathname buffer + lds si,dword ptr fdos_pb+2 + +; we must trick redir_build_path to find the correct function number - +; otherwise we could not get correct (critical) error reporting to work + push bp + mov bp,offset fdos_pb+6 + mov 2[bp],bp + mov byte ptr [bp],FD_EXPAND + + call redir_build_path ; build name from LDT + pop bp + jc fdos_expand60 ; bail out if bad name + lds di,ss:current_ldt ; we need to append a '\' if + mov bx,ds:LDT_ROOTLEN[di] ; we are at the root + test ds:LDT_FLAGS[di],LFLG_SUBST + jz fdos_expand30 ; if drive is SUBST'd then + mov bx,2 ; only append if real root +fdos_expand30: + mov si,offset pri_pathname ; SS:SI -> full path + push ss ! pop ds ; leave current ldt -> buffer as LAN + mov word ptr current_ldt,si ; MAN 2.1 extended edition expects it + mov word ptr current_ldt+WORD,ds + mov ax,'\' ; get pathchar in AX for checks + cmp ds:byte ptr [si+bx],ah ; are we at the root ? + jne fdos_expand40 ; if so append a '\' + mov ds:word ptr [si+bx],ax +fdos_expand40: + les di,ss:dword ptr fdos_pb+10; ES:DI -> destination buffer + call copy_asciiz ; copy the full pathname + pop ds + ret + +fdos_expand50: + mov bx,ED_DRIVE ; return bad drive error +fdos_expand60: + mov ax,bx + pop ds + jmp fdos_error + +expand_dev: +;---------- + les si,dword ptr fdos_pb+2 ; this is the original source + lods es:ax ; get the source + les di,dword ptr fdos_pb+10 ; data will end up here + cmp ah,':' ; is a drive specified ? + je expand_dev10 + mov al,'A' + add al,ss:current_dsk +expand_dev10: + call toupper ; make sure drive letter is upper case + stosb ; plant an 'd' + mov ax,':'+256*'/' + stosw ; make that 'd:/' + mov bx,offset name_buf ; DS:BX -> name buffer + jmp unparse ; unparse the device name + +eject +; RENAME FILE + +; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+ +; | 56 | old name | | new name | +; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; old name: segmented address of ASCIIZ name +; new name: segmented address of ASCIIZ name + +; exit: +; ----- +; AX: 0000 or error code ( < 0) + +; Note: R/O files can be renamed. +; --- + +fdos_move: +;--------- + call redir_move_offer + call local_disk ; get MXdisk, switch stack + call path_prep ; parse the path, go to bottom level + call chk_no_dev + cmp ss:remote_call,0 ; wildcards allowed if server/FCB + jnz move10 + call chk_no_wild ; make sure not a wild card +move10: + call finddfcbf ; else try to locate directory entry + jz fdos_ED_FILE ; error if no match occurred +move20: + call close_if_same_psp ; make sure not open by other PDs +if PASSWORD + call check_pwd_any ; check if password protected +endif + mov si,dirp ; get matching directory entry + mov di,offset save_area ; get a temporary save area + mov cx,32/WORD ; save it all + rep movsw ; so we can move it to new entry + + mov si,offset fdos_hds + mov di,offset saved_hds + mov cl,HDS_LEN + rep movsb ; copy current HDS to safe place + + mov ax,dcnt ; also save directory index + mov saved_dcnt,ax ; so we can release entry later + + les di,dword ptr fdos_pb+10 ; es:di -> path name + call path_prep_ptr ; find the destination path + call chk_no_dev ; no devices allowed here + cmp ss:remote_call,0 ; wildcards allowed if server/FCB + jnz move25 + call chk_no_wild ; make sure not a wild card +move25: + mov al,fdos_hds_drv ; get the work drive + cmp al,saved_hds_drv ; make sure same drive for + je move30 ; source and destination + + mov ax,ED_DEVICE ; "not same device" error + jmps fdos_moverr ; return the error +fdos_ED_FILE: + mov ax,ED_FILE ; get error code +fdos_moverr: + jmp fdos_error ; return the error + +move30: ; same drive for source & destination + mov al,byte ptr fdos_pb+8 ; check attributes +if PASSWORD + cmp save_area+DPWD,0 + je move31 + or al,DA_HIDDEN +move31: +endif + not al + and al,DA_HIDDEN+DA_SYSTEM+DA_DIR+DA_VOLUME + test save_area+DATTS,al + jnz move80 + mov si,offset info_fcb+1 ; SI->new name (possible wildcards) + mov di,si ; DI->new name + mov bx,offset save_area ; current name on disk + cmp byte ptr DNAME[bx],'.' + je move80 + mov cx,11 +move40: ; fill in the wild card characters + lodsb ; get next character from new name +if KANJI + call dbcs_lead ; is it the 1st of a kanji pair + jne move45 + dec cx ; copied this one + jcxz move55 ; discard if no room for kanji char + stosb ; copy 1st byte of Kanji pair + inc bx + lodsb ; copy 2nd byte + jmps move50 +move45: +endif + call toupper ; make it upper case + cmp al,'?' ; is it just a wild card? + jne move50 ; no, put in destination as is + mov al,[bx] ; else leave original character +move50: ; AL = next char for destination + stosb ; store next char in destination + inc bx ; increment all pointers + loop move40 ; repeat for all 11 characters +move55: + + call finddfcbf ; find first non-volume entry + jnz move_access ; file already exists, return error + + call move_comp ; source & destination in same dir? + jne move60 ; skip if moving to different directory + call move_seek ; else find old entry again + jmps move70 ; replace name in old entry + +move60: ; moving to different directory + test save_area+DATTS,DA_DIR ; can't move directory to new path + jnz move_access ; so return error if new path + call allocdir ; allocate a directory entry +move70: + mov si,offset info_fcb+1 ; get pointer to new name + mov di,dirp ; get pointer to directory entry + mov cx,11 ; copy new name into buffer + rep movsb + + + mov si,offset save_area+11 ; copy remaining info + mov cx,32-11 + rep movsb + call update_dir ; update the disk + + call move_comp ; did we rename across directories? + je move80 ; skip if in same directory + mov si,offset saved_hds + mov di,offset fdos_hds ; else need to copy HDS back + mov cx,HDS_LEN ; so we can get old entry again + rep movsb ; (time to get rid of it) + call move_seek ; seek the original entry + mov bx,dirp + mov DNAME[bx],0E5h ; and bye, bye! it goes... + call update_dir ; update the old directory entry +move80: + cmp ss:remote_call,0 ; wildcards allowed if server/FCB + jz move90 ; so check for multiple files + call path_prep ; parse the path, go to bottom level + + mov ax,saved_dcnt ; restore dcnt for remote call + mov dcnt,ax ; to function properly + and chdblk,0 + + call finddfcb ; try to locate another directory entry + jz move90 ; no, return now + jmp move20 ; round again if we do + +move_access: + jmp fdos_ED_ACCESS ; "access denied" if file + ; already exists +move90: +; in order to update the current directory in case part of it has been +; renamed we call fdos_chdir which does all the work for rebuilding +; the LDT_ for the given drive + push ss + pop ds + mov bx,offset sec_pathname + mov ax,path_drive + add ax,'A'+(':'*100h) + mov [bx],ax + mov word ptr 2[bx],'.' + mov fdos_pb+4,ds + mov fdos_pb+2,bx + mov byte ptr remote_call,0 + jmp fdos_move_chdir + +move_seek: ; re-seek the old directory entry + mov ax,saved_dcnt ; get saved directory count + dec ax ; move back one for GETDIR + mov dcnt,ax ; set search offset + and chdblk,0 ; follow the chains, not sequential + mov cl,0 ; return next entry + jmp getdir ; in current directory + +move_comp: + mov ax,fdos_hds_blk + cmp ax,saved_hds_blk + ret + +eject +; GET/SET FILE DATE/TIME + +; +----+----+----+----+----+----+----+----+----+----+ +; | 57 | handle | mode | date | time | +; +----+----+----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; handle: open file handle +; mode: 0 = get date/time, 1 = set date/time +; date: date as in directory FCB +; time: time as in directory FCB + +; exit: +; ----- +; AX: 0000 or error code ( < 0) +; date: date of last modification if mode = 0 +; time: date of last modification if mode = 0 + +fdos_dattim: +;----------- + call vfy_dhndl_ptr ; check file handle # + call redir_dhndl_offer + call local_disk ; get MXdisk, switch stack + call check_handle ; check if legal file handle + cmp fdos_pb+4,0 ; get/set date/time? + jne dattim1 + mov ax,es:DHNDL_DATE[bx] ; get date + mov fdos_pb+6,ax + mov ax,es:DHNDL_TIME[bx] ; get time + mov fdos_pb+8,ax + ret +dattim1: ; else set date/time stamp + mov dx,fdos_pb+6 ; set date + mov ax,fdos_pb+8 ; and time + jmps set_timestamp + + Public timestamp_dhndl + +timestamp_dhndl: +;--------------- +; On Entry: +; ES:BX -> DHNDL_ +; On Exit: +; ES:BX preserved +; +; Mark this DHNDL_ with the current time and date + push es + push bx + call ReadTOD ; get TOD in DX/AX + pop bx + pop es +; jmp set_timestamp + +set_timestamp: +;------------- +; On Entry: +; ES:BX -> DHNDL_ +; AX = time +; DX = date +; On Exit: +; None +; + and es:DHNDL_ATTR[bx],not DHAT_CLEAN + mov es:DHNDL_DATE[bx],dx ; remember to update directory + mov es:DHNDL_TIME[bx],ax ; ask SHARE to record the changes + callf share_stub+S_RECORD ; for the benefit of others + ret + + +fdos_reopen_fcb: +;--------------- +; On entry +; On exit on success pb offset 6 set to 0 if device, 1 if disk file + test byte ptr remote_call+1,DHM_FCB/100h + jnz fcb_reopen0 + mov ax,ED_FUNCTION + jmp fdos_error +fcb_reopen0: + call local_disk + call path_prep + jc fcb_reopen_error ; any error means reopen is invalid + call check_device + jnc fcb_reopen_error ; we should not find devices here + mov ax,fdos_pb+6 + mov fdos_hds_blk,ax + mov ax,fdos_pb+8 + dec ax + mov dcnt,ax + xor cx,cx + mov chdblk,cx + call getdir + jz fcb_reopen_error + cmp DNAME[bx],0e5h ; has the entry been deleted ? + je fcb_reopen_error + mov fdos_pb+2,ax + ret +fcb_reopen_error: + mov ax,ED_NOFCBS + jmp fdos_error diff --git a/IBMDOS/HEADER.A86 b/IBMDOS/HEADER.A86 new file mode 100644 index 0000000..fd62665 --- /dev/null +++ b/IBMDOS/HEADER.A86 @@ -0,0 +1,1574 @@ +; File : $HEADER.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; $Log: $ +; HEADER.A86 1.26 94/12/02 09:34:18 +; added FCB LRU counter and sharing flag +; HEADER.A86 1.24 94/11/15 08:53:04 +; Fixed the NWDOS.386 stuff. Still point at startupinfo, but take out the +; vxdname and the vxdnameseg entries. +; HEADER.A86 1.23 94/06/28 14:31:07 +; Fix last_key_ext bug +; HEADER.A86 1.17 93/11/22 15:23:16 +; Move idle data to instance page to get per domain idle detection +; HEADER.A86 1.15 93/11/08 19:09:22 +; Handle EXEPACK problems even if DOS not in HMA +; HEADER.A86 1.14 93/11/14 18:14:21 +; Initialise fdos_buf to 2/0 +; HEADER.A86 1.13 93/10/07 19:08:25 +; CALL5 always goes through 0:C0 (or FFFF:D0 alias) +; HEADER.A86 1.12 93/09/03 20:28:39 +; Add intl/dbcs support for int 21/6523 (query yes/no char) +; HEADER.A86 1.11 93/09/02 22:26:24 +; Make uppercase tables compatible (See COMPATIBLE flag in COUNTRY.SYS) +; HEADER.A86 1.9 93/08/10 17:41:25 +; Move code fragments for Rolodex Live +; HEADER.A86 1.8 93/08/04 15:15:39 +; re-arrange dummy fcbs +; HEADER.A86 1.6 93/07/22 19:29:19 +; add no/yes characters +; HEADER.A86 1.5 93/07/20 22:46:33 +; dmd_upper_root defaults to FFFF +; ENDLOG +; + +; DRDOS Header/Initialization Code +; +; NB. +; On a system where the kernel stays low and history is disabled we throw +; away as much code as possible. This includes the patch area, the command +; line history code, and the BDOS initialisation code. +; As we use the patch area the pointer in the header should be incremented +; in order to retain progressively larger amounts of code. + + include pcmode.equ + include vectors.def + + include i:cmdline.equ + include i:doshndl.def + include i:driver.equ + include i:exe.def + include i:f52data.def + include i:fdos.equ + include i:mserror.equ + include i:psp.def + include i:reqhdr.equ + include i:country.def + +PADDING equ 14*1024 ; offset code start by this much + +DOSINROM equ 0800h +DOSINHMA equ 1000h + + +;**************************************************************************** +; The format of the header is FIXED and should not be modified. +;**************************************************************************** + +PCM_HEADER CSEG PARA + + extrn edit_size:word + + dw PADDING + rb PADDING-2 ; Insert Header + + Public code_start +code_start: + +; jmp pcmode_init ; PCMODE Init Entry + db 0E9h + dw pcmode_init-PADDING-3 +; jmp pcmode_reinit ; PCMODE Re Init Entry + db 0E9h + dw pcmode_reinit-PADDING-6 + + Public pcmode_dseg, os_version, patch_version + +pcmode_dseg dw 0 ; 0006h PCMODE Data Segment Pointer + dw PADDING ; 0008h offset of start of code +os_version dw 1072h ; 000Ah OS version + dw patch_area-PADDING ; 000Ch offset of disposable code + dw pcmode_init-PADDING ; 000Eh offset of initialisation code + db 0EAh ; 0010h JMPF (MUST be para aligned) + dw 4*30h ; 0011h through the Int 30 vec + dw 0 ; 0013h to CALL 5 entry point + rb 7 ; 0015h make following offsets same as 5.0 + dw 0 ; 001Ch Compressed Data Flag + dw code_end-PADDING ; 001Eh PCMODE Code Size in Bytes + dw data_end ; 0020h PCMODE Data Length in Bytes +patch_version dw DOSINROM+0000h ; 0022h sub-version (was SYSDAT length) + db 0 ; 0024h Kanji Support Flag + db 0 ; 0025h Reserved + dw edit_size-PADDING ; 0026h Pointer Command Line Editor + ; control table. + dw NoYesChars ; 0028h offset in data of pointers to + ; default country info. + +;**************************************************************************** +; The format of the data is FIXED and should not be modified. +;**************************************************************************** + +PCMODE_DATA DSEG WORD + + + Public codeSeg ; BDOS code segment + Public dmd_root ; Root of DOS Memory List + Public hmaRoot ; Root of HMA chain + Public func52_data ; Start of the FUNC 52 compatible data + Public last_drv ; Last Drive + Public phys_drv + Public dev_root ; Root of Device List + Public nul_device ; NUL Device + Public ddsc_ptr + Public retcode + Public user_retcode + Public system_retcode + Public break_sp + Public net_retry + Public net_delay + Public file_ptr + Public clk_device ; Clock Device Pointer + Public con_device ; Console Device Pointer + Public bcb_root ; Linked List of Buffers + Public fcb_ptr + Public ldt_ptr + Public join_drv + Public share_stub + Public sector_size + Public setverPtr + Public dos_version + + Public @hist_flg ; History control flag + Public dmd_address ; don't free DMD's with segment under this value + Public dmd_owner ; don't free DMD's with owner under this value + Public dmd_upper_root ; link to upper memory + Public dmd_upper_link + Public LocalMachineID ; Normal 0, fixed up by multi-tasker + + Public biosDate ; 6 byte buffer to read/write clock + Public minute + Public hour + Public hundredth + Public second + Public dayOfMonth + Public month + Public yearsSince1980 + Public daysSince1980 + Public dayOfWeek + + + org 0 + +dos_data db 0 + dw code_start + rb 1 ; padding +if DOS5 + dw 1 +else + dw 0 +endif + + +; make end of vladivar instance data public for the multi-tasker + rb 06h - (offset $ - offset dos_data) + dw endOfInstanceData + + rb 0eh - (offset $ - offset dos_data) + Public netbios, name_num, fcb_lru_count +netbios db 0 ; NetBios Name Number +name_num db 0 ; 0 - Undefined Name +fcb_lru_count dw 0 ; fcb LRU counter + + rb 26h-0ch-(offset $ - offset dos_data) ; align func52_data on 26 + +;************************************************************************ +;* * +;* Below is the DOS defined area of the SYSTEM variables * +;* above are variables defined for DR DOS. * +;* * +;************************************************************************ +net_retry dw 3 ;-000C Network retry count +net_delay dw 1 ;-000A Network delay count +bcb_root dw -1,-1 ;-0008 Current DOS disk buffer + dw 0 ;-0004 Unread CON input +dmd_root dw 0 ;-0002 Root of DOS Memory List (Segment) +func52_data rb 0 +ddsc_ptr rd 0 ; 0000 DWORD ptr to DDSC + dw -1,-1 +file_ptr rd 0 ; 0004 DWORD ptr file table + dw msdos_file_tbl,0 +clk_device rd 0 ; 0008 DWORD ptr Clock Device Header + dw -1,-1 ; Initialize to an Invalid Address +con_device rd 0 ; 000C DWORD ptr Console Device Header + dw -1,-1 ; Initialize to an Invalid Address +sector_size dw 128 ; 0010 WORD Buffer Size (Max Sector Size) +buf_ptr dw buf_info,0 ; 0012 DWORD ptr to Disk Buffer Info +ldt_ptr dw 0,0 ; 0016 DWORD ptr Path Structures +fcb_ptr dw dummy_fcbs,0 ; 001A DWORD ptr FCB Control Structures + dw 0 ; 001E WORD UNKNOWN +phys_drv db 0 ; 0020 BYTE Number of Physical Drives +last_drv db 0 ; 0021 BYTE Last Drive +dev_root rd 0 ; 0022 DWORD ptr Device Driver List +nul_device dw -1,-1 ; Next Device Pointer + dw DA_CHARDEV+DA_ISNUL ; 0026 NUL Device Attributes + dw nul_strat ; 0028 NUL Device Strategy routine + dw nul_int ; 002A NUL Device Interrupt routine + db 'NUL ' ; 002C NUL Device Name +join_drv db 0 ; 0034 BYTE Number of JOIN'd drives + dw 0 ; 0035 DOS 4 pointer to special names (always zero in DOS 5) +setverPtr dw 0,0 ; 0037 setver list + dw 0 ; 003B unknown + dw 0 ; 003D psp of last umb exec + dw 1 ; 003F number of buffers + dw 1 ; 0041 size of pre-read buffer + public bootDrv +bootDrv db 0 ; 0043 drive we booted from + db 0 ; 0044 cpu type (1 if >=386) + dw 0 ; 0045 Extended memory +buf_info rd 1 ; 0047 disk buffer chain + dw 0 ; 004B 0 (DOS 4 = # hashing chains) + rd 1 ; 004D pre-read buffer + dw 0 ; 0051 # of sectors + db 0 ; 0053 00=conv 01=HMA + dw 0 ; 0054 deblock buf in conv +deblock_seg dw 0 ; 0056 (offset always zero) + rb 3 ; 0058 unknown + dw 0 ; 005B unknown + db 0, 0FFh, 0 ; 005D unknown + db 0 ; 0060 unknown + dw 0 ; 0061 unknown +dmd_upper_link db 0 ; 0063 upper memory link flag + dw 0 ; 0064 unknown +dmd_upper_root dw 0FFFFh ; 0066 dmd_upper_root + dw 0 ; 0068 para of last mem search + + dw invalid_stub,0 ; 006A DWORD ptr to 15 + dw nul_int,0 ; 006E SHARE STUB routines + dw nul_int,0 ; 0072 + dw nul_int,0 ; 0076 + dw nul_int,0 ; 007A + dw nul_int,0 ; 007E + dw nul_int,0 ; 0082 + dw nul_int,0 ; 0086 + dw nul_int,0 ; 008A + dw nul_int,0 ; 008E + dw invalid_stub,0 ; 0092 + dw nul_int,0 ; 0096 + dw nul_int,0 ; 009A + dw nul_int,0 ; 009E + dw nul_int,0 ; 00A2 + +msdos_file_tbl dw -1 ; 00A6 1st HDB entries + dw -1 ; Pointer to next Entry (None) + dw 5 ; Number of Entries + + rb 5*DHNDL_LEN ; Reserve 5 Internal Handles + + rb 1fbh - (offset $ - offset dos_data) + + Public savbuf +savbuf rb 128 ; cmdline editing temp buffer + Public fdos_buf +fdos_buf db 2,0 ; initialise buffer to empty + rb 128+1 ; room for 128 byte readline + LF + + rb 2feh - (offset $ - offset dos_data) +; this byte is used for ^P support + Public cio_state +cio_state db 0 ; 0 = no printer echo, ~0 echo + Public verify_flag +verify_flag db 0 ; ~0, write with verify + + rb 300h - (offset $ - offset dos_data) +; this byte is used for TAB's + Public column +column db 0 ; Current Cursor Column + Public switch_char +switch_char db '/' + Public mem_strategy +mem_strategy db 0 ; memory allocation strategy + Public sharing_flag +sharing_flag db 0 ; 00 = sharing module not loaded + ; 01 = sharing module loaded, but + ; open/close for block devices + ; disabled + ; FF = sharing module loaded, + ; open/close for block devices + ; enabled (not implemented) + Public net_set_count +net_set_count db 1 ; count the name below was set + Public net_name +net_name db ' ' ; 15 Character Network Name + db 00 ; Terminating 0 byte + +; These tables point to routines to be patched by MSNET + dw criticalSectionEnable + dw criticalSectionEnable + dw criticalSectionEnable + dw criticalSectionEnable + dw 0 ; terminating null + + rb 1 ; padding + +; +; Variables contained the the "STATE_DATA" segment contain +; information about the STATE of the current DOS Process. These +; variables must be preserved regardless of the state of the INDOS +; flag. +; +; All variables that appear in "STATE_DATA" **MUST** be declared +; in this file as the offsets from the INTERNAL_DATA variable are +; critical to the DOS applications that modify this data area. +; +; + Public error_flag, indos_flag + Public error_locus, error_code + Public error_action, error_class + Public error_dev, error_drive + Public dma_offset, dma_segment + Public current_psp, current_dsk + Public break_flag + + Public internal_data + +internal_data rw 0 ; <-- Address returned by INT21/5D06 +error_flag db 0 ; INDOS - 01 - Error Mode Flag +indos_flag db 0 ; INDOS + 00 - Indos Flag +error_drive db 0 ; INDOS + 01 - Drive on write protect error +error_locus db 0 ; INDOS + 02 - Error Locus +error_code dw 0 ; INDOS + 03 - DOS format error Code +error_action db 0 ; INDOS + 05 - Error Action Code +error_class db 0 ; INDOS + 06 - Error Class +error_dev rd 1 ; INDOS + 07 - Failing Device Address +dma_offset rw 1 ; INDOS + 0B - DMA Offset +dma_segment rw 1 ; INDOS + 0D - DMA Segment +current_psp rw 1 ; INDOS + 0F - Current PSP +break_sp rw 1 ; INDOS + 11 - used in int 23 +retcode rw 0 +user_retcode db 0 ; INDOS + 13 - return code from process +system_retcode db 0 ; INDOS + 14 - reason for process terminate +current_dsk db 0 ; INDOS + 15 - Current Drive +break_flag db 0 ; INDOS + 16 - Break Flag + dw 0 ; INDOS + 17 - unknown + + Public swap_always +swap_always rw 0 + + Public int21AX +int21AX dw 0 ; INDOS + 19 - AX from last Int 21 + + Public owning_psp, machine_id +owning_psp dw 0 ; INDOS + 1B - owning psp +machine_id dw 0 ; INDOS + 1D - remote machine ID + + + public load_psp, load_image, load_top, load_max, load_handle + +load_psp dw 0 ; Paragraph of the new PSP. +load_image dw 0 ; Paragraph of the Load Image. +load_top dw 0 ; Last paragraph of Allocated Memory +load_max dw 0 ; ditto, but not messed with +load_handle dw 0 ; Handle allocated to load file on OPEN + + Public locus, valid_flg, retry_off, retry_sp +locus db 0 ; Public Error Locus Value +valid_flg db 0 ; Valid Options for Critical Error +retry_off dw 0 ; IP for Error Retry +retry_sp dw 0 ; SP for Error Retry + + + +; Some important data structures.... + rb 0350h - (offset $ - offset dos_data) ; DOS 5 +dayOfMonth db 0 +month db 0 +yearsSince1980 dw 0 +daysSince1980 dw 0FFFFh ; force rebuild on first clock read +dayOfWeek db 0 + + public internal_flag +internal_flag db 0 + + Public int28_flag +int28_flag db FALSE + + + public ioctlRH + +ioctlRH rb 23 ; up to 23 bytes possible + + public load_env, load_envsize, exe_loadhigh +load_env dw 0 ; Paragraph of the new environment +load_envsize dw 0 ; Size of new environment +exe_loadhigh db 0 ; load high flag + + + Public fcb_pb, fcb_path, fcb_path2 + +; These variables are used during FCB processing - we build another parameter +; block outside the MXDisk which makes handle calls to the FDOS + +fcb_pb rw 7 +fcb_path rb 15 +fcb_path2 rb 15 + + public char_count +char_count db 0 + + +;**************************************************************************** +; The format of the data is FIXED and should not be modified. +;**************************************************************************** + +; WARNING - if anyone adds/deletes PCMODE_DATA they MUST adjust these +; values so the following data will origin correctly +FIXED_DOS_DATA cseg word + +FIXED_DATA_START equ 3B0h + public MUSTBE03B0 +MUSTBE03B0: + + org 03b6h - FIXED_DATA_START ; DOS 5 +biosDate dw 0 ; days since 1980 +minute db 0 +hour db 0 +hundredth db 0 +second db 0 + rb 2 ; padding + + Public reloc_buf, load_file, RELOC_CNT +RELOC_CNT equ 80h/16 ; buffer 128 bytes here + +; function 4B uses these data area's as workspace during an EXEC + + Public pri_pathname +reloc_buf rb 0 ; shared with primary pathname +pri_pathname rb 80h + Public sec_pathname +load_file rb 0 +sec_pathname rb 80h + Public srch_buf +srch_buf rb 21+32 ; 21 byte srch state, 32 byte dir entry + Public temp_ldt +temp_ldt rb LDT_LEN + Public name_buf +name_buf rb 32 ; space enough for 1 dir entry + +magic_byte db 0 + rb 1 ; padding + Public file_attrib +file_attrib dw 0 + rb 3 ; padding + Public remote_call +remote_call dw 0 + + + org 057Ch - FIXED_DATA_START + Public exit_type ; used by break and critical error +exit_type db 0 ; handlers during termination + rb 1 ; padding + Public term_psp +term_psp dw 0 + + Public int24_esbp +int24_esbp rw 2 + Public int21regs_ptr, int21regs_off, int21regs_seg +int21regs_ptr rw 0 +int21regs_off dw 0 +int21regs_seg dw 0 + public critical_sp +critical_sp dw 0 ; critical error internal stack + Public current_ddsc +current_ddsc rw 2 + + org 059ah - FIXED_DATA_START + Public current_device +current_device rw 2 + Public current_dhndl +current_dhndl rw 2 + Public current_ldt +current_ldt rw 2 + rw 2 ; pointer to callers FCB + Public current_ifn +current_ifn dw 0 + + org 05b2h - FIXED_DATA_START + dw offset pri_pathname + dw offset sec_pathname + dw offset pri_pathname + + org 05ceh - FIXED_DATA_START + Public current_filepos +current_filepos rw 2 + + org 05f0h - FIXED_DATA_START + Public prev_int21regs_ptr, prev_int21regs_off, prev_int21regs_seg +prev_int21regs_ptr rw 0 +prev_int21regs_off dw 0 +prev_int21regs_seg dw 0 + + org 0620h - FIXED_DATA_START + + Public indos_stack, error_stack, normal_stack + + Public fcb_search_buf ; during FCB search 1st/next use bottom +fcb_search_buf rb 0 ; of error stack as scratch buffer + ; rb 43 ; - only used during int 21 call + + rw STACK_SIZE ; Error Processing Stack +error_stack rw 0 + + rw STACK_SIZE ; Normal Function Stack Area +normal_stack rw 0 + + rw STACK_SIZE ; Indos Function Stack +indos_stack rw 0 + +lookahead_flag db 0 + + Public rwmode, err_drv, ioexerr +err_drv db 0 +rwmode db 0 +ioexerr db 0 + public int2f_cmd, int2f_stack, file_mode +int2f_cmd dw 0 +int2f_stack dw 0 +file_mode dw 0 + Public cle_state +cle_state dw 0 + Public swap_indos +swap_indos rw 0 + + org 0AADh - FIXED_DATA_START + +Ucasetbl dw 128 ; Table Size + db 080h, 09ah, 'E', 'A', 08eh, 'A', 08fh, 080h + db 'E', 'E', 'E', 'I', 'I', 'I', 08eh, 08fh + db 090h, 092h, 092h, 'O', 099h, 'O', 'U', 'U' + db 'Y', 099h, 09ah, 09bh, 09ch, 09dh, 09eh, 09fh + db 'A', 'I', 'O', 'U', 0a5h, 0a5h, 0a6h, 0a7h + db 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 0e1h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh +info2_len equ word ptr (offset $ - offset Ucasetbl) + + + org 0B2Fh - FIXED_DATA_START +; Filename upper case table +FileUcasetbl dw 128 ; Table Size +standard_table rb 0 + db 080h, 09ah, 'E', 'A', 08eh, 'A', 08fh, 080h + db 'E', 'E', 'E', 'I', 'I', 'I', 08eh, 08fh + db 090h, 092h, 092h, 'O', 099h, 'O', 'U', 'U' + db 'Y', 099h, 09ah, 09bh, 09ch, 09dh, 09eh, 09fh + db 'A', 'I', 'O', 'U', 0a5h, 0a5h, 0a6h, 0a7h + db 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 0e1h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh + +info4_len equ word ptr (offset $ - offset FileUcasetbl) + + org 0BB1h - FIXED_DATA_START + +FileCharstbl: + dw 22 ; Table Size + db 001h, 000h, 0ffh, 000h, 000h, 020h, 002h, 00eh + db 02eh, 022h, 02fh, 05ch, 05bh, 05dh, 03ah, 07ch + db 03ch, 03eh, 02bh, 03dh, 03bh, 02ch +info5_len equ word ptr (offset $ - offset FileCharstbl) + + org 0BE1h - FIXED_DATA_START + +Collatingtbl: + dw 256 ; Table Size + db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h + db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh + db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h + db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh + db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h + db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh + db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h + db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh + db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh + db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h + db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh + db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h + db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh + db 043h, 055h, 045h, 041h, 041h, 041h, 041h, 043h + db 045h, 045h, 045h, 049h, 049h, 049h, 041h, 041h + db 045h, 041h, 041h, 04fh, 04fh, 04fh, 055h, 055h + db 059h, 04fh, 055h, 024h, 024h, 024h, 024h, 024h + db 041h, 049h, 04fh, 055h, 04eh, 04eh, 0a6h, 0a7h + db 03fh, 0a9h, 0aah, 0abh, 0ach, 021h, 022h, 022h + db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h + db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh + db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h + db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh + db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h + db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh + db 0e0h, 053h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h + db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh + db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h + db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh +info6_len equ word ptr (offset $ - offset Collatingtbl) + + org 0CE3h - FIXED_DATA_START + +DBCS_tbl: + dw 0 ; Table Size + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h +info7_len equ word ptr (offset $ - offset DBCS_tbl) + + + + org 0d12h - FIXED_DATA_START + +dos_version dw 6 ; our DOS version number + +; Don't know what these are for..... + db 0c8h,0a6h + db 0c8h,0a5h + db 0c8h,0a5h + db 0c8h,0a5h + +; Now we have a list of days in each month + Public days_in_month + +days_in_month db 31,28,31,30,31,30 ; Jan, Feb, Mar, Apr, May, Jun + db 31,31,30,31,30,31 ; Jul, Aug, Sep, Oct, Nov, Dec + + org 0d90h - FIXED_DATA_START + + Public last_key_ext + +;;last_key_ext db 0 ; flag set if last key zero +;** LINKER BODGE ** +; I'd like to do the above, but LINKCMD blows up when I do (it seems to be to +; many relocatable publics in the data segment that do it). So as a work around +; I do the below instead. Since the location is fixed anyway it works out OK. +last_key_ext equ byte ptr 0d90h +;** LINKER BODGE ** + + org 0e5bh - FIXED_DATA_START + +; +; Extended Error/Class/Action/Locus table. Used in conjuction with +; Int2F/1222 to setup extended error information + db 13h,0Bh,07h,02h + db 14h,04h,05h,01h + db 15h,05h,07h,0FFh + db 16h,04h,05h,01h + db 17h,0Bh,04h,02h + db 18h,04h,05h,01h + db 19h,05h,01h,02h + db 1Ah,0Bh,07h,02h + db 1Bh,0Bh,04h,02h + db 1Ch,02h,07h,04h + db 1Dh,05h,04h,0FFh + db 1Eh,05h,04h,0FFh + db 1Fh,0Dh,04h,0FFh + db 20h,0Ah,02h,02h + db 21h,0Ah,02h,02h + db 22h,0Bh,07h,02h + db 32h,09h,03h,03h + db 23h,07h,04h,01h + db 24h,01h,04h,05h + db 0FFh,0Dh,05h,0FFh + + org 0eabh - FIXED_DATA_START + +; This is a translation table from old error codes to extended errors + db 13h,14h,15h,16h,17h,18h,19h,1Ah + db 1Bh,1Ch,1Dh,1Eh,1Fh,1Fh,1Fh,22h + db 24h + + +; KLUDGE for DRDOS 6.0 security - the word at offset zero in SYSDAT (the +; SYStem DATa page) was the segment of the secure path string, with +; a zero value indicating a non-secure system. +; In order for DRDOS 6 level utilities to run we point SYSDAT at offset +; 10h in the DOS data segment (this unused word is zero). On secure systems +; the new LOGIN TSR will fix up both SYSDAT and the PD value to point to +; it's own dummy SYSDAT, and the utilities will behave correctly. + + Public @private_data + +@private_data rb 0 ; We need some private data + dw endOfInstanceData ; 0000 historical PD offset +dummy_sysdat dw 1 ; 0002 historical SYSDAT segment + dw offset histbuf1 ; 0004 History Control Block 1 + dw offset histbuf2 ; 0006 History Control Block 2 +@hist_flg db 0 ; 0008 History Control + ; Bit 0 = Buffer Select 1 = COMMAND + ; Bit 1 = History Enable 1 = ENABLE + db 1 ; 0009 Dual Language Version + db 0 ; 000A Current message language + dw 0 ; 000B Extended memory + db 0 ; 000D (was # JMPF entries to fix up) +codeSeg dw 0 ; 000E BDOS code segment (was seg of JMPF table) +hmaRoot dw 0 ; 0010 Root of himem free chain + dw 0 ; 0012 Initial Environment +hmaAlloc dw 0 ; 0014 Root of himem allocation chain +dmd_owner dw 0 ; 0016 Owner below which DMD's not freed + dw 0 ; 0018 Link to upper memory DMD's +LocalMachineID dw 0 ; 001A Patched by multi-tasker to correct value +dmd_address dw 0 ; 001C Address below which DMD's not freed + dw offset country_filename +hashptr dw 0,0 ; 0020 hash root +hashmax dw 0 ; 0024 max dir entries hashed + dw 0 ; 0026 was deblock seg + dw offset share_stub + ; 0028 share stub offset + dw offset globalPrivateData + ; 002A pointer to global private data + dw offset int2FBiosHandler + ; 002C pointer to int 2F internal hook + rw 10 ; space for expansion + + Public deblock_seg, fdos_stub + +fdos_stub dw fdos_stub_entry + dw 0 ; fixup up at run time + +share_stub dw invalid_stub,0 ; DWORD ptr to 15 + dw nul_int,0 ; SHARE STUB routines + dw nul_int,0 ; + dw nul_int,0 ; + dw nul_int,0 ; + dw nul_int,0 ; + dw nul_int,0 ; + dw nul_int,0 ; + dw nul_int,0 ; + dw nul_int,0 ; + dw invalid_stub,0 ; + dw nul_int,0 ; + dw nul_int,0 ; + dw nul_int,0 ; + dw nul_int,0 ; + + + Public WindowsHandleCheck +WindowsHandleCheck db 26h ; MUST follow share_stub + ; patched by switcher + + + org 0FC0h - FIXED_DATA_START + +childSP dw 0 +childSS dw 0 +childIP dw 0 +childCS dw 0 + +; The following table defines the format of a DOS .EXE format file. +; The .EXE header is read into this data area and check for integrity +; + Public exe_buffer +exe_buffer rb EXE_LENGTH ; Local EXE header buffer + + +if IDLE_DETECT + + Public idle_data + Public active_cnt, idle_max + Public idle_flags, idle_vec + +idle_data rw 0 ; Idle State Data Area +active_cnt dw 0 ; InActive Function Count +idle_max dw 10 ; Max No. of consecutive funcs. +idle_flags dw IDLE_INIT ; $IDLE$ Has not been loaded +idle_vec rd 1 ; DWORD pointer to IDLE handler + + + Public int28_delay, int28_reload +int28_delay dw 0 ; No. Consecutive INT28's +int28_reload dw 10 ; INT28 Delay Reload Value + dw indos_flag ; Offset of INDOS_FLAG + rw 2 ; 2 OEM Reserved Words +endif + + org 1000h - FIXED_DATA_START ; nice 4K boundry + ; for multitasker + +PCMODE_DSIZE DSEG PARA + + Public data_end +data_end rw 0 + + +PCMODE_CODE CSEG WORD 'DATA' + + +PCMODE_CODE_START equ 1000h + public MUSTBE1000 +MUSTBE1000: + + Public endOfInstanceData + +endOfInstanceData rw 0 + +;*** fixed data - init does segment fixups *** + +stub_entries rw 0 + + Public lock_bios, unlock_bios, lock_tables, unlock_tables + +lock_bios dw lockbios,0 ; MSNET critical region stubs +unlock_bios dw unlockbios,0 ; MSNET critical region stubs +lock_tables dw locktables,0 ; MSNET critical region stubs +unlock_tables dw unlocktables,0 ; MSNET critical region stubs + + Public exec_stub +exec_stub dw ExecStub,0 ; Int 21 EXEC hook + public func4B05_stub +func4B05_stub dw Func4B05Stub,0 ; Int 21/4B05 hook + +NUM_STUB_ENTRIES equ (offset $ - offset stub_entries)/4 +;*** fixed data ends *** + + cmp ds:error_flag,0 ; JT-FAX uses this code sequence to + jnz $ ; find the address of the ERROR_FLAG + mov sp,0A06h + + test ss:error_flag,0FFh ; SIDEKICK usues this fragment to + jnz $ ; locate the ERROR_FLAG + push ss:word ptr int28_flag + int 28h + +;========================== +; Entry points for DOS Code +;========================== +; +; These are normally all of the form +; +;EntryPoint: +; JMPF xxxx:RealEntryPoint +; db 3 dup(?) +; +; When we are in the HMA, and so may disable the HMA during EXEC for EXEPACK +; problems, we convert them to the following +; +;EntryPoint: +; call A20Enable +; JMPF xxxx:RealEntryPoint +; +; On an exec the A20 gate is disabled. This allows EXEPACKed programs to +; unpack properly. (some exepacked apps have a wrap-round bug which addresses +; the bottom 64K via the HMA). +; +; On the first Int 21 etc the A20Enable routine enables the A20 gate. +; + + extrn int20_entry:near, int21_entry:near + extrn int25_entry:near, int26_entry:near + extrn int27_entry:near, int2F_entry:near + extrn call5_entry:near + +FirstCodeEntryPoint rw 0 + +Int20Entry: + db 0EAh ; JMPF + dw int20_entry + rb 5 ; filled in at run time + + +Int21Entry: + db 0EAh ; JMPF + dw int21_entry + rb 5 ; filled in at run time + +Int25Entry: + db 0EAh ; JMPF + dw int25_entry + rb 5 ; filled in at run time + +Int26Entry: + db 0EAh ; JMPF + dw int26_entry + rb 5 ; filled in at run time + +Int27Entry: + db 0EAh ; JMPF + dw int27_entry + rb 5 ; filled in at run time + +Int2FEntry: + db 0EAh ; JMPF + dw int2f_entry + rb 5 ; filled in at run time + +Call5Entry: + db 0EAh ; JMPF + dw call5_entry + rb 5 ; filled in at run time + +LastCodeEntryPoint rw 0 + + +BIOSA20Enable: +;------------- +; CALLF'd by the BIOS + call A20Enable ; do a near call + sti ; re-enable interrupts + retf ; RETF to BIOS + + +A20Disable: +;---------- +; On Entry: +; DX = psp we are execing + cmp dx,0FF0h ; if we are above 64K skip the + jae A20Disable10 ; EXE pack kludge + push ax + mov ah,6 ; disable the A20 gate during EXEC + callf cs:xmsDriver ; so buggy EXE packing will work + pop ax +A20Disable10: + ret + +A20Enable: +;--------- +; On Entry: +; None +; WARNING - DS/ES/STACK could be anything +; On Exit: +; All regs preserved +; +; Unhook our Entry stubs so we don't get here again. +; Enable the global A20 line to make the DOS/BIOS/COMMAND code visible +; + cli + push ax + push ds + mov ax,0FFFFh + mov ds,ax + mov ax,ds:.94h ; is the HMA alias for Int 21 + or ax,ds:.96h ; zero - if so the HMA is there + pop ds + jnz A20Enable10 + pop ax + ret + +A20Enable10: +; We need to enable the A20 gate, go do so + push bx + mov cs:oldSS,ss ; save stack + mov cs:oldSP,sp + mov ax,cs + mov ss,ax ; swap to the error stack in case + mov sp,offset error_stack ; 3rd part XMS driver needs a lot + + mov ah,5 ; enable A20, ignoring errors as we + callf cs:xmsDriver ; can't do anything about them + + mov ss,cs:oldSS ; switch back to callers stack + mov sp,cs:oldSP + + pop bx + pop ax + ret + +oldSS dw 0 ; save area for stack swap +oldSP dw 0 + +; +++++++++++++++++++++++++++++++++ +; Default Int 24 Handler for DR DOS +; +++++++++++++++++++++++++++++++++ +; +; Our default critical error handler during boot simply FAIL's all +; critical errors. When COMMAND.COM is loaded this will install +; the "normal" Retry/Abort/Ignore handler. +; +; These interrupts normally point to an IRET. +; +; + +Int24Entry: +;========== + mov al,3 ; return "FAIL" +DummyIRET: +;========= + iret + +; EXEC Code +; +; In order to cope with old buggy EXEPACKED programs we need to turn +; the A20 gate of during the exec, and turn it back on asap. +; To do this we hook all the DOS code entry points and re-enable the +; A20 whenever the app issues an Int 21 etc +; + + +ExecStub: +;======== +; On Entry: +; AX = FCB validity flags +; DX = current PSP +; ES:SI -> new CS:IP +; CX:DI -> users stack +; On Exit: +; AX = FCB validity flags +; BX = 0 +; SS:SP = users stack +; CS:IP = values from EXE header +; DS = ES = DX = current PSP +; +; When we start execing the application we have the A20 gate disabled so +; buggy EXE packed programs will unpack properly. +; We also hook Int 21 and Int 2F to re-enable the A20 gate on the first +; calls made to them. (These should only happen AFTER the unpacking). +; + + call A20Disable + mov ss,cx ; switch to new USER stack + mov sp,di + push es + push si ; CS:IP on USER stack + mov ds,dx ; DS = ES = PSP we are exec'ing + mov es,dx + xor bx,bx ; BX = zero, set flags + sti + retf ; lets go! + +Func4B05Stub: +;============ +; On Entry: +; ES:BP -> callers stack +; DX = PSP to exec on +; On Exit: +; callers registers restored +; + call A20Disable ; turn off A20 + mov ax,es + mov ss,ax ; back to users stack + mov sp,bp + POP$DOS ; Restore Registers + iret + + + Public int2FNext, int2FBiosHandler + +Int2FBios: +;--------- +; On Entry: +; DS on stack +; On Exit: +; All regs preserved +; +; Pass on an Int 2F call to the BIOS + pop ds ; recover DS and pass on to BIOS + db 0EAh ; JMPF bios Int 2F entry point +int2FBiosHandler dw 0,0 ; filled in at run time +int2FNext dw Int2FBios, 0 ; seg filled in at run time + + +nul_strat: + cmp RH_CMD,CMD_INPUT + jne nul_strat10 ; if it's input + mov RH4_COUNT,0 ; Say none transferred #IJ +nul_strat10: + mov RH_STATUS,RHS_DONE ; Set the DONE bit in the +nul_int: ; Request Header and Return + clc ; (indicate success for SHARE) + retf + + Public invalid_stub + +invalid_stub: + mov ax,ED_FUNCTION ; indicate bad function +fdos_stub_entry: + stc ; indicate error + retf + + Public lock_bios, unlock_bios, lock_tables, unlock_tables + +lockbios: +;-------- + push ax + mov ax,8002h + jmps CriticalSection + +unlockbios: +;---------- + push ax + mov ax,8102h + jmps CriticalSection + +locktables: +;---------- + push ax + mov ax,8001h + jmps CriticalSection + +unlocktables: +;------------ + push ax + mov ax,8101h +; jmps CriticalSection + +CriticalSection: +;--------------- +; On Entry: +; AX = critical section number +; STACK = original AX +; On Exit: +; AX poped from stack +; + cmp cs:criticalSectionEnable,0 + je CriticalSection10 + int 2ah ; issue critical section callout +CriticalSection10: + pop ax + retf + + public criticalSectionEnable + +criticalSectionEnable db 0 + + + Public SwStartupInfo + +SwStartupInfo dw 3 ; version + dw 0 + dw 0 ; link to next in chain + +;; dw offset vxdName ; Virtual Dev file +;; replaced above line with DW 0 as vxd no longer required BAP + dw 0 + dw 0 + + dw 0,0 ; Reference Data + dw offset instanceItems +instanceSeg dw 0 + +;vxdName db 'A:\OPENDOS.386',0 + + public histbuf1, histsiz1, histbuf2, histsiz2 + +instanceItems: + dw 0 ; offset zero (for instancing) +histbuf1 dw 0 ; Command history buffer segment +histsiz1 dw 0 ; size (in bytes) + + dw 0 ; offset zero (for instancing) +histbuf2 dw 0 ; Application history buffer segment +histsiz2 dw 0 ; size (in bytes) + + +; some ROS fixups + dw 000h,050h,002h ; BASIC variables + dw 00Eh,050h,014h ; BASIC variables + +; some BIOS fixups + dw 0B8h,070h,004h ; BIOS req_hdr +; dw 16Ch,070h,002h ; BIOS dev_no (no longer required) + dw 600h,070h,002h ; BIOS local_char + +bdosInstanceFixups rw 0 + dw con_device,0,4 ; CON: device ptr + dw savbuf,0,column-savbuf+1 + dw dmd_upper_root,0,2 + dw dmd_upper_link,0,1 + dw exe_buffer,0,EXE_LENGTH + + dw 0,0 ; zero terminated instance list + + +xmsDriver rd 1 + +globalPrivateData: + rd 1 ; 0000 delwatch driver vector + rw 4 ; space for expansion + + +;** COUNTRY INFO ** + + +; +; The following routines are called by the end user using the DWORD +; pointers in the Country Data. Each Country Data area contains a +; pointer to one of the following routines. All valid charcater +; codes above 7Fh are translated to Upper Case +; + + Public xlat_xlat + +xlat_xlat: + cmp al,080h + jb xlat_exit + sub al,080h + push bx + mov bx,offset Standard_table + xlat cs:al + pop bx +xlat_exit: + retf + + + Public cur_country + Public cur_cp + Public default_country + Public country_data + Public Ucasetbl + Public FileUcasetbl + Public FileCharstbl + Public Collatingtbl + Public DBCS_tbl + Public info1_len + Public info2_len + Public info4_len + Public info5_len + Public info6_len + Public info7_len + Public intl_xlat + +; table of pointers to default country info. pointed to in BDOS header + Public NoYesChars + +NoYesChars db 'NnYy' + dw country_data + dw default_country + dw Ucasetbl + dw FileUcasetbl + dw FileCharstbl + dw Collatingtbl + dw DBCS_tbl + + + org 11F0h - PCMODE_CODE_START + + +dummy_fcbs dw 0ffffh ; terminate now + dw 0 + dw 1 ; with one entry + rb DHNDL_LEN ; this many bytes in it + + org 1232h - PCMODE_CODE_START + + Public country_filename +country_filename db '\COUNTRY.SYS' + rb 64 - length country_filename + + org 1276h - PCMODE_CODE_START + +; We fix the country tables at this location for the benefit of +; LAN Manager 2.2 extended edition. It peeks directly rather than use +; int 21/65 ! + +countryTable: + db 2 + dw offset UCasetbl,0 + db 4 + dw offset FileUCasetbl,0 + db 5 + dw offset FileCharstbl,0 + db 6 + dw offset Collatingtbl,0 + db 7 + dw DBCS_tbl,0 + db 1 + dw 26h +country_data: +cur_country dw 1 ; Country Code +cur_cp dw 437 ; Code Page +default_country: + dw US_DATE ; Date Format (Binary) + db '$',0,0,0,0 ; Currency Symbol + db ',',0 ; Thousands Separator + db '.',0 ; Decimal Separator + db '-',0 ; Date Separator + db ':',0 ; Time Separator + db 0 ; Symbol before Value without Space ($n.nn) + db 2 ; Significant Currency Digits + db CLOCK_12 ; Time Format +intl_xlat dw xlat_xlat ; Case Translation Routine + dw 0000h ; Case Translation Segment (Runtime Fixup) + db ',',0 ; Data List Separator +info1_len equ word ptr (offset $ - offset country_data) + ; If NOT COUNTRY.SYS then include the + rb 10 ; 10 zero bytes held at the end of the + ; country information. + +PCM_CODEND CSEG PARA + + Public code_end +code_end rb 0 + + +BDOS_DATA DSEG + + Public hashroot, hashmax + +; The hashroot must be global, but we also need to make it accessible +; during CONFIG so we copy it from the private data area + +hashroot dw 0,0 + + +PCM_HISTORY CSEG + +patch_area dw 0666h + include i:patch.cod + +PCM_ICODE cseg + +; +; The following routine initializes all the standard MS-DOS interrupt +; vectors which are initialized to point to the PC-MODE handlers. +; +; Entry: AX Memory Size - Paragraphs +; BX First Available Paragraph +; DL Initial Drive +; DS PCM Dseg +; +pcmode_init: + and cs:patch_version,not DOSINROM + ; won't clear if we are in ROM... + mov cs:pcmode_dseg,ds ; save PCM Dseg + mov ds:instanceSeg,ds ; fixup pointer to instance items + +; removed this as VxD no longer required BAP +; mov ds:vxdNameSeg,ds ; and vxdName + +; add ds:vxdName,dl ; fixup drive letter + mov ds:word ptr buf_ptr+2,ds + mov ds:word ptr file_ptr+2,ds + mov ds:word ptr fcb_ptr+2,ds + push ax ; Save the memory size + push bx ; First Free Paragraph + mov ds:current_dsk,dl ; save initial drive + inc dl ; make drive one based + mov ds:bootDrv,dl ; and save for func 3305 + mov ax,ds ; AX = PCMode Data + mov ds:word ptr fdos_stub+WORD,ax + add ds:dummy_sysdat,ax ; point dummy "sysdat" at a zero word + ; ie. dummy "secure path" segment + mov si,offset countryTable +countryFixupLoop: + mov ds:word ptr 3[si],ds ; fixup the segment + add si,5 ; onto the next entry + cmp ds:word ptr 3[si],0 ; done the lot yet ? + je countryFixupLoop + mov es,ax ; ES -> PCMode Data + mov di,offset stub_entries ; ES:DI -> stub segs + mov cx,NUM_STUB_ENTRIES ; entries to initialise +stubs_loop: + add di,WORD ; skip the offset + stosw ; fixup segment + loop stubs_loop ; do the next one + mov di,offset share_stub ; fixup the SHARE entries + mov cx,NUM_SHARE_STUB_ENTRIES +share_loop: + add di,WORD ; skip the offset + stosw ; fixup segment + loop share_loop +; mov cx,0 + mov es,cx ; Initialize the DOS vectors + + mov ax,es:.INT2F_OFFSET ; remember address of BIOS Int 2F + mov ds:int2FBiosHandler,ax + mov ax,es:.INT2F_SEGMENT + mov ds:int2FBiosHandler+2,ax + mov ds:int2FNext+2,ds ; fixup seg of out stub + + mov cx,40h-2Ah ; 2A-3F point at IRET in DOS Data Seg + mov di,INT2A_OFFSET +dummy_vecs_loop: + mov ax,offset DummyIRET ; point at an IRET + stosw ; do the offset + mov ax,ds + stosw ; then the segment + loop dummy_vecs_loop + + + mov si,offset def_data_vecs ; the following vector point to + mov cx,no_def_data_vecs ; pcmode DATA seg +def_data_vecs_loop: + lods cs:ax ! mov di,ax ; Get the Vector Offset (from CS) + db 2Eh ; CS: + movsw ; copy service routine offset + mov ax,ds ; finally fixup the segment too + stosw + loop def_data_vecs_loop + + mov es:byte ptr .INT30_OFFSET,0EAh + ; fixup CALL 5 JMPF + + mov si,offset bdosInstanceFixups +InstanceFixupLoop: + mov ds:2[si],ds ; fixup data segment + add si,6 ; onto next item + mov ax,ds:[si] ; still BDOS ? + or ax,ds:2[si] + jnz InstanceFixupLoop ; yep, do another one + + push cs ; we will have a RETF + call pcmode_reinit ; to return from this call + + pop ax ; First Free Paragraph + pop dx ; Restore the BIOS memory size + sub dx,ax ; convert to TPA size + dec dx ; Decrement the Size by DMD Size + push ax + add ax,dx ; AX = possible next DMD + mov es,ax + mov al,IDZ ; assume no extra DMD's + cmp al,es:DMD_ID ; have we extra one ? + jne pcmode_init10 + mov al,IDM ; yes, no longer end of chain + dec dx ; decrement by size of existing DMD +pcmode_init10: + pop es + mov es:DMD_ID,al ; Last DMD in list + mov es:DMD_PSP,0000h ; This is Free Memory Owning PSP == 0 + mov es:DMD_LEN,dx ; Save Memory Length + mov es:word ptr DMD_NAME,'S'+256*'D' + mov es:DMD_NAME+2,0 + mov ds:dmd_root,es ; Save the DMD address in root + retf + +eject +; +; +; On Entry: +; DS = DOS data seg + +pcmode_reinit: +;============= + mov ds:word ptr intl_xlat+2,ds + ; fixup intl case routine + mov ds:codeSeg,cs ; fixup code segment + + + mov ax,ds:hashptr ; make a copy of the hashroot + mov ds:hashroot,ax ; so it's global + mov ax,ds:hashptr+WORD + mov ds:hashroot+WORD,ax + mov al,ds:@hist_flg ; get initial history flags + and ax,RLF_ENHANCED+RLF_INS+RLF_SEARCH + mov ds:cle_state,ax ; use to set initial editing state + + mov ds:word ptr xmsDriver,offset invalid_stub + mov ds:word ptr xmsDriver+2,ds + + mov bx,offset FirstCodeEntryPoint +pcmode_reinit10: + mov ds:3[bx],cs ; fixup segment of the JMPF + add bx,8 ; onto the next one + cmp bx,offset LastCodeEntryPoint + jb pcmode_reinit10 + mov ax,ds:hmaRoot ; have we established an HMA free chain + or ax,ds:hmaAlloc ; or have any registered users ? + jz pcmode_reinit30 ; if so hook for EXEPACK support + mov ax,4300h + int 2Fh ; do we have an XMS driver ? + cmp al,80h ; 80h says yes + jne pcmode_reinit30 + mov ax,4310h ; get it's entry point + int 2Fh ; in ES:BX + mov ds:word ptr xmsDriver,bx + mov ds:word ptr xmsDriver+2,es + + mov ax,0FFFFh + mov es,ax + inc ax ; AX = 0 + mov es:.94h,ax ; zero the HMA alias for Int 21 + mov es:.96h,ax ; we use this as our A20 gate test + + mov bx,offset FirstCodeEntryPoint +pcmode_reinit20: + mov ax,offset A20Enable-3 ; we need a relative offset to + sub ax,bx ; poke in a "call A20Enable" + xchg ax,ds:1[bx] ; pick up the entry point segment + mov ds:byte ptr 0[bx],0E8h ; CALL NEAR + mov ds:byte ptr 3[bx],0EAh ; JMPF + mov ds:4[bx],ax ; fixup the offset + mov ds:6[bx],cs ; fixup the segment + add bx,8 ; ready to do the next entry + cmp bx,offset LastCodeEntryPoint + jb pcmode_reinit20 + + mov ax,70h ; now fixup the BIOS A20 Enable + mov es,ax + xor di,di ; patch entry point at 70:0 + mov al,09Ah ; CALLF + stosb + mov ax,offset BIOSA20Enable + stosw ; offset + mov ax,ds + stosw ; seg + mov al,0C3h + stosb ; RET + + cmp ds:codeSeg,0F000h ; have we relocated DOS into the HMA ? + jb pcmode_reinit30 ; if so we must remember it + or cs:patch_version,DOSINHMA +pcmode_reinit30: + retf + + +def_data_vecs rw 0 + dw INT22_OFFSET, DummyIRET + dw INT23_OFFSET, DummyIRET + dw INT24_OFFSET, Int24Entry + dw INT28_OFFSET, DummyIRET + + dw INT20_OFFSET, Int20Entry + dw INT21_OFFSET, Int21Entry + dw INT25_OFFSET, Int25Entry + dw INT26_OFFSET, Int26Entry + dw INT27_OFFSET, Int27Entry + dw INT2F_OFFSET, Int2FEntry + dw INT30_OFFSET+1,Call5Entry + + +no_def_data_vecs equ (offset $ - offset def_data_vecs)/4 + + +end + diff --git a/IBMDOS/HISTORY.A86 b/IBMDOS/HISTORY.A86 new file mode 100644 index 0000000..fa1c91f --- /dev/null +++ b/IBMDOS/HISTORY.A86 @@ -0,0 +1,541 @@ +; File : $HISTORY.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; ENDLOG +; +; DOSPLUS Command Line Editor Routines +; + + include pcmode.equ + include i:msdos.equ + include i:char.def + include i:cmdline.equ + + + +PCM_HISTORY CSEG + + public init_history, save_history + public del_history_buffers, del_cur_history_buffer + public prev_cmd, next_cmd, match_cmd, search_cmd + public prev_word, next_word, match_word + public goto_eol + public del_bol + public deln_word + + extrn next_char:near + extrn save_line:near + extrn space_out:near + extrn bs_out:near + extrn goto_bol:near + extrn del_eol:near + extrn del_line:near + extrn char_info:near + extrn put_string:near + extrn prev_w20:near + extrn deln_w10:near + +init_history: +;------------ +; On Entry: +; SS:BP -> history structure +; On Exit: +; SS:SP filled in with appropriate history buffer +; Preserve DX +; + push ds + push es + push ss + pop es + lea di,RL_HIST_SEG ; point at history buffer variables + mov si,offset histbuf1 ; assume root buffer + test RL_FLAGS,RLF_INROOT ; root task after all? + jnz init_history10 ; if not we need to switch + mov si,offset histbuf2 ; application buffer +init_history10: + movsw ; copy the seg + lodsw ; get overall length + sub ax,2*WORD ; last two words contain pointers + stosw ; save the working length + xchg ax,si ; SI -> saved buffer positions + mov ds,RL_HIST_SEG ; in the buffer segment + movsw ; update save and + movsw ; recall positions + pop es + pop ds + ret + + +save_history: +;------------ +; We are exiting from READLINE - if line has been modified save the +; current line and update our pointers. +; + test dx,dx ; skip update of sav/recall pointers + jz save_history30 ; if empty line + call save_current ; save away current command line + mov di,RL_HIST_SAVE ; start with the old one + call find_current_hist ; wrap it if we need to + call find_next_null ; find end of "new" command + inc di ; onto next character + cmp di,RL_HIST_SIZE ; do we need to wrap ? + jb save_history10 + xor di,di ; wrap the line +save_history10: + mov RL_HIST_SAVE,di ; update "save" pointer + test RL_FLAGS,RLF_DIRTY ; if a line has been changed we'd + jz save_history30 ; better update "recall" pointer + mov RL_HIST_RECL,di ; too +save_history30: + push ds + push es + push ss ! pop ds + lea si,RL_HIST_SAVE ; point at history buffer variables + mov es,RL_HIST_SEG + mov di,RL_HIST_SIZE + movsw ; save the "save" pointer + movsw ; and the "recall" one + pop es + pop ds + ret + +save_current_if_dirty: +;--------------------- + test RL_FLAGS,RLF_DIRTY ; if data is dirty (ie. user modified) + jz save_current20 ; then save it +save_current: +;------------ +; Copy current buffer contents to next free location in history buffer +; + push si + push di + push dx + cmp dx,RL_HIST_SIZE ; is history buffer big enough ? + jae save_current10 ; no, skip saving this line + call find_free_hist ; Find the next bit of space + pop cx ! push cx ; CX = chars to save + jcxz save_current10 ; none, forget about it + push ds + push es + lds si,RL_BUFPTR + mov es,RL_HIST_SEG + rep movsb ; and save the data. + xor ax,ax ; Null terminate it. + stosb + pop es + pop ds + push di + call find_next_null ; Find the end of the entry we just + mov cx,di ; overwrote - if any remains zap it + pop di + cld + xor ax,ax ; Null terminate this entry + sub cx,di ; Figure out number of zeros to write + jbe save_current10 + push es + mov es,RL_HIST_SEG + rep stosb ; and pad to the next entry + pop es +save_current10: + pop dx + pop di + pop si +save_current20: + ret + + +; +; Here is the code to deal with history buffers +; +; match_cmd Does a string search based on what the user has typed so far +; search_cmd Matches string, but doesn't change match state +; prev_cmd Retrieves the previous command from the history buffer +; next_cmd " " next " " " " " +; +match_cmd: + mov al,@hist_flg ; is matching enabled ? + and ax,RLF_MATCH + jz search_cmd ; no, always match + xor RL_FLAGS,ax ; toggle match bit + test RL_FLAGS,ax ; turning matching off ? + jz match30 ; then just exit +search_cmd: + mov RL_SAVPOS,si ; any chars to save ? + test si,si + jz prev_cmd ; blank line - just get previous + call save_current_if_dirty ; save current line if it needs saving + push si ; save current offset in line + push di + push dx ; Save index to end of current line + mov dx,si ; discard rest of line if no match + mov di,RL_HIST_RECL ; Point to the current entry +match_loop: + call find_prev_hist ; DI-> previous cmd in buffer + push di ; save this command position + mov di,RL_HIST_RECL ; get starting position + call find_current_hist ; handle any wrapping + pop si ; recover previous command + cmp di,si ; have we been all round ? + je match_error ; YES - We've looped so no match found + push ds + push si ; save this entry + mov ds,RL_HIST_SEG + mov di,RL_BUFOFF ; ES:DI -> match string + mov cx,RL_SAVPOS ; try to match CX characters + repe cmpsb + pop di ; recover this entry + pop ds + jne match_loop ; try again if we didn't match + call copy_from_hist ; if it did match copy it +match_error: + pop cx ; Get end of displayed line + pop di ; user's buffer + pop si + push si ; save current position in lines + call space_out ; Rub the displayed line out + call bs_out ; And backspace to it's start + call goto_eol ; display the line + call goto_bol ; Move cursor to begining + pop cx ; CX = end of matched portion + mov RL_SAVPOS,cx ; CX = Current position in command + jcxz match20 +match10: ; Move cursor forward to current + push cx ; position + call next_char ; next_char destroys our loop count + pop cx ; so keep it + loop match10 +match20: + mov cx,RL_SAVMAX ; we can't copy any more + mov RL_SAVPOS,cx +match30: + ret + + +prev_cmd: +; Get the previous command from the buffer + test RL_FLAGS,RLF_RECALLED ; is this the 1st recall ? + jnz prev_cmd10 + push cx + push di + mov di,RL_HIST_SAVE ; get existing "save" ptr + call find_current_hist ; wrap it if we need to + mov RL_HIST_RECL,di ; and update "recall" pointer + pop di + pop cx +prev_cmd10: + call save_current_if_dirty ; save current line if it needs saving + call del_line ; then delete it + push si + push di + mov di,RL_HIST_RECL ; point to the current entry + call find_prev_hist ; DI -> previous entry + jmps found_cmd ; now go and copy it to the user buffer + +next_cmd: +; Get the next command from the buffer + call save_current_if_dirty ; save current line if it needs saving + call del_line ; then delete it + push si + push di + mov di,RL_HIST_RECL ; point to the current entry + call find_next_hist ; DI -> next entry +; jmps found_cmd ; now go and copy it to the user buffer + +found_cmd: + call copy_from_hist ; Copy from history to user buffer + pop di + pop si +; jmp goto_eol ; Display new line. + +goto_eol: ; Move the cursor to the end of the + mov cx,dx ! sub cx,si ; displayed line + jcxz goto_e10 ; Already at the EOL + add si,RL_BUFOFF ; Get the Offset in the buffer + call put_string ; Output the sub_string + add di,cx ; Update the local variables + mov si,dx ; and return +goto_e10: + ret + +; DI-> Current entry in history buffer +; +copy_from_hist: + or RL_FLAGS,RLF_RECALLED ; remember we have recalled something + and RL_FLAGS,not RLF_DIRTY ; this entry is already in buffers + mov RL_HIST_RECL,di ; update pointer for next time + call find_next_null ; how big is this entry ? + mov cx,di + mov si,RL_HIST_RECL + sub cx,si ; (CX-SI)=No of bytes to copy + cmp cx,RL_MAXLEN ; is the line bigger than our buffer ? + jb copy_from_hist1 ; if so we want to clip it + mov cx,RL_MAXLEN ; to the maximum possible value +copy_from_hist1: + mov dx,cx + push ds + mov ds,RL_HIST_SEG + mov di,RL_BUFOFF + rep movsb ; copy to line buffer + pop ds + call save_line ; save the line + mov cx,RL_SAVMAX ; we can't copy any more + mov RL_SAVPOS,cx + ret + +; Some primitives for history buffer handling: +; +; find_free_hist Find the next free entry in the history buffer +; find_next_null Finds the end of the current entry +; find_prev_hist Finds the start of the previous entry +; find_next_hist Finds the start of the next entry +; find_current_hist Finds the start of current entry + +; +; Make DI-> next entry of sufficient length for the current cmd buffer +; If we can't fit at the end zero the remainder of the buffer then wrap +; back to the start. +; + +find_free_hist: + mov di,RL_HIST_SAVE ; Point at current last entry + push di ; Will DX bytes fit? + add di,dx + cmp di,RL_HIST_SIZE ; Did we run out of buffer? + pop di + jb find_free_hist20 + xor ax,ax ; doesn't fit, so zero to end of buffer +find_free_hist10: + push es + mov es,RL_HIST_SEG + stosb ; keep on zeroing + pop es + cmp di,RL_HIST_SIZE + jb find_free_hist10 + xor di,di ; wrap back to start of history buffer +find_free_hist20: + ret + +; Entry DI-> entry in the history buffer +; Make DI-> next NULL in the history buffer ( end of current entry ) +; +find_next_null: + mov cx,RL_HIST_SIZE + sub cx,di ; Calc no of bytes left + xor ax,ax ; Look for next terminator + push es + mov es,RL_HIST_SEG + repnz scasb + dec di ; point at the NUL + pop es + ret + +; Entry DI-> entry in the history buffer +; Make DI-> previous entry in the history buffer +; Preserve CX +find_prev_hist: + call find_current_hist ; handle any wrapping + mov ax,di ; AX = entry we want previous for +find_prev_hist10: + push ax ; save current offset + push di ; save initial offset + xchg ax,di ; find next from here until + call find_next_hist ; we get back where we started + xchg ax,di ; AX = current offset + pop di ; recover initial value + pop bx ; recover previous offset + cmp ax,di ; have we wrapped yet ? + je find_prev_hist20 ; yes, BX = previous entry + ja find_prev_hist10 ; we are above target so continue + cmp bx,di ; we are below target - if previous + jae find_prev_hist10 ; was above target we are OK + cmp ax,bx ; if new below previous then we + jnb find_prev_hist10 ; have ERROR wrap, so stop +find_prev_hist20: + mov di,bx ; DI -> Previous entry + ret + +find_next_hist: + call find_current_hist ; handle any wrapping + call find_next_null ; point to end of current entry +; jmp find_current_hist ; handle any wrapping + +find_current_hist: +; This routine is complicated by the need to handle switchers, where +; our buffers and pointers may get out of step + push es + xor ax,ax + mov es,RL_HIST_SEG ; now work backwards to start of line +find_current_hist10: + cmp di,1 ; are we at the start of the buffer + jb find_current_hist30 ; then don't wrap + std + scasb ; is previous char a NUL ? + cld ; (it should be!) + jne find_current_hist10 + inc di ; ES:DI -> 1st char of line +find_current_hist20: + mov cx,RL_HIST_SIZE + sub cx,di ; CX= Remaining no: of bytes in buffer + jbe find_current_hist30 + repe scasb ; skip over zero's + jne find_current_hist40 +find_current_hist30: + mov di,1 ; wrap to start of buffer +find_current_hist40: + dec di + pop es + ret + +del_history_buffers: +;------------------- +; Delete contents of both history buffers +; + mov ax,histbuf1 ; Segment of 1st history buffer + mov cx,histsiz1 ; End of 1st history buffer + call zap_buffer + mov ax,histbuf2 ; Segment of 2nd history buffer + mov cx,histsiz2 ; End of 2nd history buffer + jmps zap_buffer + +del_cur_history_buffer: +;---------------------- +; Delete contents of the current history buffer +; + mov ax,RL_HIST_SEG ; zero the current buffer + mov cx,RL_HIST_SIZE +zap_buffer: + push es ; zero fill CX bytes at AX:0 + push di + mov es,ax + xor ax,ax + mov RL_HIST_RECL,ax + mov RL_HIST_SAVE,ax + xor di,di + rep stosb ; zero fill the buffer + pop di + pop es + call del_line ; then delete current line + jmp save_line + + +next_word: + mov cx,dx ; Calculate the number of bytes + sub cx,si ; left to scan + jcxz next_w10 ; Skip if at the EOL + push si ; Save the current Index + mov si,di ; Scan from the current location + call match_word ; Get the next word boundary + mov cx,si + sub cx,di ; Calculate the string length + mov si,di ; to be displayed from the current + call put_string ; location and output the data + pop si + add si,cx ; Update the Index and Offset pointers + add di,cx +next_w10: + ret + +; +; MATCH_WORD scans the buffer at ES:SI for word boundaries +; and returns to the calling routine whenever it detects such +; a boundary. +; +; On Entry: ES:SI Buffer Address +; CX Maximum No of bytes to Scan +; +; On Exit: ES:SI Next Word Boundary +; +match_word: + call char_info + test ah,CHAR_ALPHAN or CHAR_KANJI + loopnz match_word ; scan the rest of the current word + jcxz match_w30 ; end of word or kanji ? + + push dx +match_w10: + mov dx,si + call char_info + test ah,CHAR_ALPHAN or CHAR_KANJI + loopz match_w10 + jz match_w20 + sub si,dx ; Correct the count in CX + add cx,si ; and return the location of the + mov si,dx ; word boundary + +match_w20: + pop dx +match_w30: + ret + +prev_word: + mov cx,si ! jcxz match_w30 ; Initialize the count + push dx ! push si ! push di + mov si,RL_BUFOFF ; Scan from the begining of the buffer + mov dx,si ; keeping the last match in DX +prev_w10: + call match_word ; Find the next word boundary + jcxz prev_w15 ; Stop when we get to the current offset + mov dx,si ; Save current location + jmps prev_w10 ; and repeat +prev_w15: + jmp prev_w20 + +del_bol: ; Delete to the begining of the line + or si,si ! jz del_bol10 ; Ignore if at the begining + or dx,dx ! jz del_bol10 ; Or the line is empty + push di ; Save the current index + call goto_bol ; Move to the start of the line + pop cx ; Restore the current offset + jmp deln_w10 ; and jump to common code +del_bol10: + ret + +deln_word: + mov cx,dx ; Calculate the number of bytes + sub cx,si ; left to scan + jcxz del_bol10 ; Skip if at the EOL + push si ; Save the current Index + mov si,di ; Scan from the current location + call match_word ; Get the next word boundary + mov cx,si + pop si + jmp deln_w10 + +PCMODE_DATA DSEG WORD + + extrn @hist_flg:byte ; To select between histbufs 1 or 2 + +GLOBAL_DATA dseg word + + extrn histbuf1:word, histsiz1:word, histbuf2:word, histsiz2:word + + end + diff --git a/IBMDOS/IBMDOS.INP b/IBMDOS/IBMDOS.INP new file mode 100644 index 0000000..7e6ab48 --- /dev/null +++ b/IBMDOS/IBMDOS.INP @@ -0,0 +1,5 @@ +ibmdos.tmp=header.obj,pcmif.obj,cio.obj,disk.obj,ioctl.obj,misc.obj,support.obj, +dosmem.obj,error.obj,process.obj,network.obj,int2f.obj,fdos.obj,cdevio.obj,fioctl.obj, +fcbs.obj,redir.obj,dirs.obj,buffers.obj,bdevio.obj,cmdline.obj,history.obj +[map, data[origin[0000]]] + \ No newline at end of file diff --git a/IBMDOS/IBMDOS.MAP b/IBMDOS/IBMDOS.MAP new file mode 100644 index 0000000..3c4e85e --- /dev/null +++ b/IBMDOS/IBMDOS.MAP @@ -0,0 +1,154 @@ +Map for file: IBMDOS.TMP + +Segments +-------- + +Length Start Stop Align Comb Name Class + +3830 (0000:0000-382F) PARA PUB PCM_HEADER CODE +2C03 (0000:3830-6432) BYTE PUB PCM_CODE CODE +3ADE (0000:6434-9F11) WORD PUB BDOS_CODE CODE +02CC (0000:9F12-A1DD) WORD PUB PCM_RODATA CODE +0399 (0000:A1DE-A576) BYTE PUB PCM_HISTORY CODE +01B5 (0000:A577-A72B) BYTE PUB PCM_ICODE CODE +0000 PARA PUB PCM_CODEND CODE +0000 BYTE PUB CODE CODE +03A2 (0000:0000-03A1) WORD PUB PCMODE_DATA DATA +000E (0000:03A2-03AF) WORD COM FDOS_DSEG DATA +0C50 (0000:03B0-0FFF) WORD PUB FIXED_DOS_DATA DATA +02B8 (0000:1000-12B7) WORD PUB PCMODE_CODE DATA +0014 (0000:12B8-12CB) WORD PUB GLOBAL_DATA DATA +0120 (0000:12CC-13EB) WORD PUB BDOS_DATA DATA +0000 PARA PUB PCMODE_DSIZE DATA + +Groups Segments +------ -------- + +PCMDATA PCMODE_DATA FDOS_DSEG FIXED_DOS_DATA PCMODE_CODE + GLOBAL_DATA BDOS_DATA PCMODE_DSIZE +PCMCODE PCM_HEADER PCM_CODE BDOS_CODE PCM_RODATA + PCM_HISTORY PCM_ICODE PCM_CODEND + +map for module: HEADER + +382A (0000:0000-3829) PCM_HEADER +0102 (0000:A1DE-A2DF) PCM_HISTORY +01B5 (0000:A577-A72B) PCM_ICODE +03A2 (0000:0000-03A1) PCMODE_DATA +000E (0000:03A2-03AF) FDOS_DSEG +0C50 (0000:03B0-0FFF) FIXED_DOS_DATA +02B8 (0000:1000-12B7) PCMODE_CODE +0004 (0000:12CC-12CF) BDOS_DATA + +map for module: PCMIF + +03F6 (0000:3830-3C25) PCM_CODE +00DC (0000:9F12-9FED) PCM_RODATA +000E (0000:03A2-03AF) FDOS_DSEG + +map for module: CIO + +0491 (0000:3C26-40B6) PCM_CODE +0004 (0000:9FEE-9FF1) PCM_RODATA +000E (0000:03A2-03AF) FDOS_DSEG +0001 (0000:12B8-12B8) GLOBAL_DATA + +map for module: DISK + +044C (0000:40B7-4502) PCM_CODE +000E (0000:03A2-03AF) FDOS_DSEG +0002 (0000:12BA-12BB) GLOBAL_DATA + +map for module: IOCTL + +0164 (0000:4503-4666) PCM_CODE +0032 (0000:9FF2-A023) PCM_RODATA +000E (0000:03A2-03AF) FDOS_DSEG + +map for module: MISC + +0687 (0000:4667-4CED) PCM_CODE +004D (0000:A024-A070) PCM_RODATA +000E (0000:03A2-03AF) FDOS_DSEG +0002 (0000:12BC-12BD) GLOBAL_DATA + +map for module: SUPPORT + +00C7 (0000:4CEE-4DB4) PCM_CODE +000E (0000:03A2-03AF) FDOS_DSEG + +map for module: DOSMEM + +0260 (0000:4DB5-5014) PCM_CODE +000E (0000:03A2-03AF) FDOS_DSEG + +map for module: ERROR + +01AE (0000:5015-51C2) PCM_CODE +00B4 (0000:A072-A125) PCM_RODATA +000E (0000:03A2-03AF) FDOS_DSEG + +map for module: PROCESS + +07B2 (0000:51C3-5974) PCM_CODE +000E (0000:03A2-03AF) FDOS_DSEG + +map for module: NETWORK + +0086 (0000:5975-59FA) PCM_CODE +000E (0000:03A2-03AF) FDOS_DSEG + +map for module: INT2F + +04EB (0000:59FB-5EE5) PCM_CODE +000E (0000:03A2-03AF) FDOS_DSEG +000E (0000:12BE-12CB) GLOBAL_DATA + +map for module: FDOS + +199A (0000:6434-7DCD) BDOS_CODE +0078 (0000:12D0-1347) BDOS_DATA + +map for module: CDEVIO + +02B7 (0000:7DCE-8084) BDOS_CODE + +map for module: FIOCTL + +0238 (0000:8085-82BC) BDOS_CODE + +map for module: FCBS + +0558 (0000:82BD-8814) BDOS_CODE + +map for module: REDIR + +06CB (0000:8815-8EDF) BDOS_CODE + +map for module: DIRS + +03EE (0000:8EE0-92CD) BDOS_CODE +0037 (0000:1348-137E) BDOS_DATA + +map for module: BUFFERS + +052C (0000:92CE-97F9) BDOS_CODE +0005 (0000:1380-1384) BDOS_DATA + +map for module: BDEVIO + +0717 (0000:97FA-9F10) BDOS_CODE +0065 (0000:1386-13EA) BDOS_DATA + +map for module: CMDLINE + +054D (0000:5EE6-6432) PCM_CODE +00B7 (0000:A126-A1DC) PCM_RODATA +000E (0000:03A2-03AF) FDOS_DSEG + +map for module: HISTORY + +0297 (0000:A2E0-A576) PCM_HISTORY +000E (0000:03A2-03AF) FDOS_DSEG + + \ No newline at end of file diff --git a/IBMDOS/IBMDOS.SYM b/IBMDOS/IBMDOS.SYM new file mode 100644 index 0000000..5a9daae --- /dev/null +++ b/IBMDOS/IBMDOS.SYM @@ -0,0 +1,179 @@ + +0000 VARIABLES 0000 DATA +03A2 FDOS_DSEG +0000 VARIABLES 0000 DATA +13F0 DATA_END 12CC HASHROOT +0000 LABELS 0000 CODE +3800 CODE_START 380A OS_VERSION 3822 PATCH_VERSION +3806 PCMODE_DSEG A730 CODE_END +0000 VARIABLES 0000 DATA +0FE4 ACTIVE_CNT 056D FILE_ATTRIB 0572 REMOTE_CALL +043E SEC_PATHNAME 0EFE FDOS_STUB 0EE0 HASHMAX 057E TERM_PSP +03B6 BIOSDATE 0D1C DAYS_IN_MONTH 0588 CRITICAL_SP +0AA2 RWMODE 0F02 SHARE_STUB 0AA0 INDOS_STACK 03B8 MINUTE +0AAD UCASETBL 0EBC @PRIVATE_DATA 05CE CURRENT_FILEPOS +0584 INT21REGS_PTR 05F0 PREV_INT21REGS_OFF 0AA4 INT2F_CMD +0FE4 IDLE_DATA 0AAC SWAP_INDOS 03BE PRI_PATHNAME +05F2 PREV_INT21REGS_SEG 0ECC HMAROOT 0580 INT24_ESBP 0FEA IDLE_VEC +057C EXIT_TYPE 0620 FCB_SEARCH_BUF 0CE3 DBCS_TBL 054B NAME_BUF +0AA3 IOEXERR 0920 NORMAL_STACK 07A0 ERROR_STACK +05AA CURRENT_IFN 043E LOAD_FILE 058A CURRENT_DDSC +0FEE INT28_DELAY 0FE6 IDLE_MAX 0AA8 FILE_MODE 03B0 MUSTBE03B0 +05A2 CURRENT_LDT 03BA HUNDREDTH 0FE8 IDLE_FLAGS +0FF0 INT28_RELOAD 0D12 DOS_VERSION +059E CURRENT_DHNDL 04BE SRCH_BUF 0ED6 LOCALMACHINEID +0EC4 @HIST_FLG 05F0 PREV_INT21REGS_PTR 03BE RELOC_BUF +059A CURRENT_DEVICE 0BB1 FILECHARSTBL +0B2F FILEUCASETBL 0AAA CLE_STATE 0AA1 ERR_DRV +0F3E WINDOWSHANDLECHECK 0AA6 INT2F_STACK +0584 INT21REGS_OFF 04F3 TEMP_LDT 0ED8 DMD_ADDRESS +0ECA CODESEG 0FC8 EXE_BUFFER 03BB SECOND 0586 INT21REGS_SEG +03B9 HOUR 0ED2 DMD_OWNER 0BE1 COLLATINGTBL +0374 EXE_LOADHIGH 0048 DEV_ROOT 0320 ERROR_FLAG +032E DMA_SEGMENT 0324 ERROR_CODE 0303 SHARING_FLAG +0010 FCB_LRU_COUNT 03A1 CHAR_COUNT 0351 MONTH 034A LOCUS +0334 RETCODE 01FB SAVBUF 0352 YEARSSINCE1980 0328 ERROR_DEV +0392 FCB_PATH2 0335 SYSTEM_RETCODE 0026 FUNC52_DATA +0089 DMD_UPPER_LINK 0358 INT28_FLAG 0300 COLUMN +02FF VERIFY_FLAG 0301 SWITCH_CHAR 005D SETVERPTR +0046 PHYS_DRV 034C RETRY_OFF 000E NETBIOS 0359 IOCTLRH +0357 INTERNAL_FLAG 0320 INTERNAL_DATA 0383 FCB_PATH +034E RETRY_SP 0304 NET_SET_COUNT 001A NET_RETRY 0337 BREAK_FLAG +0356 DAYOFWEEK 0327 ERROR_CLASS 0069 BOOTDRV 0040 FCB_PTR +033E MACHINE_ID 0342 LOAD_IMAGE 0372 LOAD_ENVSIZE +0322 ERROR_DRIVE 008C DMD_UPPER_ROOT 033C OWNING_PSP +0336 CURRENT_DSK 0334 USER_RETCODE 0346 LOAD_MAX +033A INT21AX 0332 BREAK_SP 0326 ERROR_ACTION 0305 NET_NAME +0370 LOAD_ENV 034B VALID_FLG 027B FDOS_BUF 002E CLK_DEVICE +0036 SECTOR_SIZE 001E BCB_ROOT 0348 LOAD_HANDLE +033A SWAP_ALWAYS 0323 ERROR_LOCUS 0032 CON_DEVICE +000F NAME_NUM 0302 MEM_STRATEGY 0344 LOAD_TOP 0340 LOAD_PSP +007C DEBLOCK_SEG 0026 DDSC_PTR 0354 DAYSSINCE1980 +0330 CURRENT_PSP 002A FILE_PTR 001C NET_DELAY 0321 INDOS_FLAG +032C DMA_OFFSET 0024 DMD_ROOT 0350 DAYOFMONTH 003C LDT_PTR 02FE CIO_STATE +005A JOIN_DRV 0375 FCB_PB 0048 NUL_DEVICE 0047 LAST_DRV 1010 EXEC_STUB +1008 LOCK_TABLES 113E HISTBUF1 1144 HISTBUF2 +1129 CRITICALSECTIONENABLE 112A SWSTARTUPINFO +10E5 INT2FBIOSHANDLER 12A8 INTL_XLAT 1192 XLAT_XLAT 1000 MUSTBE1000 +1232 COUNTRY_FILENAME 1296 DEFAULT_COUNTRY +1004 UNLOCK_BIOS 1000 ENDOFINSTANCEDATA 1294 CUR_CP +1140 HISTSIZ1 1146 HISTSIZ2 10E9 INT2FNEXT 1102 INVALID_STUB +1014 FUNC4B05_STUB 100C UNLOCK_TABLES +1292 COUNTRY_DATA 1000 LOCK_BIOS 1292 CUR_COUNTRY +11A0 NOYESCHARS +0000 NUMBERS +0D90 LAST_KEY_EXT 001C INFO1_LEN 0082 INFO2_LEN 0082 INFO4_LEN +0018 INFO5_LEN 0102 INFO6_LEN 0012 INFO7_LEN 0008 RELOC_CNT +0000 LABELS 0000 CODE +3830 CALL5_ENTRY 3B29 DO_INT24 3A65 INT25_ENTRY +3A61 INT26_ENTRY 3B18 INT27_ENTRY +3BFD INVALID_FUNCTION 3C03 RELOAD_REGISTERS 3987 INACTIVE +39B3 DOS_ENTRY 3A36 INT21_FUNC 3BE9 GET_DSEG 3936 INT21_EXIT 39A7 ACTIVE +384F INT20_ENTRY 3851 INT21_ENTRY 9F12 PCMODE_FT +0000 NUMBERS +006D PCMODE_FTL +0000 LABELS 0000 CODE +3C26 FUNC01 3C2A FUNC02 3C37 FUNC03 3C3D FUNC04 3C42 FUNC05 +3C6C FUNC06 3C7F FUNC07 3C87 FUNC08 3CA3 FUNC09 +3F10 DEVICE_WRITE 3CB7 FUNC0A 3CC0 FUNC0B +3E00 COOKED_WRITE 3CCE FUNC0C 3CFD BREAK_CHECK +3DD0 RAW_READ 3F0C DEVICE_READ 3DC1 CMDLINE_READ +40DF VALID_DRIVE 4104 FUNC10 4104 FUNC11 4104 FUNC21 +4104 FUNC12 4236 FUNC40 4104 FUNC22 4104 FUNC13 41DA FUNC41 +4167 FUNC32 4104 FUNC23 4104 FUNC14 43EA FUNC60 426B FUNC42 +4104 FUNC24 4104 FUNC15 4295 FUNC43 4104 FUNC16 42FE FUNC53 +4104 FUNC17 42BD FUNC45 4174 FUNC36 4104 FUNC27 42B2 FUNC46 +412C FUNC19 4104 FUNC28 4317 FUNC56 42EB FUNC47 4340 FUNC57 +41E4 FUNC39 4409 FUNC67 4482 FUNC68 4130 FUNC1A 4139 FUNC1B +41E4 FUNC3A 4139 FUNC1C 40B7 FUNC0D 41E4 FUNC3B 40CD FUNC0E +4373 FUNC5A 41F6 FUNC3C 4104 FUNC0F 420E FUNC3D 41F6 FUNC5B +4167 FUNC1F 42CD FUNC5C 42BD FUNC3E 41C9 FUNC2F 448E FUNC6C +4236 FUNC3F 41E4 FUNC4E 41E4 FUNC4F +451B FUNC44 4503 FUNC69 +47B4 FUNC30 47C9 FUNC33 4800 FUNC25 4678 FUNC52 4667 FUNC34 +4816 FUNC35 483C FUNC63 4838 FUNC54 4797 FUNC37 4B89 FUNC65 +4AA8 FUNC38 4873 FUNC29 4C77 FUNC66 495A FUNC2A 4980 FUNC2B +496D FUNC2C 4999 FUNC2D 4832 FUNC2E 467D FUNC5D +466A RETURN_DSBX_AS_ESBX 49BC READTIMEANDDATE +4D59 FCBFDOS_CRIT 4D3D RETURN_AX_CLC +4D01 SET_RETRY_RF 4CEE STRLEN 4D8E RETURN_BX 4D9B RETURN_CX +4D6F FDOS_NOCRIT 4DA8 RETURN_DX 4D03 SET_RETRY 4D82 RELOAD_ES +4D33 FDOS_AX_CRIT 4D28 FDOS_CRIT +4EED SET_OWNER 4DB5 FUNC48 4E4F FUNC58 4DE2 FUNC49 4EB7 FREE_ALL +4E1E FUNC4A 5004 CHECK_DMD_ID +5062 CHAR_ERROR 504A ERROR_RET 5015 FUNC59 503D ERROR_EXIT +505A FCBERROR_EXIT +54D3 FUNC00 52B0 FUNC31 52A3 FUNC50 52A8 FUNC51 52A8 FUNC62 +51EF FUNC26 51C3 FUNC55 5928 CHECK_EXE 52DE FUNC4B 54F1 FUNC4C +55A4 FUNC4D 5936 IMAGE_SIZE +59E2 FUNC5F_COMMON 5975 FUNC5E 59B1 FUNC5F +5A52 INT2F_ENTRY +0000 VARIABLES 0000 DATA +132C GLOBAL_PASSWORD 12D6 FDOS_HDS_ROOT 12E6 INFO_FCB +131C FDOS_PB 12D4 FDOS_HDS_BLK 12D8 FDOS_HDS_DRV +132A FDOS_RET 1316 FDOS_INFO +0000 LABELS 0000 CODE +7DB4 SHARE_DELAY 6E07 FDOS_MKDDSC +6B82 FDOS_GETDPB 682B FDOS_CLOSE 6FB5 FDOS_MOVE +6D61 FILE_UPDATE 6552 FDOS_MKDIR 7CD9 READTOD +7B7F LDS_SI_DMAPTR 65B4 FDOS_RMDIR 6CA6 FDOS_NEXT +6EFD FDOS_EXPAND 6BEA FDOS_SELECT +7A9F DISCARD_FILES 7A70 RELEASE_HANDLE 6DB9 FDOS_MKNEW +6BB8 FDOS_FLUSH 7108 FDOS_DATTIM 71B2 DBCS_LEAD +79EE VFY_DHNDL_PTR 6C7D FDOS_FIRST 6D53 FDOS_COMMIT +6B34 FDOS_CURDIR 7C77 MV_JOIN_ROOT 6514 FDOS_ERROR +68B5 FDOS_WRITE 6A25 FDOS_ED_FUNCTION 74F0 GET_PB2_DRIVE +68EE FDOS_UNLINK 7B8B COPY_ASCIIZ 6434 FDOS_ENTRY +7607 UNPARSE 79AB VERIFY_HANDLE 7B7A CURRENT_DSK2AL +6E18 BPB2DDSC 654D FDOS_ED_ACCESS 7B60 GET_XFTPTR 685E FDOS_READ +77B8 CHECK_DELIM 7AF0 FIND_DHNDL 6E9C FDOS_DDIO 78C6 FIND_XFN +7B92 CHECK_JOIN 720B REBUILD_LDT_ROOT 653E FDOS_ED_DRIVE +7D6B HASH_PWD 77FD TOUPPER 6C1D FDOS_EXEC 652D FDOS_RESTART +78DF ALLOC_DHNDL 6DDD FDOS_LOCK 6AEA FDOS_DUP 65FA FDOS_CHDIR +64BD LOCAL_DISK 78ED ALLOC_XFN 69BB FDOS_CHMOD 7B85 LES_DI_DMAPTR +77F5 CHECK_SLASH 75F7 HDSBLK 7AC7 IFN2DHNDL 6AF9 FDOS_FDUP +673D FDOS_CREAT 65DF UPDATE_DIR_FAT 77EC CHECK_DSLASH +7791 PARSE_ONE 7133 TIMESTAMP_DHNDL 67C2 FDOS_OPEN 6960 FDOS_LSEEK +8019 FIRST_DEV 7E81 WRITE_DEV 804C IOC6_DEV 8050 IOC7_DEV 7EB6 READ_DEV +7E67 DUP_DEV 7DCE OPEN_DEV 7E75 CLOSE_DEV +80A9 FDOS_IOCTL +82BD FDOS_EXIT 8301 FDOS_FCB +8957 ISLOCAL 8815 REDIR_DHNDL_OFFER 8D5B REDIR_BUILD_PATH +8891 REDIR_DRV_OFFER 8845 REDIR_MOVE_OFFER 8904 GET_LDT +883F REDIR_ASCIIZ_DEV_OFFER 887C REDIR_ASCIIZ_FILE_OFFER +8877 REDIR_ASCIIZ_OFFER 8919 GET_LDT_RAW +88A7 REDIR_SNEXT_OFFER +0000 VARIABLES 0000 DATA +137D CHDBLK 1379 DCNT 1377 DIRP 137B FINDDFCB_MASK +1357 DIRBUF +0000 LABELS 0000 CODE +8EE0 FILL_DIRBUF 928A ALLOCDIR 9259 HSHDSCRD +8F9B DISCARD_DIRBUF 8F3A FLUSH_DIRBUF 9005 SETENDDIR +917E FIXUP_HASHING 9022 FINDDFCB 901F FINDDFCBF 915A MKHSH +9025 GETDIR +960B UPDATE_DIR 92CE UPDATE_DDSC_FREE 946C FIXFAT +9414 ALLOCATE_CLUSTER 936C GETNBLK 9334 BUFFERS_CHECK +9595 LOCATE_BUFFER 9523 FATPTR 946A CHANGE_FAT_ENTRY +96D3 ZEROBLK 961B FLUSH_DRIVE 92FB DISCARD_DIRTY +93A7 ALLOC_CLUSTER 93AA ALLOC_CHAIN 9351 DELFAT +92FF DISCARD_ALL 9303 DISCARD_DIR 9382 GETBLK +9612 UPDATE_DAT 9616 UPDATE_FAT +0000 VARIABLES 0000 DATA +13A5 DOSFAT 1395 LASTCL 1388 LOGICAL_DRV 139F CLSIZE +13B4 FDRWFLG 139D NFATRECS 13B0 CUR_DMA_SEG 13AE CUR_DMA +138A PSECSIZ 1393 DATADD 138E FATADD 13CD REQ_HDR 13A1 SECPERCLU +1399 DIRADD 1389 PHYSICAL_DRV 13A3 DIRPERCLU 1391 DIRINROOT +1386 HDSADDR 13A8 PBLOCK 13A7 ADRIVE 13AC MULT_SEC 139B NFATS +0000 LABELS 0000 CODE +9EF3 CLUS2SEC 9CE1 SELECT_PHYSICAL_DRV 9E9E WRITE_BLOCK +9819 FDOSRW 9D06 SELECT_ADRIVE 9C59 DEVICE_DRIVER +97FA GET_DDSC 9C85 SELECT_LOGICAL_DRV 9C38 BLOCK_DEVICE_DRIVER +9EB2 READ_BLOCK 9E79 MARK_LDT_UNSURE 9BF9 DDIOIF 9BD4 BLOCKIF +6389 SPACE_OUT 6136 DEL_EOL 6116 PREV_W20 619F DEL_LINE 5EE6 READ_LINE +6339 CHAR_INFO 638D BS_OUT 6399 PUT_STRING 60C9 GOTO_BOL 62B4 SAVE_LINE +615E DELN_W10 60DD NEXT_CHAR A127 EDIT_SIZE +A303 SAVE_HISTORY A2E0 INIT_HISTORY A51D MATCH_WORD +A4E4 DEL_CUR_HISTORY_BUFFER A554 DEL_BOL A4D1 DEL_HISTORY_BUFFERS +A53C PREV_WORD A502 NEXT_WORD A378 MATCH_CMD A388 SEARCH_CMD A3E1 PREV_CMD +A405 NEXT_CMD A418 GOTO_EOL A565 DELN_WORD + \ No newline at end of file diff --git a/IBMDOS/INT2F.A86 b/IBMDOS/INT2F.A86 new file mode 100644 index 0000000..734f813 --- /dev/null +++ b/IBMDOS/INT2F.A86 @@ -0,0 +1,1245 @@ +; File : $Workfile$ +; +; Description : +; +; Original Author : +; +; Last Edited By : $Author$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; INT2F.A86 1.23 94/11/14 10:34:17 +; Fixed the NWDOS.386 stuff. Still point at startupinfo, but take out the +; vxdname and the vxdnameseg entries. +; INT2F.A86 1.22 94/10/07 09:05:11 +; Added patch 005 as source fix. Removed the stuff to load NWDOS.386 as +; the vxd is no longer needed. +; INT2F.A86 1.21 94/03/24 18:40:10 +; Support para-aligned HMA allocations (Stacker 4 bug) +; INT2F.A86 1.20 93/09/28 19:43:12 +; Extra field to export upper memory root on windows startup +; INT2F.A86 1.19 93/09/06 15:37:35 +; Startup Broadcast fills entry ES:BX into SwStartupInfo "next" link field +; INT2F.A86 1.16 93/08/06 16:35:58 +; Change DELWATCH int 2F hook for getnblk to getblk +; INT2F.A86 1.15 93/07/20 22:47:21 +; Pass on Int 2F/12FF to BIOS - (really to CONFIG) +; INT2F.A86 1.11 93/06/11 02:10:01 +; GateA20 disabled on EXEC for EXEPACKED apps +; ENDLOG +; +; DOS INT 2F Support +; + include pcmode.equ + include i:msdos.equ + include i:mserror.equ + include i:driver.equ + include i:psp.def + include i:doshndl.def + include i:redir.equ + +PCM_CODE CSEG BYTE + + extrn get_dseg:near ; in PCMIF.PCM + extrn do_int24:near ; in PCMIF.PCM + extrn dos_entry:near + extrn strlen:near ; in SUPPORT.PCM + extrn toupper:near ; in UTILS.FDO (in BDOS_CODE) + extrn ReadTOD:near ; in UTILS.FDO (in BDOS_CODE) + extrn share_delay:near ; in UTILS.FDO (in BDOS_CODE) + +eject + +PointHMA: +;-------- +; On Entry: +; None +; On Exit: +; DS = DOS data seg +; BX = bytes available (0 if none) +; ES:DI -> start of available area (FFFF:FFFF if none) +; All other regs preserved +; + call get_dseg ; DS = DOS data + mov di,0FFFFh + mov es,di ; ES:DI = FFFF:FFFF + mov bx,hmaRoot + test bx,bx ; have we an HMA ? + jz PointHMA10 + mov di,bx ; ES:DI = start of HMA free area + mov bx,es:2[bx] ; BX = length + sub bx,4 ; forget the header + and bl,not 15 ; make it complete para's +PointHMA10: + ret + +QueryHMA: +;-------- +; On Entry: +; None +; On Exit: +; BX = bytes available (0 if none) +; ES:DI -> start of available area (FFFF:FFFF if none) +; All other regs preserved +; + push ds + call PointHMA ; registers ready for return + jmps int2F_BIOS ; give CONFIG processing a chance + + +AllocHMA: +;-------- +; On Entry: +; BX = bytes required +; On Exit: +; ES:DI -> start of available area (FFFF:FFFF if none) +; + push ds + xchg ax,bx ; AX = bytes required + add ax,15 + and al,not 15 ; round up to para's + call PointHMA + xchg ax,bx + cmp ax,bx ; enough room up there ? + jae AllocHMA10 + mov di,es ; ES:DI = FFFF:FFFF + jmps AllocHMA20 +AllocHMA10: + add hmaRoot,bx ; set new start + mov ax,es:2[di] ; get length + sub ax,bx ; subtract what we just allocated + mov es:2[di+bx],ax ; set new length + cmp ax,4 ; have we shrunk to zero spare ? + mov ax,es:[di] ; move link field to + mov es:[di+bx],ax ; new head + ja AllocHMA20 + mov hmaRoot,ax ; set new hmaRoot +AllocHMA20: + mov ax,4A02h ; "restore" AX + pop ds + iret + +eject +; ++++++++++++++++++++++++++++ +; Int 2F - Multiplex Interrupt +; ++++++++++++++++++++++++++++ +; +; This interrupt is used by DBASE III Plus +; +; On Entry:- AH - Multi-Plex Number +; 01 - Print Spooler +; 02 - Assign Command (Documented) +; 05 - Critical Error Msg +; 06 - Assign Command (By Inspection) +; 08 - DRIVER.SYS Interface for MS-DOS 3.xx +; 10 - Share Command +; 11 - Internal DOS - Network Hooks +; 12 - Internal DOS - Support Services +; 13 - Original INT 13 ROS ISR Address (BIOS) +; 14 - NLSFUNC utility +; AD - IBM CodePage Screen Driver +; B7 - Append Command +; B8 - Network Command +; +; AL - Function Code +; 00 - Get Installed State (All) +; 01 - Submit File (PRINT) +; 02 - Cancel File (PRINT) +; 03 - Cancel All Files (PRINT) +; 04 - Spooler Status (PRINT) +; 05 - End of Status (PRINT) +; +; The Network Test returns the current Network configuration in +; BX when the Get Installed State is requested. +; +; BX = 0008h Redirector | Increasing +; BX = 0080h Receiver | Network +; BX = 0004h Messenger | Functionality +; BX = 0040h Server V +; + Public int2F_entry + +int2F_entry: + sti + cld + cmp ah,012h ! je i2f_12 ; intercept the AH=12 subfunctions + cmp ah,011h ! je i2f_11 ; intercept the AH=11 subfunctions + cmp ah,010h ! je i2f_10 ; intercept the AH=10 subfunctions + cmp ah,005h ! je i2f_05 ; intercept the AH=05 subfunctions + cmp ax,4A01h! je QueryHMA ; intercept Query Free HMA Space + cmp ax,4A02h! je AllocHMA ; intercept Allocate HMA space + cmp ah,016h ! jne int2F_exit ; intercept the AH=16 subfucntions + jmp WindowsHooks ; go do windows things... +int2F_exit: + push ds ; pass onto BIOS now + call get_dseg ; trying to remain ROMMABLE +int2F_BIOS: + jmpf ds:int2FNext ; hence this complication + + +eject +i2f_05: +;------ +; CRITICAL ERROR MSG +; This is the critical error message interceptor. +; On Entry: AL = extended error code. +; On Exit: if CY clear then ES:DI -> ASCIIZ string to be used in place +; of the default error message + stc ; please use the default message + retf 2 ; IRET, but keep flags + + +eject +i2f_10: +;------ +; SHARE + cmp al,i2f_10size ; do we do this one ? + jae int2F_exit ; no, skip it + shl al,1 ; we need a word offset + jz int2F_exit ; exit if share installation check + cbw ; zero AH + xchg ax,bx ; we will index with it + push ds + call get_dseg ; get PCMode data seg + push ds ! pop es + call i2f_10tbl[bx] ; execute the function + pop ds + retf 2 ; and return + +eject +i2f_11: +;------ +; MSNET redirector + test al,al ; is it installation check ? + jz i2f_11_10 + mov ax,1 ; no, return ED_FUNCTION error + stc ; indicate an error +i2f_11_10: + retf 2 ; return + +eject +i2f_12: +;------ +; DOS Internal +; Support DOS internal functions here + cmp al,0FFh ; should we pass it on to the BIOS ? + je int2F_exit ; yes, do so + cmp al,i2f_12size ; do we do this one ? + jae i2f_12_bad ; no, skip it + push bp + xor ah,ah + add ax,ax ; make sub-func a word + mov bp,ax ; we need offset in pointer register + mov ax,i2f_12tbl[bp] ; get address of service routine + mov bp,sp ; BP points to stack frame + call ax ; call the service routine + pop bp +i2f_12_exit: + retf 2 ; IRET, but returning flags +i2f_12_bad: + mov ax,-ED_FUNCTION + stc + retf 2 + + +i2f_12tbl dw i2f_1200 + dw i2f_1201 + dw i2f_1202 + dw i2f_1203 + dw i2f_1204 + dw i2f_1205 + dw i2f_1206 + dw i2f_12nyi ; Move disk buffer + dw i2f_1208 + dw i2f_12nyi ; DS:DI -> Disk Buffer ?? + dw i2f_120A + dw i2f_120B + dw i2f_120C + dw i2f_120D +if DOS5 + dw share_delay ; delay +else + dw i2f_120E ; get buffers +endif + dw i2f_12nyi ; relink buffer ES:DI ([DI+5].20 <- 0) - Trout + dw i2f_1210 + dw i2f_1211 + dw i2f_1212 + dw i2f_1213 + dw i2f_1214 + dw i2f_12nyi ; Disk buffer DS:SI ??? (Write - Trout) + dw i2f_1216 + dw i2f_1217 + dw i2f_1218 + dw i2f_1219 + dw i2f_121A + dw i2f_121B + dw i2f_121C + dw i2f_121D + dw i2f_121E + dw i2f_121F + dw i2f_1220 + dw i2f_1221 + dw i2f_1222 + dw i2f_1223 + dw share_delay + dw i2f_1225 + dw i2f_1226 + dw i2f_1227 + dw i2f_1228 + dw i2f_1229 + dw i2f_122A + dw i2f_122B + dw i2f_122C + dw i2f_122D +i2f_12size equ ((offset $) - (offset i2f_12tbl))/2 + +i2f_12nyi: +; Sets CY the falls through to installation check - so returns ax = 00FF +; Who knows what to do ? + stc ; indicate problem ? + +i2f_1200: + mov ax,00FFh + ret + +i2f_1201: +; Close file ??? (at current_dhndl) + les di,current_dhndl + mov bx,es:DHNDL_WATTR[di] + test bh,DHAT_REMOTE/100h + jz i2f_1201_10 ; is it networked ? + mov ax,I2F_CLOSE + int 2fh ; then close using int 2f call +i2f_1201_10: ; else do nothing for now + ret + +i2f_1202: +; Get Interrupt Vector pointer + xor bx,bx + mov es,bx ; point at the vectors + mov bl,8[bp] ; pick up which vector + add bx,bx + add bx,bx ; make it a DWORD offset + ret + +i2f_1203: +; Get DOS Data segment + jmp get_dseg ; return DS = DOS data seg + +i2f_1204: +; Normalise path character + mov ax,8[bp] ; the char is on the stack +tobslash: + cmp al,'/' ; if it's a fslash + jne i2f_1204_10 + mov al,'\' ; make it a bslash +i2f_1204_10: + cmp al,'\' ; set ZF if bslash + ret + +i2f_1205: +; Output Character on the stack + push dx + mov ah,MS_C_WRITE + mov dx,8[bp] ; get char from the stack + call dos_entry ; and output it + pop dx + ret + +i2f_1206: +; Invoke critical error INT 24 + push ds + mov ax,8[bp] ; action/drive on stack + mov es,0[bp] ; seg was in BP + call get_dseg ; get the segment right + call do_int24 ; invoke the critical error handler + push ax + les ax,int24_esbp + mov [bp],ax ; really return new BP + pop ax + pop ds + ret + +i2f_1208: +; Decrement word at ES:DI, skipping zero + mov ax,es:word ptr [di] ; return the word in AX +i2f_1208_10: + dec es:word ptr [di] ; dec it + jz i2f_1208_10 ; dec again if it's zero + ret + +i2f_120A: + push ds + lds si,current_ddsc ; point at current driver + lodsb ; get the drive + cbw ; pretend dos area read + pop ds + mov err_drv,al + mov rwmode,ah ; set error drive for Int 24h + mov ax,3 ; return a Fail ? + stc ; return as error + ret + +i2f_120B: +; ES:DI -> system file table entry + mov ax,20h ; sharing violation + stc ; return as error + ret + +i2f_120C: +; Open file ??? (at current_dhndl) + les di,current_dhndl +; would need to call the device driver, but as we don't support this for +; block devices and as it is generally not supported for remote files (but +; only known to be called from redirectors) we leave this out for later + test es:byte ptr DHNDL_MODE+1[di],DHM_FCB/100h + jz i2f_120C_10 ; is it an FCB open ? + mov ax,current_psp + mov es:DHNDL_PSP[di],ax ; update owning PSP field +i2f_120C_10: ; else do nothing for now + ret + +i2f_120D: +; Get Date/Time + push ds + push es + push cx + push bx + push si + push di + push ss + pop ds + call ReadTOD + pop di + pop si + pop bx + pop cx + pop es + pop ds + ret + + +if DOS5 eq 0 +i2f_120E: +; Disk Buffers +; On Return ES:DI -> first disk buffer +; + les di,ss:bcb_root ; get head of buffer chain + ret +endif + + +i2f_1210: +; Find Dirty Buffer Entry DS:SI -> 1st buffer, On exit DS:SI-> 1st dirty buffer +; ZF set if none found + xor ax,ax ; never find dirty buffers + ret + +i2f_1211: +; Normalise ASCIIZ filename DS:SI -> source buffer, ES:DI -> dest buffer +; make uppercase, fslash becomes bslash +; (Stops at slash - Trout) + lodsb ; get a character + call toupper ; upper case it + call tobslash ; convert '/' to '\' + stosb ; plant it + test al,al ; terminating zero ? + jnz i2f_1211 + mov ax,8[bp] ; AX from stack + ret + +i2f_1212: +; Get length of ASCIIZ string ES:DI + push ds ! push si + push es ! pop ds + mov si,di ; make DS:SI -> ASCIIZ + call i2f_1225 ; then use our other primitive + pop si ! pop ds + ret + +i2f_1213: +; Upperase character on stack + mov ax,8[bp] ; get the character + jmp toupper ; use BDOS Intl routine + +i2f_1214: +; Compare far pointers DS:SI with ES:DI + cmp di,si + jne i2f_1214_10 + push ax ! push bx + mov ax,ds + mov bx,es + cmp ax,bx + pop bx ! pop ax +i2f_1214_10: + ret + +i2f_1216: +; Get address in ES:DI of DOSHNDL for file BX + push ds + call get_dseg ; we work with the PCMODE data + les di,file_ptr ; get the address of the first entry + pop ds + push bx ; handle # in BX +i2f_1216_10: + cmp bx,es:DCNTRL_COUNT[di] ; handle in this block? + jb i2f_1216_20 ; skip if yes + sub bx,es:DCNTRL_COUNT[di] ; update the internal file number + les di,es:DCNTRL_DSADD[di] ; get the next entry and check + cmp di,0FFFFh ; for the end of the list + jnz i2f_1216_10 + pop ax ; handle # back in AX + stc ; invalid file handle number + ret + +i2f_1216_20: + push dx ; save DX and calculate the offset + mov ax,DHNDL_LEN ; of the DOS Handle + mul bx + add di,ax ; add structure offset (should be 0) + add di,DCNTRL_LEN ; and then skip the header + pop dx + pop ax ; handle # back in AX +; clc + ret ; valid file handle number + +i2f_1217: +; Default Drive ??? +; On Exit: +; AL = drive we have set to, DS:SI -> LDT structure + call get_dseg ; DS -> PCMODE data + mov ax,8[bp] ; get the drive + cmp al,last_drv ; do we have an LDT for it ? + jae i2f_1217_10 ; if not do no more + cmp word ptr ldt_ptr+2,0 ; valid LDT ? + je i2f_1217_10 + push ax + mov ah,LDT_LEN + mul ah + lds si,ldt_ptr + add si,ax ; DS:SI -> requested LDT, current_LDT + mov ss:word ptr current_ldt,si + mov ss:word ptr current_ldt+2,ds + pop ax + stc ; indicate NO error (CY inverted) +i2f_1217_10: + cmc + ret ; CY set if invalid + + +i2f_1218: +; DS:SI -> User register on DOS Call + call get_dseg ; we save SS:SP after PUSH$DOS + lds si,int21regs_ptr ; in this location + ret + +i2f_1219: +; Stack = drive (0=default, 1 = A: etc) + push ds ! push si ! push word ptr 8[bp] + dec byte ptr 8[bp] ; make drive zero based + cmp byte ptr 8[bp],0ffh ; do we want the default ? + jne i2f_1219_10 + call get_dseg + mov al,current_dsk + mov byte ptr 8[bp],al ; use the default drive +i2f_1219_10: + call i2f_1217 ; set's up current_ldt + jc i2f_1219_20 + test ds:byte ptr 44h[si],40h ; is it valid LDT ? + jnz i2f_1219_20 + stc ; indicate an error +i2f_1219_20: + pop word ptr 8[bp] ! pop si ! pop ds + ret + +i2f_121A: +; Get files drive DS:SI -> drives, AL = drive + xor ax,ax ; assume default drive + cmp ds:byte ptr 1[si],':' + jne i2f_121A_10 ; if no drive letter, then default + mov al,ds:byte ptr [si] + test al,al ; null string ? + jz i2f_121A_10 ; then it's the default drive + call toupper + sub al,'A'-1 ; make one based + jbe i2f_121A_20 ; it's invalid.. + push ds + call get_dseg + cmp al,last_drv ; is it a valid drive ? + pop ds + ja i2f_121A_20 ; yes, return it +i2f_121A_10: + clc + ret +i2f_121A_20: + mov al,0FFh ; invalid drive + stc + ret + +i2f_121B: +; On Entry CX = year-1980 +; On Exit AL = days in February + push bx + mov bx,offset days_in_month+1 + mov ds:byte ptr [bx],28 ; assume 28 days in Feb + test cl,3 ; is it a leap year ? + jnz i2f_121B_10 + inc ds:byte ptr [bx] ; yes, we have 29 +i2f_121B_10: + mov yearsSince1980,cl ; save the year + mov al,ds:byte ptr [bx] ; return the days in Feb + pop bx + ret + +i2f_121C: +; Checksum Memory CX bytes at DS:SI, DX = initial checksum +; DX = final checksum +; I've seen this used to total days in N months. +; On Entry: +; CX = current month +; DX = total days in prior years +; DS:SI -> days-per-month table +; On Exit: +; DX = Total days to start of current month +; + xor ax,ax ; clear AX + jcxz i2f_121C_20 ; check for zero bytes +i2f_121C_10: + lodsb ; get a byte + add dx,ax ; add to the checksum + loop i2f_121C_10 ; until we run out +i2f_121C_20: + ret + +i2f_121D: +; Calculate Date +; On Entry: +; CX = 0 +; DX = total day count this year +; DS:SI -> days-per-month table +; On Exit: +; CX = Month +; DX = Day +; + xor ax,ax +i2f_121D_10: + lodsb + inc cx + sub dx,ax + jnb i2f_121D_10 + dec cx ; undo the last count + add dx,ax ; undo the sub + cmp dx,ax ; get the flags right + ret + +i2f_121E: +; Compare Filenames at DS:SI and ES:DI + push si ! push di ! push cx + call i2f_1225 ; find length of DS:SI filename + push cx + call i2f_1212 ; find length of ES:DI filename + pop ax + cmp ax,cx ; if lengths not the same + jne i2f_121E_20 ; don't even bother +i2f_121E_10: + push cx + lodsb + call toupper + call tobslash ; normalise slash characters + push ax ; save it + mov al,es:byte ptr [di] + inc di + call toupper + call tobslash ; normalise slash again + pop cx ; recover the character + cmp al,cl ; are they the same? + pop cx + loope i2f_121E_10 ; yes, try again if we have any left +i2f_121E_20: + pop cx ! pop di ! pop si + mov ax,8[bp] ; return stack value in AX + ret + +i2f_121F: +; Build drive info into block +; Stack = Drive (1=A: etc) + push ds ! push si ! push dx + call get_dseg + les di,current_ldt + push di + mov ax,8[bp] ; get the drive we want to do + stosb ; plant the ASCII + xchg ax,dx ; save drive in DX + mov ax,'\:' + stosw ; we have d:\ + xor ax,ax + mov cx,LDT_FLAGS-3 + rep stosb ; zero rest of name and flags +; lea di,LDT_FLAGS + and dl,1fh ; convert from ASCII + dec dx ; into zero based drive number + cmp dl,phys_drv ; valid physical drive ? + jae i2f_121F_10 ; mark it as such + mov ax,LFLG_PHYSICAL +i2f_121F_10: + stosw ; set flags +; lea di,LDT_PDT + lea si,ddsc_ptr-18h +i2f_121F_20: + lds si,18h[si] + cmp si,-1 + je i2f_121F_30 + cmp dl,[si] ; is this the DDSC for the drive + jne i2f_121F_20 ; if so save it away +i2f_121F_30: + xchg ax,si ; AX = DDSC offset + stosw + mov ax,ds ; AX = DDSC seg + stosw +; lea di,LDT_BLK + mov ax,0FFFFh ; AX = FFFF + stosw ! stosw ! stosw ; fill in block info +; lea di,LDT_ROOTLEN + mov ax,2 + stosw ; set root length + pop di + pop dx ! pop si ! pop ds + ret + +i2f_1220: +; Get pointer to system file table number for handle BX into ES:DI + push ds + call get_dseg + mov es,current_psp + mov ax,6 ; assume illegal + cmp bx,PSP_XFNMAX ; is it a legal handle + cmc ; invert CY for error return + jc i2f_1220_10 ; no, forget it + les di,PSP_XFTPTR ; get XFT from PSP + add di,bx ; add in the offset +; clc +i2f_1220_10: + pop ds + ret + +i2f_1221: + mov ah,MS_X_EXPAND ; let the FDOS do the walking... + call DOS ; and call our internal entry point + jnc i2f_1221_10 + neg ax ; get error code correct + stc ; before returning error +i2f_1221_10: + ret + +i2f_1222: +; Store error class, locus, action from DS:SI +i2f_1222_10: + lodsw + cmp al,byte ptr error_code ; have we found the error ? + je i2f_1222_20 + inc al ; or hit the end of the list ? + jz i2f_1222_20 + lodsw ; skip this one + jmp i2f_1222_10 ; and try the next +i2f_1222_20: + cmp ah,0ffh ; valid error class ? + je i2f_1222_30 + mov error_class,ah +i2f_1222_30: + lodsw + cmp al,0ffh + je i2f_1222_40 + mov error_action,al +i2f_1222_40: + cmp ah,0ffh + je i2f_1222_50 + mov error_locus,ah +i2f_1222_50: + ret + +i2f_1223: +; On Entry buffer at 4E6 filled with Device name - eg. "NAME1 " +; Preserve word ptr [4E6] +; if byte ptr [4E6] = 5 then byte ptr [4E6] = E5 +; if byte ptr [506] & 8 then exit now with STC +; otherwise work down device chain +; Find device driver for device NAME1 +; Check if character device + push ds + call get_dseg +if FALSE + push word ptr name_buf ; save 1st char of name + test magic_byte,8 ; magic location and number ?? + jnz i2f_1223_40 ; can we do the check ? + cmp name_buf,5 + jne i2f_1223_10 ; if 1st char is 5, make it + mov name_buf,0e5h ; an E5 +i2f_1223_10: +endif + mov si,offset nul_device ; start from NUL +i2f_1223_20: + test ds:DH_ATTRIB[si],DA_CHARDEV + jz i2f_1223_30 ; skip unless character device + mov cx,8 + lea di,name_buf ; point at name we are looking for + push si + lea si,ds:DH_NAME[si] ; point a device name + repe cmpsb ; compare the names + pop si + jne i2f_1223_30 ; if we found it, save info + mov es:word ptr current_device,si + mov es:word ptr current_device+2,ds + mov bh,ds:byte ptr DH_ATTRIB[si] + or bh,0e0h + xor bh,20h ; clear this bit + clc ; we found it + jmps i2f_1223_50 +i2f_1223_30: + lds si,ds:DH_NEXT[si] + cmp si,0ffffh ; any more entries ? + jne i2f_1223_20 ; yes, do them +i2f_1223_40: + stc +i2f_1223_50: +if FALSE + pushf + call get_dseg ; we may have scambled DS + popf + pop word ptr name_buf ; restore 1st character +endif + pop ds + ret + + +i2f_1225: +; Get length of ASCIIZ string DS:SI + call strlen + inc cx ; include the terminating zero + mov ax,8[bp] ; restore AX from stack + ret + +; The following are NOT required for MSNET - they are used by NLSFUNC + +i2f_1226: +; Open the file at DS:DX + mov al,cl ; open mode in CL on entry + mov ah,MS_X_OPEN ; open the file +DOS: + push ds ! push es ! pop ds ! pop es + call dos_entry ; reverse DS/ES before for dos_entry + push ds ! push es ! pop ds ! pop es + ret + +i2f_1227: +; Close file BX + mov ah,MS_X_CLOSE ; close the file + jmps DOS + +i2f_1228: +; LSEEK on file BX + mov ax,[bp] ; seek mode in BP on entry + mov ah,MS_X_LSEEK ; do the seek + jmps DOS + +i2f_1229: +; Read from file BX + mov ah,MS_X_READ + jmps DOS + +i2f_122A: +; Set fastopen entry point to DS:SI +; SI = FFFF, sdont't set - just check if installed + mov ax,si ; AX = offset + inc ax ; AX = 0 if it's an installation check + stc ; assume it is, and say not installed + jne i2f_122A_10 + clc ; fail new installation +i2f_122A_10: + ret + +i2f_122B: +; IOCTL + mov al,[bp] ; get IOCTL minor + mov ah,MS_X_IOCTL + jmps DOS + +i2f_122C: +; Get 2nd device driver header address + push ds + call get_dseg + lds ax,ds:dword ptr nul_device + mov bx,ds ; BX:AX -> 2nd device header + pop ds + ret + +i2f_122D: +; Get extended error code + mov ax,error_code + ret + + +; +; Our FDOS extentions live here +; +if DELWATCH + extrn locate_buffer:near + extrn flush_drive:near + extrn delfat:near + extrn allocate_cluster:near + extrn getblk:near + extrn change_fat_entry:near + extrn fixup_hashing:near + +; for speed/code size we just call directly in BLACK.A86 +endif + +i2f_10tbl dw i2f_10nyi ; never gets here... + dw i2f_1001 ; install fdos hook +if DELWATCH +if FALSE + dw i2f_1002 ; read buffer + dw i2f_1003 ; flush buffers + dw i2f_1004 ; free fat chain + dw i2f_1005 ; allocate cluster + dw i2f_1006 ; next cluster + dw i2f_1007 ; update fat entry + dw i2f_1008 ; fixup checksums +else + dw locate_buffer ; ask BLACK to find that buffer + dw flush_drive ; ask BLACK to flush buffers + dw delfat ; ask BLACK to release FAT chain + dw allocate_cluster; ask DEBLOCK to allocate space + dw getblk ; ask DEBLOCK to return next block + dw change_fat_entry; ask DEBLOCK to update fat entry + dw fixup_hashing ; ask BLACK to fixup hashing/checksums +endif + dw i2f_1009 ; directory buffer info +endif +i2f_10size equ (offset $ - offset i2f_10tbl)/2 + +i2f_1001: +;-------- +; install fdos stub +; +; On Entry: +; DX:AX -> new fdos_stub entry address +; On Exit: +; None +; + call get_dseg ; get PCMode data seg + mov word ptr fdos_stub,ax ; fixup our share stubs + mov word ptr fdos_stub+WORD,dx +i2f_10nyi: + ret + +if DELWATCH +if FALSE + +i2f_1002: +;-------- +; read buffer +; On Entry: +; CH = 0FFh (pre-read required) +; CL = BF_ISFAT/BF_ISDIR/BF_ISDATA +; AH:DX = 24 bit sector number +; On Exit: +; ES:SI -> Buffer control block +; + jmp locate_buffer + +i2f_1003: +;-------- +; flush buffers +; On Entry: +; AL = drive +; AH = buffer type to flush (BF_ISFAT+BF_ISDIR+BF_ISDATA) +; On Exit: +; None +; + jmp flush_drive + +i2f_1004: +;-------- +; free fat chain +; On Entry: +; AX = 1st block to release on current drive +; On Exit: +; None + jmp delfat + +i2f_1005: +;-------- +; allocate cluster +; On Entry: +; AX = block to start search from (eg. current end of file) +; 0000 = start of disk +; On Exit: +; AX = 0000 if none available +; else allocated block (marked as End Of Chain) +; + jmp allocate_cluster ; ask DEBLOCK.A86 to allocate some space + +i2f_1006: +;-------- +; get next cluster +; On Entry: +; AX = current block +; On Exit: +; AX = next block in chain +; + jmp getblk ; ask DEBLOCK.A86 to return next block + +i2f_1007: +;-------- +; change fat entry +; On Entry: +; AX = fat entry to change +; DX = new value +; On Exit: +; None +; + jmp change_fat_entry ; ask DEBLOCK.A86 to modify FAT entry + +i2f_1008: +;-------- +; update hash code for directory entry on current drive +; On Entry: +; AX = segment of dir buffer +; CX = cluster to fixup (0 = root) +; DI = directory entry index(clipped to cluster if subdir) +; AX:SI-> dir entry (single entry for hashing) +; On Exit: +; None +; + jmp fixup_hashing + +endif + +i2f_1009: +;-------- +; return dirbuf info +; On Entry: +; None +; On Exit: +; ES:DI -> 128 byte directory record buffer +; ES:SI -> dir bcb structure +; 0[si] = drive (FF = invalid) +; 1[si] = low byte of record number +; 2[si] = mid byte of record number +; 3[si] = hi byte of record number +; + push cs ! pop es + mov si,offset invalid_dir_bcb + ret + +invalid_dir_bcb db 0ffh ; drive is invalid +; db ?,?,? ; don't bother about record number + +endif ;DELWATCH + + +WindowsHooks: +;------------ +; On Entry: +; AH = 16h, it's a windows broadcast +; AL = subfunction, other regs as appropriate +; On Exit: +; Various +; +if DOS5 + cmp al,07h ; 1607: Virtual device init + je WindowsDOSMGR +endif + test dx,1 ; is it a DOSX broadcast ? + jnz WindowsExit + cmp al,05h ; 1605: Windows enhanced mode init + je WindowsStartup +if DOS5 + cmp al,06h ; 1606: Windows enhanced mode exit + je WindowsShutdown +endif +WindowsExit: + iret + + + +WindowsStartup: +;-------------- + push ds + call get_dseg ; DS -> our data +if DOS5 + inc criticalSectionEnable ; enable Int 2Ah for Windows + inc WindowsHandleCheck +endif + +;;if 0 Put this back in, as instance data still required +;; Removed pointer to vxd in HEADER.A86 BAP + + mov SwStartupInfo+2,bx ; Commented out, as NWDOS.386 + mov SwStartupInfo+4,es ; no longer needed. + push ds + pop es ; ES -> pcmode data + mov bx,offset SwStartupInfo +;;endif + jmp int2F_BIOS ; pass on to the BIOS + +if DOS5 + +WindowsShutdown: +;--------------- + push ds + call get_dseg ; DS -> our data + dec criticalSectionEnable ; enable Int 2Ah for Windows + dec WindowsHandleCheck + pop ds + sub dx,dx ; return success + iret + + +WindowsDOSMGR: +;------------- + cmp bx,15h ; is it DOS manager? + jne WindowsExit ; forget the others +; cmp cx,0 + jcxz WindowsCX0 + dec cx + jcxz WindowsCX1 + dec cx ! dec cx ! dec cx + jcxz WindowsCX4 + dec cx + jcxz WindowsCX5 + iret + + +WindowsCX0: +;---------- + push ds + call get_dseg + push ds + pop es ; ES = DOS data segment + pop ds + lea bx,windowsData ; ES:BX -> secret variables + inc cx ; tell them we've responded + iret + +WindowsCX1: +;---------- + mov bx,dx ; entry DX=1Fh, exit BX=1Fh + mov ax,0B97Ch ; AX, DX are magic values + mov dx,0A2ABh +; xor cx,cx ; CX = 0 + iret + +WindowsCX4: +;---------- + xor dx,dx +; xor cx,cx ; CX = 0 + iret + +WindowsCX5: +;---------- +; entry: ES:DI -> device driver +; determine device driver size in bytes + + push ds + test di,di ; not primary DEVICE= driver? + jnz WindowsCX5NoDev ; can't have DMD preceeding it + mov ax,es ; get device segment + dec ax ; DMD is one paragraph lower down + mov ds,ax ; DS:DI -> device DMD + inc ax ; AX = device driver segment + cmp ds:byte ptr 0[di],'D' ; see if 'D'device= + jne WindowsCX5NoDev ; skip if not + cmp ax,ds:word ptr 1[di] ; owned by the driver ? + jne WindowsCX5NoDev ; skip if not + + mov ax,10h ; bytes per paragraph + mul ds:word ptr 3[di] ; bytes in device driver + pop ds + mov bx,dx ; BX = high word + xchg ax,cx ; CX = low word + mov ax,0B97Ch ; AX, DX are magic values + mov dx,0A2ABh + iret + +WindowsCX5NoDev: +; ES:DI -> not an external device + pop ds + xor ax,ax + xor dx,dx +; xor cx,cx ; CX = 0 + iret + +endif +eject +PCMODE_DATA DSEG WORD + extrn hmaRoot:word + extrn last_drv:byte + extrn phys_drv:byte + extrn ddsc_ptr:dword + extrn current_psp:word + extrn current_dsk:byte + extrn net_delay:word + extrn nul_device:byte + extrn error_code:word + extrn error_class:byte + extrn error_action:byte + extrn error_locus:byte + extrn file_ptr:dword + extrn ldt_ptr:dword + extrn current_device:dword + extrn current_ldt:dword + extrn current_dhndl:dword + extrn current_ddsc:dword + extrn yearsSince1980:byte + extrn days_in_month:byte + extrn name_buf:byte + extrn int21regs_ptr:dword + extrn int24_esbp:dword + extrn int2FNext:dword + extrn fdos_stub:dword + extrn SwStartupInfo:word + extrn err_drv:byte + extrn rwmode:byte + +if DOS5 + extrn indos_flag:byte, machine_id:byte, internal_data:byte, dmd_upper_root:word + + extrn criticalSectionEnable:byte + extrn WindowsHandleCheck:byte + +GLOBAL_DATA dseg + +windowsData dw 5 ; version number ? + dw $ ; dummy + dw $ ; dummy + dw offset indos_flag + dw offset machine_id + dw offset internal_data-10 + dw offset dmd_upper_root +else + extrn bcb_root:dword +endif + end diff --git a/IBMDOS/IOCTL.A86 b/IBMDOS/IOCTL.A86 new file mode 100644 index 0000000..d76bb66 --- /dev/null +++ b/IBMDOS/IOCTL.A86 @@ -0,0 +1,468 @@ +; File : $IOCTL.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; $Log: $ +; IOCTL.A86 1.17 94/11/28 15:42:19 +; f440B now does not modify net_retry if DX=0 +; IOCTL.A86 1.16 93/11/08 19:15:18 +; SETVER to subversion 0xFF disabled int 21/4452 +; IOCTL.A86 1.15 93/07/26 18:16:16 +; add some code which disables drdos check if app is SETVER'd +; leave said code disabled unless required +; IOCTL.A86 1.14 93/07/22 19:29:54 +; get/set serial number now the correct way round +; IOCTL.A86 1.11 93/06/17 22:14:34 +; support for ioctl 10/11 query ioctl support +; ENDLOG +; +; 7 Nov 87 Removal of development flags +; 17 Dec 87 Return "Single device Supported" for IOCTL sub-functions +; 0Eh and 0Fh. +; 24 Feb 88 Return 1060h from IOCTL sub-function 51h under DOS PLUS +; instead of the Concurrent DOS OS version. +; 24 Feb 88 Correct Generic IOCTL function and prevent the generation +; of critical errors. +; 24 May 88 sub-function 53h returns the address of the INT24 handler +; for the command processor. +; 01 Jun 88 Add sub-function 4454 to support setting the default password +; 03 Nov 88 Add History Buffer Sub-Command f4456 for DOSPLUS +; 02 Feb 89 Add code page switching sub-function 0Ch +; 19 Feb 89 Support Sub-Command f4457 to control SHARE +; 15 Mar 89 Do not generate critical errors from 4402 and 4403. +; 18 Apr 89 Sub-function 53 only suported for Concurrect DOS +; 19 Apr 89 Don't clobber error code on 440D and 440E (pc-cache) +; 31 May 89 New function f4458 to return pointer to private data. +; 31 May 89 f440B sets up DOS internal data +; 15 Jun 89 Don't throw away inheritance bit when masking Share Mode Flags +; 11 Oct 89 f4407/07 set AX on return, not just AL +; 26 Oct 89 for a few bytes more... +; 18 Jan 90 HILOAD interface added onto f4457 +; 25 Jan 90 INT21/4458 returns a pointer to IDLE_DATA in ES:AX +; 13 Jan 90 private_data exported in CDOS for DEBUG systems +; 27 Feb 90 4459 provides Int21 function that does Int224 calls +; 7 Mar 90 Convert to register preserved function calls +; 14 Mar 90 No critical error generated in IOCTL functions +; 3 May 90 stop forcing ioctl 4403/3/4/5 errors to ED_ACCESS +; 4 Jun 90 445A provides user group support on CDOS +; 3 jun 92 Add 4456/2+3 to examine history state, toggle history enable +; 30 jul 92 HILOAD now uses official memory strategy calls +; + include pcmode.equ + include fdos.def + include i:msdos.equ + include i:mserror.equ + include i:cmdline.equ + include i:driver.equ + include i:reqhdr.equ + include i:psp.def + +PCM_CODE CSEG BYTE + extrn os_version:word + extrn patch_version:word + + extrn invalid_function:near + extrn error_ret:near + extrn fdos_nocrit:near + extrn fdos_crit:near + extrn fdos_ax_crit:near + extrn return_AX_CLC:near + extrn return_DX:near + extrn return_DSBX_as_ESBX:near + extrn set_retry_RF:near + extrn patch_version:word + + +; ***************************** +; *** DOS Function 69 *** +; *** set/get serial num *** +; ***************************** +; + Public func69 +func69: + call set_retry_RF ; Prepare for an FDOS function + mov FD_FUNC,MS_X_IOCTL + mov cx,866h ; assume a get serial num + cmp al,1 ; check for 0/1 + mov al,0Dh ; ready for ioctl 0D + jb func44common ; go ahead with get serial num + mov cl,46h ; maybe it's a set + je func44common ; go ahead with set serial num +; jmp invalid_function ; ah well, it's an invalid one + jmps f44_30 + +; ***************************** +; *** DOS Function 44 *** +; *** I/O Control *** +; ***************************** +; + Public func44 +func44: + call set_retry_RF ; Prepare for an FDOS function +func44common: + mov FD_IOCTLFUNC,ax ; save subfunction for FDOS + mov ioctlRH,22 ; assume RH will be wanted + mov ioctlRH+13,0 ; init len and media byte + mov word ptr ioctlRH+14,dx ; point at buffer segment + mov word ptr ioctlRH+16,es + mov word ptr ioctlRH+18,cx ; the Byte Count + cmp ax,dosf44_ftl ; Check for a valid PC-DOS + jae f44_20 ; sub-functions +f44_10: + xchg ax,si + shl si,1 + mov si,func44_ft[si] + xchg ax,si + jmp ax +f44_20: + sub al,52h-dosf44_ftl ; adjust to our base of 52h + jc f44_30 ; bail out if too low + cmp ax,ourf44_ftl ; is it too high ? + jb f44_10 +f44_30: + jmp invalid_function + +; *********************************************** +; *** Sub Function 00 - Get Device Info *** +; *********************************************** +f4400: + call fdos_handle ; execute the function + mov dx,ax ; return in DX too +return_AX_and_DX: + call return_DX ; return to caller in DX + jmp return_AX_CLC ; return AX too + +; *********************************************** +; *** Sub Function 01 - Set Device Info *** +; *** Sub Function 06 - Get Input Status *** +; *** Sub Function 07 - Get Output Status *** +; *********************************************** +f4401: +f4406: +f4407: + call fdos_handle ; Execute the Function + jmp return_AX_CLC + +; ************************************************ +; *** Sub Function 04 - Read Blk Device *** +; *** Sub Function 05 - Write Blk Device *** +; *** Sub Function 11 - Query ioctl Blk *** +; ************************************************ +; +f4404: +f4405: +f4411: + xor bh,bh ; BX = drive number + +; ************************************************ +; *** Sub Function 02 - Read Character Dev *** +; *** Sub Function 03 - Write Character Dev *** +; *** Sub Function 10 - Query ioctl Char *** +; ************************************************ +; +f4402: +f4403: +f4410: + mov dx,DA_QUERY ; assume we will query support + mov al,CMD_QUERY_IOCTL ; and be ready to go + mov cx,FD_IOCTLFUNC ; re-read the function number + test cl,10h ; is it function 10 of 11? + jnz f44ioctl ; yes, we are ready + mov dx,DA_IOCTL ; no, we actually want to do it + mov al,CMD_INPUT_IOCTL ; even functions are input + test cl,1 ; test for input functions + jz f44ioctl + mov al,CMD_OUTPUT_IOCTL ; odd functions are output +f44ioctl: + mov FD_IOCTLSTAT,dx ; this device driver support is required + mov ioctlRH+2,al ; this is the function + call fdos_handle ; Execute the Function + mov ax,word ptr ioctlRH+18 ; return # xfered + jmp return_AX_CLC + +; ***************************** +; *** Sub Function 09 *** +; *** Networked Media *** +; ***************************** +; +f4409: + call fdos_drive ; Execute the Function + mov dx,ax ; Get the Return Information + mov ax,0300h + jmps return_AX_and_DX + +; ***************************** +; *** Sub Function 0A *** +; *** Networked Handle *** +; ***************************** +; +f440A: + call fdos_handle ; Execute the Function + mov dx,ax ; Get the Return Information + jmp return_DX ; and return in DX + +; ***************************** +; *** Sub Function 0B *** +; *** Update Share Retry *** +; ***************************** +; +; dos_CX [1] Number of times to execute the delay loop +; which consists of xor cx,cx ! loop $ +; +; dos_DX [3] Number of times to retry +; +; +f440B: + mov net_delay,cx + test dx,dx + jz f440B_10 + mov net_retry,dx +f440b_10: + ret + +; ***************************** +; *** Sub Function 0D *** +; *** Device Driver Req *** +; ***************************** +; +f440D: + xor bh,bh +; jmp f440C + +; ***************************** +; *** Sub Function 0C *** +; *** Code Page Switching *** +; ***************************** +; +f440C: + mov FD_IOCTLSTAT,DA_GETSET ; device driver support required + mov FD_HANDLE,bx ; Save the Handle Number + mov ioctlRH,23 ; different RH length + mov ioctlRH+2,CMD_GENERIC_IOCTL + xchg cl,ch ; swap minor/major functions + mov word ptr ioctlRH+13,cx ; and store in request header + mov word ptr ioctlRH+15,si + mov word ptr ioctlRH+17,di + mov word ptr ioctlRH+19,dx ; point at buffer segment + mov word ptr ioctlRH+21,es + call fdos_ax_crit ; Execute the Function and + jc fdos_error ; return all error codes + ret + +; *********************************************** +; *** Sub Function 08 - Removable Media *** +; *** Sub Function 0E - Get Logical Drive *** +; *** Sub Function 0F - Set Logical Drive *** +; *********************************************** +; +f4408: +f440E: +f440F: + call fdos_drive ; Execute the Function + jmp return_AX_CLC ; return result in AX + + +fdos_drive: +;---------- + xor bh,bh ; BX = the drive number +fdos_handle: +;---------- + mov FD_HANDLE,bx + call fdos_crit ; then execute the FDOS + jnc fdos_OK ; exit on Error + add sp,WORD ; discard near return address +fdos_error: + jmp error_ret ; and return the error +fdos_OK: + mov ax,FD_IOCTLSTAT ; get the return information + ret +eject +; ***************************** +; *** CCP/M Extension *** +; *** Sub Function 52 *** +; *** Return CCP/M Version *** +; ***************************** +; +f4452: +if DOS5 + mov es,current_psp ; version is kept in the PSP + cmp PSP_VERSION,0FF00h ; sub-version of 255 ? + jae f4452_10 ; then say we ain't DRDOS +endif + mov ax,cs:os_version ; Get OS ver number + mov dx,cs:patch_version + call return_DX ; return in DX + jmp return_AX_CLC ; return in AX + +if DOS5 +f4452_10: + jmp invalid_function +endif + +if PASSWORD + +; ***************************** +; *** CCP/M Extension *** +; *** Sub Function 54 *** +; *** Set Default PASSWORD *** +; ***************************** +; +f4454: + mov FD_IOCTLFUNC,0Bh ; save subfunction for FDOS + jmp fdos_nocrit ; Execute the Function + +endif + + +; ***************************** +; *** CCP/M Extension *** +; *** Sub Function 56 *** +; *** History Buffer Cntrl *** +; ***************************** +; +; This function changes the default history buffer used for func0A: +; +; On Entry: +; DL = 0 -> Standard Process Buffer +; DL = 1 -> Command.com history Buffer +; DL = 2 -> Toggle history enable/disable +; DL = 3 -> Get current state of history buffers +; DL = 4 -> Toggle insert mode +; +; On Exit: +; AL = previous history state (Bit 0 set if history on) +; Bit 0 -> set if history enabled +; Bit 1 -> set if insert enabled +; Bit 7 -> set if command history buffer +; +f4456: + mov ax,cle_state ; Get the current History Status + cmp dl,2 ; are we disabling/enabling ? + jb f4456_10 ; below, switch buffers + je f4456_05 ; yes, try and do it + cmp dl,4 ; toggle insert state ? + jne f4456_20 ; no, return existing state + xor al,RLF_INS ; toggle insert state + jmps f4456_20 ; set and return prev state + +f4456_05: + mov cl,RLF_ENHANCED ; we are interested in enhancements + test @hist_flg,cl ; only if history possible + jz f4456_20 ; just return existing state + xor al,cl ; invert current setting + ; and fall thru' to enable/disable + ; standard buffer (never called + ; by COMMAND...) +f4456_10: + or al,RLF_INROOT ; assume we are in the root +if IDLE_DETECT + or idle_flags,IDLE_COMMAND +endif + test dl,1 ; Get new state and mask bit + jnz f4456_20 + and al,not RLF_INROOT ; we are in application buffer +if IDLE_DETECT + and idle_flags,not IDLE_COMMAND +endif +f4456_20: + xchg ax,cle_state ; set state, returning old state + ret + + +; ***************************** +; *** CCP/M Extension *** +; *** Sub Function 58 *** +; *** Private Data Func *** +; ***************************** +; +; On Exit ES:BX points to our DRDOS private data. +; ES:AX points to the IDLE Data Area + +f4458: + mov bx,offset @private_data + call return_DSBX_as_ESBX ; return ES:BX pointing to private data + mov ax,offset idle_data + jmp return_AX_CLC + + + + +PCM_RODATA CSEG WORD +; +; PCDOS Sub-Functions Only +; +func44_ft dw f4400 + dw f4401 + dw f4402 + dw f4403 + dw f4404 + dw f4405 + dw f4406 + dw f4407 + dw f4408 + dw f4409 + dw f440A + dw f440B + dw f440C + dw f440D + dw f440E + dw f440F + dw f4410 + dw f4411 +dosf44_ftl equ (offset $ - offset func44_ft)/2 +; +; CCP/M Sub-Functions Only +; + dw f4452 ; 4452 OS version no + dw invalid_function ; 4453 Invalid Function +if PASSWORD + dw f4454 ; 4454 set default password +else + dw invalid_function ; 4454 was set default password +endif + dw invalid_function ; 4455 Invalid Function + dw f4456 ; 4456 history buffer support + dw invalid_function ; 4457 was share enable/disable + dw f4458 ; 4458 pointer to private data + +ourf44_ftl equ (offset $ - offset func44_ft)/2 + +PCMODE_DATA DSEG WORD + extrn net_delay:word, net_retry:word + extrn @hist_flg:byte + extrn @private_data:byte +if IDLE_DETECT + extrn idle_data:word + extrn idle_flags:word +endif + extrn cle_state:word + extrn ioctlRH:byte + extrn dos_version:word + extrn current_psp:word + + end diff --git a/IBMDOS/MAKE.BAT b/IBMDOS/MAKE.BAT new file mode 100644 index 0000000..1deb259 --- /dev/null +++ b/IBMDOS/MAKE.BAT @@ -0,0 +1,109 @@ +@ECHO off + +SET TOOLS=C:\TOOLS + +REM +REM YOU SHOULD NOT HAVE TO CHANGE ANYTHING BELOW THIS LINE. +REM + +REM Define local Caldera tools +SET LOCTOOLS=..\LTOOLS + +IF NOT EXIST BIN\*.* MD BIN + +REM ****************************************** +REM Build the .A86 files next, get the obj's +REM ****************************************** + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\buffers.a86 .\bin\buffers.obj $szpz /DDELWATCH /DDOS5 +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\dirs.a86 .\bin\dirs.obj $szpz /DDELWATCH +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\fdos.a86 .\bin\fdos.obj $szpz /DDELWATCH /DKANJI /DDOS5 /DPASSWORD /DJOIN /DUNDELETE +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\fcbs.a86 .\bin\fcbs.obj +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\bdevio.a86 .\bin\bdevio.obj $szpz /DDELWATCH /DDOS5 /DJOIN +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\cdevio.a86 .\bin\cdevio.obj $szpz /DDOS5 +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\fioctl.a86 .\bin\fioctl.obj $szpz /DPASSWORD /DJOIN /DDOS5 +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\redir.a86 .\bin\redir.obj $szpz /DKANJI /DDOS5 /DJOIN +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\header.a86 .\bin\header.obj $szpz /DDOS5 +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\pcmif.a86 .\bin\pcmif.obj $szpz /DDOS5 +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\cio.a86 .\bin\cio.obj +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\disk.a86 .\bin\disk.obj $szpz /DDELWATCH +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\ioctl.a86 .\bin\ioctl.obj $szpz /DPASSWORD /DDOS5 +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\misc.a86 .\bin\misc.obj $szpz /DDOS5 +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\support.a86 .\bin\support.obj +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\dosmem.a86 .\bin\dosmem.obj +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\error.a86 .\bin\error.obj +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\process.a86 .\bin\process.obj $szpz /DDOS5 +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\network.a86 .\bin\network.obj +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\int2f.a86 .\bin\int2f.obj $szpz /DDOS5 /DDELWATCH +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\history.a86 .\bin\history.obj +IF ERRORLEVEL 1 GOTO FAILED + +%LOCTOOLS%\rasm_sh %LOCTOOLS%\rasm86.exe . .\cmdline.a86 .\bin\cmdline.obj +IF ERRORLEVEL 1 GOTO FAILED + +copy ibmdos.inp .\BIN +CD .\BIN +..\%LOCTOOLS%\linkcmd.exe ibmdos[i] +IF ERRORLEVEL 1 GOTO FAILED +CD .. +%LOCTOOLS%\bin2asc -ob -s128 .\BIN\ibmdos.tmp .\BIN\ibmdos.com +IF ERRORLEVEL 1 GOTO FAILED +%LOCTOOLS%\compbdos .\BIN\ibmdos.com +IF ERRORLEVEL 1 GOTO FAILED +goto exit + +:failed +ECHO Error in Build! +goto exit + +:badtool +ECHO Can't find that tool! + +:exit +REM ********* +REM CLEANUP +REM ********* + +SET TOOLS= +SET LTOOLS= + \ No newline at end of file diff --git a/IBMDOS/MISC.A86 b/IBMDOS/MISC.A86 new file mode 100644 index 0000000..f10f1e6 --- /dev/null +++ b/IBMDOS/MISC.A86 @@ -0,0 +1,1829 @@ +; File : $MISC.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; $Log$ +; MISC.A86 1.29 94/11/30 14:40:17 +; fixed error return for function 6602 +; MISC.A86 1.28 94/07/13 15:31:04 +; Pass name to share on Int21/5D02 (close file by name) +; MISC.A86 1.27 93/11/29 14:18:16 +; Fix bug in get extended country info if not current country +; MISC.A86 1.25 93/11/19 17:00:14 +; If 21/38 get country info fails for current codepage, try any codepage +; MISC.A86 1.24 93/11/16 15:57:08 +; int 21/5D06 clears CY flag +; MISC.A86 1.23 93/10/21 19:31:16 +; Move Int 21/5D03+5D04 support (close all files by machine/psp) into share +; MISC.A86 1.22 93/10/18 17:41:45 +; fix for >255 open files (PNW Server) +; MISC.A86 1.21 93/09/03 20:28:57 +; Add intl/dbcs support for int 21/6523 (query yes/no char) +; MISC.A86 1.20 93/07/26 20:42:13 +; Seperate int21/3306 +; MISC.A86 1.12 93/03/05 18:12:33 +; Fix DS corruption for NLSFUNC calls +; ENDLOG +; + +VALID_SIG equ 0EDC1h + + include pcmode.equ + include i:msdos.equ + include i:mserror.equ + include i:psp.def + include i:driver.equ + include i:char.def + include i:country.def + include i:doshndl.def + include i:redir.equ + include i:fdos.equ + +NLSFUNC equ TRUE + +; +GLOBAL_DATA DSEG WORD + extrn default_country:byte + extrn Ucasetbl:word + extrn FileUcasetbl:word + extrn FileCharstbl:word + extrn Collatingtbl:word + extrn DBCS_tbl:word + extrn NoYesChars:byte + extrn info1_len:abs + extrn info2_len:abs + extrn info4_len:abs + extrn info5_len:abs + extrn info6_len:abs + extrn info7_len:abs + extrn dos_version:word + extrn country_filename:byte + + +PCM_CODE CSEG BYTE + extrn dbcs_lead:near + extrn device_write:near ; Write to a Character Device + extrn device_read:near ; Read from a Character Device + extrn dos_entry:near + extrn error_exit:near + extrn error_ret:near + extrn func5F_common:near + extrn get_dseg:near + extrn valid_drive:near + extrn ifn2dhndl:near + extrn int21_func:near + extrn invalid_function:near + extrn patch_version:word + extrn reload_registers:near + extrn reload_ES:near + extrn return_AX_CLC:near + extrn return_BX:near + extrn return_CX:near + extrn return_DX:near + extrn toupper:near + extrn xlat_xlat:word + +; +; ***************************** +; *** DOS Function 34 *** +; *** Get The Indos Flag *** +; ***************************** + Public func34 +func34: + mov bx,offset indos_flag +; jmp return_DSBX_as_ESBX ; return ES:BX -> indos flag + + Public return_DSBX_as_ESBX + +return_DSBX_as_ESBX: +;------------------- +; On Entry: +; DS:BX to be returned to caller in ES:BX +; On Exit: +; ES/DI trashed +; + les di,ss:int21regs_ptr + mov es:reg_ES[di],ds + mov es:reg_BX[di],bx + ret + + +; +; ***************************** +; *** DOS Function 52 *** +; *** Get Internal Data *** +; ***************************** +; +; + Public func52 +func52: + mov bx,offset func52_data + jmps return_DSBX_as_ESBX ; return ES:BX -> internal data + +; +; ***************************** +; *** DOS Function 5D *** +; *** Private DOS Func *** +; ***************************** +; +; + Public func5D +func5D: +if DOS5 + cmp al,7 + jae f5d_05 + mov si,dx ; ES:SI -> callers structure + mov bx,es:word ptr 20[si] + mov ss:owning_psp,bx ; update PSP from there + cmp WindowsHandleCheck,26h + jne f5D_05 ; check if Windows is running + mov bx,es:word ptr 18[si] + mov ss:machine_id,bx ; no, update machine_id +f5D_05: +else + push ds + push es ! pop ds ; restore users DS + callf ss:win386_remote_machine + pop ds +endif + cbw ; zero AH for valid functions + xchg ax,bx ; sub function in BX + + cmp bx,func5D_ftl ; Assume Illegal Subfunction + jb f5D_10 ; check that it is a valid + mov bx,func5D_ftl ; subfunction +f5D_10: + shl bx,1 + push func5D_ft[bx] ; save function address + shr bx,1 + xchg ax,bx ; restore BX + ret ; go to function + +f5D_msnet: + mov ax,I2F_REDIR_5D ; magic number to redirect + jmp func5F_common ; calls to extentions +; +; +; The registers for some of the following sub-functions are passed +; in the following structure. +; +RDC_AX equ es:word ptr 00[di] ; User AX +RDC_BX equ es:word ptr 02[di] ; User BX +RDC_CX equ es:word ptr 04[di] ; User CX +RDC_DX equ es:word ptr 06[di] ; User DX +RDC_SI equ es:word ptr 08[di] ; User SI +RDC_DI equ es:word ptr 10[di] ; User DI +RDC_DS equ es:word ptr 12[di] ; User DS +RDC_ES equ es:word ptr 14[di] ; User ES +RDC_RES equ es:word ptr 16[di] ; Remote Machine ID (High Word) +RDC_UID equ es:word ptr 18[di] ; Remote Machine ID (Low Word) +RDC_PID equ es:word ptr 20[di] ; Process ID +; +; ***************************** +; *** DOS Function 5D00 *** +; *** Remote DOS Call *** +; ***************************** +; +; +f5D00: + mov remote_call,0ffh ; set remote op flag + push es + les di,int21regs_ptr ; stack image the copy registers + pop ds + mov cx,6 + rep movsw ; Copy AX, BX, CX, DX, SI, DI + inc di ! inc di ; Skip BP in the destination + movsw ! movsw ; finally copy DS and ES + push ss ! pop ds ; DS -> PCMDSEG + call reload_registers ; load up the new registers + jmp int21_func ; then execute that function + +; ***************************** +; *** DOS Function 5D01 *** +; *** Commit all files *** +; ***************************** +; +f5D01: +;----- +; We are being asked to commit all files to disk +; By pretending to be FCB's we force use of IFN's, and we commit all possible +; files in the range 0-255, ignoring errors from unopened handles. +; + mov remote_call,DHM_FCB ; pretend to be FCB, forces use of IFN + xor bx,bx ; start with handle zero +f5D01_10: + mov ah,MS_X_COMMIT + call dos_entry ; commit this file + inc bx ; onto next candidate + cmp bx,0FFh ; runout yet ? + jb f5D01_10 ; + ret + + +; ***************************** +; *** DOS Function 5D02 *** +; *** Close file by name *** +; ***************************** +; +f5D02: +;----- +; Close file by name. We do a search first to find out about the file. +; As long as it's local we call share with the directory cluster/index +; to close it if it's open. +; + mov di,dx ; ES:DI -> register block + mov dx,RDC_DX + mov es,RDC_DS ; ES:DX -> filename to close + push dma_offset + push dma_segment + mov dma_offset,offset fcb_search_buf + mov dma_segment,ds + mov cx,DA_RO+DA_SYSTEM+DA_HIDDEN + mov ah,MS_X_FIRST ; look for this file + call dos_entry ; to get dir entry info + pop dma_segment + pop dma_offset + jc f5Dret + mov al,fcb_search_buf ; get drive # + test al,al ; reject networked drives + js f5Dret + dec ax ; make drive zero based + mov cx,word ptr fcb_search_buf+0Dh + ; CX = directory count + mov dx,word ptr fcb_search_buf+0Eh + ; DX = parent directory cluster + lea bx,fcb_search_buf+1 ; DS:BX -> name + mov di,S_CLOSE_IF_OPEN +; jmps f5D_common +f5D_common: + callf lock_tables ; protect SHARE with a critical section + callf share_stub[di] + callf unlock_tables ; safe again +f5Dret: + ret + +; ***************************** +; *** DOS Function 5D03 *** +; *** Close files by machine*** +; ***************************** +; +; ***************************** +; *** DOS Function 5D04 *** +; *** Close by Machine/PSP *** +; ***************************** +f5D03: +f5D04: +;----- +; Close all files for given PSP +; + mov di,S_CLOSE_FILES + jmps f5D_common + + +; ***************************** +; *** DOS Function 5D05 *** +; ***************************** +; +f5D05: +; On Entry: +; RDC.BX = Share File # to look to +; RDC.CX = Share Record # to look for +; On Exit: +; AX = DOSHNDL Attribute Word +; BX = machine ID +; CX = locked blocks count +; ES:DI -> buffer containing full pathname +; +; + callf lock_tables ; protect SHARE with a critical section + callf share_stub+S_GET_LIST_ENTRY + callf unlock_tables ; safe again + jnc f5Dret ; just return if it went OK + jmp error_ret ; else return error code in AX + + +; ***************************** +; *** DOS Function 5D06 *** +; *** Get Internal Data *** +; ***************************** +; +f5D06: + mov cx,offset swap_indos ; Calculate Size of Swap + sub cx,offset internal_data ; Swap INDOS Array + call return_CX ; CX = Swap Indos length + mov dx,offset swap_always ; Calculate Size of Swap + sub dx,offset internal_data ; Swap ALWAYS Array + call return_DX ; DX = Swap Always length + mov si,offset internal_data + call return_DSSI + mov ax,5D06h + jmp return_AX_CLC + + +; +; ***************************** +; *** DOS Function 5D0A *** +; ***Set Extended Error Info*** +; ***************************** +; +f5D0A: + mov si,dx ; ES:SI -> parameter block + lods es:word ptr [si] + mov error_code,ax ; copy the appropriate fields + lods es:word ptr [si] + mov error_class,ah + mov error_action,al + lods es:word ptr [si] + mov error_locus,ah + add si,2*WORD ; skip to device + lods es:word ptr [si] + mov error_dev,ax + lods es:word ptr [si] + mov error_dev+2,ax + xor ax,ax ; return AL=0 + ret +; +; ***************************** +; *** Get switch character *** +; ***************************** +; +; + Public func37 +func37: + cmp al,1 ! jb f37_getswitch ; Get the current Switch Character + je f37_setswitch ; Set the Switch Character + cmp al,3 ! je f37_s03 ; Sub-Func 03 Return Unchanged + mov dl,0ffh ! jb f37_return_DX ; Sub-Func 02 Return DL == 0FFh + mov al,0FFh ; else invalid sub-function +f37_s03: + ret + +f37_getswitch: + mov dl,switch_char +f37_return_DX: + jmp return_DX ; return current setting in DX + +f37_setswitch: + mov switch_char,dl + ret + +;************************************************** +;************************************************** +;*** *** +;*** Miscellaneous Isolated Functions *** +;*** *** +;************************************************** +;************************************************** +; +; ***************************** +; *** DOS Function 30 *** +; *** Get Version Number *** +; ***************************** + + Public func30 +func30: +if DOS5 + mov es,current_psp ; version is kept in the PSP + mov ax,PSP_VERSION +else + mov ax,dos_version ; version returned in AX +endif +ReturnVersionNumber: + xor bx,bx ; zero BX and CX + xor cx,cx + call return_BX + call return_CX + jmp return_AX_CLC + +; +; ***************************** +; *** DOS Function 33 *** +; *** Get/Set Cntl-Break *** +; ***************************** + Public func33 + +; WARNING - called on USER stack + +func33: + cmp al,2 ; range check subfunction + jbe f33_10 + mov dl,bootDrv ; assume we want boot drive + cmp al,5 ; did we ? + je f33_30 +if DOS5 + cmp al,6 ; get true version ? + je f33_60 +endif + mov reg_AL[bp],0FFh ; return AL = FF + ret ; Illegal function request +f33_10: + and dl,01h ; force a valid value + cmp al,1 ; check for get or set + jae f33_20 + mov dl,break_flag ; it's a get, so use existing setting +f33_20: + xchg dl,break_flag ; replace current setting + je f33_40 +f33_30: + mov reg_DL[bp],dl ; return setting in DL +f33_40: + ret + +if DOS5 +f33_60: + mov reg_BX[bp],TRUE_VERSION ; return version number + mov ax,patch_version + mov reg_DX[bp],ax ; return revision+HMA + ret +endif + + +; +; ***************************** +; *** DOS Function 25 *** +; *** Set Interrupt Vector *** +; ***************************** +; + +; WARNING - use no stack as device drivers have called us re-entrantly + + Public func25 +func25: + mov bx,es ; is really dos_DS - save for later + xor di,di ; replace with the values in dos_DS:DX + mov es,di ; es -> zero segment + xor ah,ah ; the interrupt number + mov di,ax ; 0:di -> vector + shl di,1 ! shl di,1 ; 4 bytes per vector + + cli + xchg ax,dx ; Get New Offset + stosw ; and Save + xchg ax,bx ; Get New Segment + stosw ; and Save + sti + xchg ax,dx ; recover entry AL to (preserve it) + ret + +; ***************************** +; *** DOS Function 35 *** +; *** Get Interrupt Vector *** +; ***************************** + +; WARNING - use no stack as device drivers have called us re-entrantly + + Public func35 +func35: + xor bx,bx + mov ds,bx ; DS:0 -> vector table + mov bl,al ; BX = the interrupt number + shl bx,1 ! shl bx,1 ; 4 bytes per vector + lds bx,ds:dword ptr [bx] ; DS:BX -> vector + les di,ss:int21regs_ptr + mov es:reg_BX[di],bx + mov es:reg_ES[di],ds + jmp get_dseg ; restore DS for return + +;PC-DOS Verify and Break Flags Support +; +; ***************************** +; *** DOS Function 2E *** +; *** Set/Reset Verify *** +; ***************************** + Public func2E +func2E: + and al,1 ; only use bottom bit + mov verify_flag,al ; store for use later + ret + +; ***************************** +; *** DOS Function 54 *** +; *** Get Verify Setting *** +; ***************************** + Public func54 +func54: + mov al,verify_flag ; return verify flag + ret + +; ***************************** +; *** DOS Function 63 *** +; *** Get Lead Byte Table *** +; ***************************** +; + + + Public func63 +func63: + cmp al, 1 ; subfunction #? + jb f63_get_tbl ; subfunction 0 + je f63_set_flg ; subfunction 1 + cmp al, 2 ; subfunction 2? + je f63_get_flg ; yes + + mov ax, ED_FUNCTION ; invalid subfunction number + jmp error_exit ; so quit + + +f63_get_flg: +; Get the current state of the DOS interim character console flag. +; If this flag is set int 21h functions 07h, 08h, 0Bh, 0Ch are supposed +; to return "interim character information" which I assume is incomplete +; characters. (In languages like Korean a given double byte character +; may be built by the user entering several keystrokes which form +; incomplete characters.) + mov es, current_psp + mov dl, PSP_RIC ; Return Interim Character flag + jmp return_DX ; flag returned in dl + + +f63_set_flg: +; Set the current state of the DOS interim character console flag. +; dos_DL = 0 - clear flag, dos_DL = 1 - set flag + mov es, current_psp + mov PSP_RIC, dl ; record flag + ret + + +f63_get_tbl: +; Get the current DBCS table address. + mov si,offset DBCS_tbl+2; skip the table size entry +; jmp return_DSSI + +return_DSSI: +;----------- +; On Entry: +; DS:SI to be returned to caller +; On Exit: +; AX preserved +; + les di,ss:int21regs_ptr + mov es:reg_DS[di],ds + mov es:reg_SI[di],si + ret + +; +; ***************************** +; *** DOS Function 29 *** +; *** Parse String *** +; ***************************** + Public func29 +func29: +; +; Entry: +; DS:SI -> line to parse +; ES:DI -> resulting fcb +; Exit: +; DS:SI -> terminating delimeter past parsed filename +; ES:DI -> filled in fcb (Affects 16 bytes: DnnnnnnnnTTT0000) +; + push ds + push es + call reload_ES + pop ds + call parse + call return_DSSI ; return result of parse + pop ds + mov al,dh ; return result in AL + ret + +;----- +parse: ; parse DOS filename delimited by TAB,SPACE,or .,+:;=|"/\[]<> or ctrl +;----- +; Entry: +; DS:SI -> line to parse +; ES:DI -> fcb to parse into +; AL == bit options: +; Bit 0 == 1: scan off leading delimiters +; Bit 1 == 1: change drive only if specified +; Bit 2 == 1: change name " " " +; Bit 3 == 1: change type " " " +; Exit: +; DS:SI -> terminating delimeter past parsed filename +; ES:DI -> filled in fcb (Affects 16 bytes: DnnnnnnnnTTT0000) +; DH == 1 if wild, 0FFh if the drive is invalid, 0 otherwise +; + push di ; (<--keep DI last on stack) + + cld ; ChSh + xor dx,dx ; DH = default return value (0) + xchg al,dl ; put flags into DL, AL = 0 + + mov cx,1 + test dl,0010b ; should we initialize drive? + call nz_store_al ; do conditional store + + mov al,' ' ; use spaces for filename & typ + + mov cl,8 + test dl,0100b ; should we initialize the name? + call nz_store_al + + mov cl,3 + test dl,1000b ; should we initialize the typ? + call nz_store_al + + xor ax,ax ; zero-out the 4 post-typ bytes + stos ax + stos ax + + pop di ! push di ; restore DI to start of FCB + +deblank_loop: + lods al ; grab char + cmp al,' ' ; is it a blank? + je deblank_loop ; Y: keep looping + cmp al,'I'-'@' ; is it a tab? + je deblank_loop ; Y: keep looping + + test dl,0001b ; skip-delimiter-bit set? + jz parse_drive ; N: go start parsing + +skip_delim_loop: + call check_delimiters ; check AL for delimiterness + jb parse_dec_ret ; found terminator, dec SI & leave + mov dl,dh ; flag no-more-delimiter-skip (DL = 0) + je deblank_loop ; found separator, go deblank after it + +parse_drive: + dec si + cmp byte ptr 1[si],':' ; is the drive specified? + jne parse_name + lods ax ; get drive, junk colon + and al,01011111b ; upper case it + sub al,'@' ; AL = 1-relative drive # + push ax ! push ds ; Save the drive code and call + call get_dseg ; Restore our Data Segment + call valid_drive ; routine to validate drive ZR == OK + pop ds ! pop ax ; Restore drive code and User DS + jz parse_d10 + dec dh ; flag drive error (0FFh) +parse_d10: + mov es:[di],al ; insert drive in fcb + +parse_name: + inc di ; DI -> fname + mov cx,8 + call parse_item ; parse an up-to 8 char filename + cmp dl,'.' ; was the delimeter a '.'? + jne parse_dec_ret ; N: the parse is complete + + mov cl,3 + call parse_item ; parse an up-to 3 char filetype +parse_dec_ret: + dec si ; bump SI back to point to delimeter + +parse_ret: + pop di + ret + + +;----------- +nz_store_al: +;----------- +; Entry: +; DI -> destination to conditionally initialize +; CX == length of destination +; AL == byte to initialize with +; ZF set: do not initialize destination +; Exit: +; DI -> past destination (initial DI+CX) +; Changed: +; CX,DI +; + jnz skip_store ; should we initialize? + rep stosb ; Y: store them bytes +skip_store: + add di,cx ; bump DI to post-dest position + ret + + +;========== +parse_item: ; Parses item into fcb if item is specified +;========== +; +; Entry: +; SI -> item to parse (name or type) +; DI -> fcb area to parse it into +; CX == length of item +; DH == parse_return +; Exit: +; SI -> past ending delimeter +; DI -> past fcb area (initial DI + CX) +; CH == If zero on enter zero on exit else 0-255 +; DH == updated parse_return w/possible wild bit set +; DL == character delimiter @(SI-1) +; Changed: +; AX,CX,DX,SI,DI +; + + mov ah,FALSE ; specified item flag +parse_item_loop: + lods al ; get char + call check_delimiters ; is it a delimiter? + jbe pi_pad_ret ; Y: the parse is complete + jcxz parse_item_loop ; if the name is full, skip the char + mov ah,al ; flag name as present + cmp al,'?' ; is it a single wild char? + je pi_set_wild ; Y: set wild flag + cmp al,'*' ; is it a multi-char wild card? + jne pi_store ; N: store it + mov al,'?' ; Y: fill with '?' to end of name + rep stosb +pi_set_wild: + or dh,1 ; set wild flag + jcxz parse_item_loop ; skip store if name is now filled +pi_store: + dec cx ; another char done + call dbcs_lead ; is it the 1st byte of kanji ? + jne pi_store10 + inc si ; skip 2nd byte + jcxz parse_item_loop ; can I copy both ? + dec cx ; yes, do so + stosb + dec si ; point at second byte + lodsb ; so we can copy it too.. +pi_store10: + stos al ; put the char in the fcb + jmps parse_item_loop +pi_pad_ret: + mov dl,al ; DL = ending delimeter + or ah,ah ; the the item specified? + jz pi_ret ; N: skip padding + mov al,' ' ; Y: pad to end with spaces + rep stosb +pi_ret: + add di,cx ; bump DI out to end + ret + + +;---------------- +check_delimiters: +;---------------- +; +; Entry: +; AL == char to check in list of delimiters +; Exit: +; AL == char changed to uppercase +; CF set if it is one of the terminators: |"/\[]<> & ctrl chars != TAB +; ZF set if it is one of the separators: .,+:;= SPACE & TAB +; OR one of the non-ctrl terminators +; + + cmp al,'a' ; check for lower case + jb not_lower + cmp al,'z' + ja not_lower + and al,01011111b ; uppercase it, CF clear, ZF clear + ret +not_lower: + push cx ! push di ! push es + push cs ! pop es ; ES = Code segment + mov di,offset parse_separators + mov cx,length parse_separators + repne scasb ; is AL a separator? + je cpd_pop_ret ; Y: return ZF set + mov cl,length parse_terminators + repne scasb ; is AL a terminator? + stc ; (set CF if true) + je cpd_pop_ret ; Y: return CF & ZF set + cmp al,' ' ; (AL == ' ') ZF set, (AL < ' ') CF set +cpd_pop_ret: + pop es ! pop di ! pop cx + ret + +; +; ***************************** +; *** DOS Function 2A *** +; *** Get Current Date *** +; ***************************** + Public func2A +func2A: +; +; entry: None +; +; exit: cx = year (1980-2099) +; dh = month (1-12) +; dl = day (1-31) +; al = DOS returns day of week here +; + call ReadTimeAndDate ; Get the current Time and Date + mov cx,1980 + add cx,yearsSince1980 +; mov dl,dayOfMonth +; mov ah,month + mov dx,word ptr dayOfMonth + mov al,dayOfWeek + jmps f2C_10 ; exit via common routine + +; ***************************** +; *** DOS Function 2C *** +; *** Get Current Time *** +; ***************************** + Public func2C +func2C: +; +; entry: None +; +; exit: ch = hours (0-23) +; cl = minutes (0-59) +; dh = seconds (0-59) +; dl = Hunredths seconds (0-99) +; al = 0 +; + call ReadTimeAndDate ; Get the current Time and Date + mov cx,biosDate+2 ; Get the Hour and Minute + mov dx,biosDate+4 ; Get the Seconds and Hundredths + xor ax,ax ; return AL = 0 +f2C_10: + call return_CX ; and return to caller + jmp return_DX + + + +; ***************************** +; *** DOS Function 2B *** +; *** Set Current Date *** +; ***************************** + Public func2B +func2B: +; +; entry: cx = year (1980-2099) +; dh = month (1-12) +; dl = day (1-31) +; +; exit: al = 00H success +; = FFH failure +; + call ConvertDate ; Convert to BIOS date + jc f2B_20 ; Abort on Error + push cx ; save the converted date + call ReadTimeAndDate ; Get the current Time and Date + pop biosDate ; new date, existing time +f2B_10: ; Set the current Time and Date + call rw_clock_common ; make sure clock is there/setup regs + call device_write ; Update the Date and Time + xor ax,ax + ret + +f2B_20: + mov al,0FFh ; return FAILURE + ret + +; ***************************** +; *** DOS Function 2D *** +; *** Set Current Time *** +; ***************************** + Public func2D +func2D: +; +; entry: ch = hours (0-23) +; cl = minutes (0-59) +; dh = seconds (0-59) +; dl = hundredth seconds (0-99) +; +; exit: al = 00H success +; = FFH failure +; + cmp ch,23 ; Range check hours + ja f2B_20 + cmp cl,59 ; Range check minutes + ja f2B_20 + cmp dh,59 ; Range check seconds + ja f2B_20 + cmp dl,99 ; Range check hundredths + ja f2B_20 + push cx ; save hours/mins + push dx ; save secs/hundredths + call ReadTimeAndDate ; Get the current Time and Date + pop biosDate+4 ; leave the date alone + pop biosDate+2 ; but update the time + jmps f2B_10 ; Update the Date and Time + + + Public ReadTimeAndDate + +ReadTimeAndDate: ; Get the current Time and Date + call rw_clock_common ; make sure clock is there/setup regs + call device_read ; read the Date and Time + mov ax,biosDate ; get the BIOS date and convert + cmp ax,daysSince1980 ; (but only if necessary) + jne NewDate + ret + +NewDate: + mov daysSince1980,ax ; so we won't have to convert next time + inc ax ; Day number starting 1 Jan 1980 + mov cx,ax ; save day count + inc ax ; convert to a sunday as 1/1/80 is tues + xor dx,dx + mov bx,7 + div bx + mov dayOfWeek,dl ; save day of week + + xor dx,dx + mov ax,cx ; recover day count + + xor di,di ; assume zero leap days + sub ax,60 ; less than 60 days + jc no_leap_days ; means no leap days to subtract + mov bx,1461 ; 1461 = days in four years + div bx ; get number of leap years since 1980 + inc ax ; include 1980 + sub cx,ax ; normalize years to 365 days + mov di,ax ; save proper leap day count +no_leap_days: + + xor dx,dx + xchg ax,cx ; DX:AX = years since 1980 * 365 + mov bx,365 + div bx ; get number of years since 1980 + or dx,dx ; check for zero days left + jnz days_left + dec ax ; dec year count + mov dx,365 ; set day count to last day of last year +days_left: + + mov yearsSince1980,ax ; save the year + xchg ax,si ; save in SI + + xor bx,bx + mov cx,12 +get_month: ; find the appropriate month + cmp dx,totaldays[bx] + jbe got_month + inc bx ! inc bx + loop get_month +got_month: + shr bx,1 ; BX = month + mov month,bl + + dec bx + shl bx,1 ; BX = index to previous months + sub dx,totaldays[bx] ; get days into this month + + cmp bx,2 ; if it's FEB 29th we've lost a day + jne not_leap_yr ; check it's FEB + test si,3 + jnz not_leap_yr ; but is it a leap year ? + shr si,1 ! shr si,1 ; divide years by 4 + inc si ; include this year + cmp si,di ; compare against leap day adjustment + jne not_leap_yr + inc dx ; put 29th feb back again +not_leap_yr: + mov dayOfMonth,dl ; save the day of the month + ret + + +ConvertDate: + sub cx,1980 ; Base year is 1980 + jc xset_date_error + cmp cx,2100-1980 ; Year in valid range ? + jnc xset_date_error + mov bl,dh ; Month to BL + xor bh,bh + dec bx ; Adjust month to 0-11 + cmp bl,12 ; Month in valid range ? + jnc xset_date_error + mov al,dl ; Day of month + cbw + test cl,3 ; Leap year ? + jnz not_leap_year ; Jump if not + cmp dh,3 ; After February ? + cmc + adc al,ah ; Increment days in current year if so + cmp dl,29 ; Day of month 29 ? + jz day_valid ; Valid if so + +not_leap_year: + dec dx + cmp dl,monthdays[bx] ; Day of month within range for non-leap + ; year ? + jnc xset_date_error + +day_valid: + shl bx,1 + add ax,totaldays[bx] ; Get total days in current year + + push ax + + mov ax,365 + mul cx ; Convert year to days since 1-1-1980 + mov cx,ax + +; if total (ax) >= 60 (Feb 29 1980) then +; leap$days = (total - 60) / (365 * 4) + 1 + + sub ax,60 ; Before first leap year date + jc noleap ; Jump if so + mov bx,365*4 ; 4 years worth of days (365 * 4) + sub dx,dx + div bx ; Get number of leap years - 1 + inc ax + add cx,ax ; CX now has total days including leap + ; days + +noleap: + dec cx + + pop ax + + add cx,ax ; Get total days since 1-1-1980 + clc + ret + +xset_date_error: + stc + ret + +rw_clock_common: + mov cx,6 ; read/write 6 characters + mov dx,offset biosDate ; DX -> 6 byte buffer + les si,clk_device ; Get the address of the Clock Device + cmp si,-1 ; Has a valid device been selected + jne rw_clock_common10 + add sp,WORD ; discard near return address +rw_clock_common10: + ret + + +; ***************************** +; *** DOS Function 38 *** +; *** Get/Set Country Data *** +; ***************************** + Public func38 +func38: + xor ah,ah ; Generate 16 Bit country + cmp al,0FFh ; FF means country code in BX + jne f38_10 + xchg ax,bx ; AX = real country code +f38_10: + xchg ax,dx ; DX = country + test dx,dx ; dos_AL = 0 get the current country + jz f38_get + inc ax ; now check for dos_DX = FFFF + jz f38_set ; which means set country code + dec ax ; no, return buffer to normal +f38_get: + test dx,dx ; Get current? + jnz f38_g10 ; Yes + mov dx,cur_country ; use current country +f38_g10: +; look for (and if neccessary load) type 1 info into buffer + xchg ax,di ; ES:DI -> buffer + mov bx,cur_cp ; bx=codepage + call f38_get_info ; get info in current codepage + jnc f38_g20 + push ss ! pop ds + xor bx,bx ; now try any codepage + call f38_get_info ; if none for current codepage + jc f38_error ; No Match Found +f38_g20: + lea si,EXCI_CI_DATAOFF[si] ; point at CI_, not EXCI_ data + mov bx,CI_CODE[si] ; Return the selected country code + mov cx,CI_STATICLEN/2 + rep movsw + +if NLSFUNC + push ss + pop ds +; call get_dseg ; DS back to PCMODE +endif + call return_BX ; return country code in BX + xchg ax,bx + jmp return_AX_CLC ; and in AX + +f38_get_info: + push es ! push di ! push dx ; save pointer to buffer + mov al,1 ; Get data list seperators etc... + call f65_get_info ; DS:SI -> extended country info buffer + pop dx ! pop di ! pop es ; ES:DI -> users buffer + ret + +f38_set: + mov bx,cur_cp ; bx=codepage + and bx,f38_flag ; force CP to zero if 1st time here + call f38_set_country ; Update the Internal Data Structures + jc f38_error +f38_s20: + mov f38_flag,0FFFFh ; Country Code Set Successfully + mov ax,cur_country ; and return the current country + jmp return_AX_CLC ; to the user + + +f38_error: + +if NLSFUNC + push ss + pop ds +; call get_dseg ; DS back to PCMODE +endif + mov ax,ED_FILE ; This is the Error to return + jmp error_exit + + +f38_set_country: +; On Entry: +; BX = codepage +; DX = country +; On Exit: +; AX = error code +; preserve codepage/country info if there is an error (ie do type 1 last!) +; + mov al,2 ; Get uppercase & filename table + mov di,offset Ucasetbl + mov cx,info2_len + call f38_update + jc f38_seterr + mov al,4 ; Get uppercase & filename table + mov di,offset FileUcasetbl + mov cx,info4_len + call f38_update + jc f38_seterr + mov al,5 ; Get Legal file characters + mov di,offset FileCharstbl + mov cx,info5_len + call f38_update + jc f38_seterr + mov al,6 ; Get Collating table + mov di,offset Collatingtbl + mov cx,info6_len + call f38_update + jc f38_seterr + mov al,7 ; Get double byte character set table + mov di,offset DBCS_tbl + mov cx,info7_len + call f38_update + jc f38_seterr + mov al,1 ; Get data list seperators etc... + mov di,offset country_data ; do last since this updates + mov cx,info1_len ; cur_country/cur_cp + call f38_update +; jc f38_seterr +; clc + ret +f38_seterr: + mov ax,ED_FILE ; return file not found error + ret + +f38_update: + push ds ; save important registers + push bx ; codepage + push cx ; count for move + push dx ; country + push di ; destination offset for move + push ds ; destination segment + call f65_get_info ; DS:SI -> buffer with country info + pop es ; destination seg in ES + pop di ; ES:DI -> destination of move + pop dx ; country + pop cx ; bytes to move + pop bx ; codepage back again + jc f38_update10 ; any problems ? + rep movsb ; no, copy the data +f38_update10: + pop ds ; DS back to PCMDSEG + ret + +; ***************************** +; *** DOS Function 65 *** +; *** Extended Country Data *** +; ***************************** +; +;CODEPAGE equ 437 ; Return Standard Code Page +; +; Get Extended Country Code Sub-Functions +; +func65_dt dw 0FFFFh ; 00 Illegal Sub-Function + dw offset country_data ; 01 Extended Country Info + dw offset Ucasetbl ; 02 UpperCase Table + dw 0FFFFh ; 03 Invalid Subfunction + dw offset FileUcasetbl ; 04 FileName Upper Case Table + dw offset FileCharstbl ; 05 Valid Filename Characters + dw offset Collatingtbl ; 06 Collating Sequence + dw offset DBCS_tbl ; 07 DBCS Environment Vector +func65_dtl equ (offset $ - offset func65_dt)/2 + + Public func65 +func65: + cmp al,func65_dtl ; is sub-function 0-7 ? + jb func65_read_table + sub al,20h ; now check for 20-22 + jb f65_invalid + je func6520 ; it's upper case character + sub al,2 + je func6522 + jb func6521 + sub al,1 ; how about 6523 ? + jnz f65_invalid +; jmp func6523 + +func6523: +;-------- +; On Entry: +; DX = character to check +; On Exit: +; AX = 0, No +; AX = 1, Yes +; AX = 2, neither +; + push ds + pop es + mov di,offset NoYesChars ; 'NnYy' + cbw ; assume No (AX=0) + xchg ax,dx ; AX = char, DX = answer + call dbcs_lead ; is it 1st of a DBCS pair + jne func6523_10 + scasw ; check 'N' + je func6523_30 + inc dx ; assume Yes (DX=1) + scasw ; check 'Y' + jmps func6523_20 +func6523_10: + scasb ; check 'N' + je func6523_30 + scasb ; check 'n' + je func6523_30 + inc dx ; assume Yes (DX=1) + scasb ; check 'Y' + je func6523_30 + scasb ; check 'y' +func6523_20: + je func6523_30 + inc dx ; it's neither (DX=2) +func6523_30: + xchg ax,dx ; return result in AX + jmp return_AX_CLC ; Return the Code Page + +func6522: +;-------- +; Upper case ASCIIZ string at ES:DX + mov cx,0FFFFh ; calculate the length + mov di,dx ; of the string +; mov al,0 + repne scasb + not cx ; CX = length, including 0 +; jmp func6521 ; now use upper case CX bytes + +func6521: +;-------- +; Upper case string of CX bytes at ES:DX + mov si,dx + mov di,dx ; point SI & DI at string +f6521_10: + lods es:al ; read a character + call dbcs_lead ; is it 1st of a DBCS pair + jne f6521_20 + stosb ; store 1st byte of this pair + movs es:byte ptr [di],es:byte ptr [si] + ; copy 2nd byte + dec cx ; 1st byte of pair + loopnz f6521_10 ; go around for another one + ret ; time to go... +f6521_20: + call toupper ; upper case the character + stosb ; + loop f6521_10 ; go and do another one + ret + +func6520: +;-------- +; Upper case character DL + xchg ax,dx ; character in AX + call toupper ; upper case it + mov dl,al ; return in AL and DL + jmp return_DX ; set return code + +f65_invalid: +;----------- +; short jump to invalid function + jmp invalid_function + + +func65_read_table: +;----------------- + cmp cx,5 ; Check for valid buffer size + jb f65_invalid + cbw ; Get the request sub-function + mov si,ax ; into SI + shl si,1 + mov si,func65_dt[si] + inc si ; is SI = 0FFFFh + jz f65_invalid ; if so it's an invalid function + dec si + + cmp dx,0ffffh + jne f65_21 ; FFFF means + mov dx,cur_country ; use default country +f65_21: + cmp bx,0ffffh + jne f65_22 ; FFFF means + mov bx,cur_cp ; use default codepage +f65_22: + call f65_get_info ; DS:SI -> extended info for this pair + mov ax,ED_FILE ; On Error return File Not Found + jnc f65_23 ; for any error + push ss ! pop ds + jmp error_exit ; so Quit +f65_23: + les bx,ss:int21regs_ptr ; point to callers registers + mov ax,es:reg_AX[bx] ; get the subfunction number + mov cx,es:reg_CX[bx] ; this much data is requested + mov di,es:reg_DI[bx] ; Get the Parameter Block Offset + mov es,es:reg_ES[bx] ; and Segment + stosb ; fill in Info ID + cmp al,1 ; 1 is special - the rest + jne f65_30 ; want a DWORD ptr + cmp cx,EXCI_MAXLEN ; Check CX against the sub-function 1 + jbe f65_25 ; maximum and force CX to this value + mov cx,EXCI_MAXLEN ; if it is greater +f65_25: + call return_CX ; Return the number of bytes transfered + sub cx,EXI_DATA_LEN ; Adjust count for 3 byte header + mov ax,cx ! stosw ; fill in EXCI_LENGTH + push cx ; Save the count and copy as much + cmp cx,EXCI_STATLEN ; valid data a possible. IE at most + jbe f65_27 ; EXCI_STATLEN bytes + mov cx,EXCI_STATLEN +f65_27: + rep movsb ; just copy the data + pop cx ; Zero the rest of the data + sub cx,EXCI_STATLEN ; Skip if no space left in users + jbe f65_40 ; buffer otherwise STOSB + xor al,al ! rep stosb + jmps f65_40 + +; +; All function 65 sub-functions apart from 01 (Extended Country Info.) +; pass use this code to update the users parameter block. +; +f65_30: + mov cx,5 + call return_CX + mov ax,si ! stosw ; fill in the DWORD ptr to the data + mov ax,ds ! stosw +f65_40: + push ss + pop ds +; call get_dseg ; back to PCMDSEG + mov ax,cur_cp ; ##jc## Is the Requested or Current + jmp return_AX_CLC ; Return the Code Page + +; ***************************** +; *** DOS Function 66 *** +; ***Get/Set Global CodePage*** +; ***************************** +; + Public func66 +func66: + cbw + dec ax ! jz f66_10 ; AL = 1, Get the Current CodePage + dec ax ! jz f66_20 ; AL = 2, Set the Current CodePage + jmp invalid_function ; Illegal Sub-Function return an Error + +f66_10: ; Get the Current Code Page Info + mov bx,cur_cp ; Current CodePage + call return_BX + mov dx,SYS_CP ; System CodePage + jmp return_DX + +f66_20: ; Set the Current CodePage + mov dx,cur_country ; The Codepage has changed, so update + call f38_set_country ; Country Info and tables + jnc f66_30 ; Reset the Current CodePage if + mov ax,ED_FILE ; and return the error + jmp error_exit +f66_30: + mov bx,cur_cp ; select the new codepage + call f66_select_cp ; Prepare CodePage Devices + jnc f66_40 ; No Errors Skip Error Handler + mov ax,-65 ; Update Error Status do not generate + call error_ret ; a critical error but return + ; "access denied" to the application +f66_40: + ret + + +f65_get_info: +; On Entry: +; AL = info type +; BX = codepage (zero means any) +; DX = country +; On Exit: +; CY set if error +; DS:SI -> buffer with info in it +; +; NB. Remember to to Xlat fixups ! +; + cmp dx,cur_country ; is it default country ? + jne f65_p30 ; have we already got correct country ? + test bx,bx ; CP zero special case and we will + jz f65_p20 ; accept anything for this country + cmp bx,cur_cp ; otherwise is the codepage + jne f65_p30 ; in the default system ? +f65_p20: + cbw ; make info type a word + mov si,ax ; into index register + shl si,1 ; now a word offset + mov si,func65_dt[si] ; pick up offset of correct table + jmps f65_p90 +f65_p30: + push ax + call f65_locate_and_read ; get info into a buffer at DS:SI + pop ax + jc f65_p_exit +f65_p90: + cmp al,1 ; was it country info ? + jne f65_p95 ; no, skip the fixup + mov CI_CASEOFF+EXCI_CI_DATAOFF[si],offset xlat_xlat + mov CI_CASESEG+EXCI_CI_DATAOFF[si],ss +f65_p95: + clc +f65_p_exit: + ret + + +; +; ********************************************************************** +; *** Function 65 support - routines for seeking a country/codepage *** +; *** and loading the required information into the temp data area *** +; ********************************************************************** +; +; ************************************************** +; *** Open country.sys and search for the *** +; *** table of offsets for the given country/ *** +; *** codepage, read it in and exit. *** +; ************************************************** + +f65_locate_and_read: +; Locate and Read info AL for Country DX Codepage BX +if NLSFUNC + mov di,offset country_filename + ; point at pathname to country.sys + xchg ax,cx ; get info into CL + mov ax,14feh ; then call magic backdoor +nlsfunc_int2f: + stc ; assume an error + int 2fh ; to do the hard work + ret +else + push ax + call f65x_find_info ; Will need to load up the info + pop ax + jc f65_lr_exit ; so do it if we can. + + mov dx,offset f65xx_temp_area + mov cx,256 ; read 256 bytes into local buffer + push ax + call f65x_load_info ; Load required info + pop ax + jc f65_lr_exit + mov ah,MS_X_CLOSE ; All done so + mov bx,c_handle ; Close the file first + call dos_entry ; before leaving +; jc f65_lr_exit + mov si,offset f65xx_temp_area ; Tell subroutines where info is +f65_lr_exit: + ret +; +; Entry: dx=country code, bx=codepage +; Exit : carry set, and country.sys closed if failure +; country.sys open ready for more reads if success +; +f65x_find_info: + push es ; Save es + push ds + pop es ; Make es=ds + mov f65xx_country,dx + mov f65xx_codepage,bx + mov dx,offset country_filename + mov ax,(MS_X_OPEN*256)+0 ; Attempt to open country.sys + test dx,dx + stc + jz f65x_40 + call dos_entry ; Handle should come back in ax + jc f65x_40 +f65x_10: + mov c_handle,ax ; Save handle + mov dx,f65xx_country + cmp f65xx_code,dx ; do we already have the information? + jne f65x_30 ; No - get it from country.sys +f65x_20: + cmp f65xx_cp,bx ; Does codepage agree too? + je f65x_35 ; Yes so exit with no more ado +f65x_30: + mov dx,007Eh + xor cx,cx ; Seek within country.sys + mov bx,c_handle + mov ax,(MS_X_LSEEK*256)+0 ; seek from begining + call dos_entry + jc f65x_err + mov ah,MS_X_READ ; Now read the signature bytes and + mov bx,c_handle ; check them + mov cx,2 + mov dx,offset f65xx_sig + call dos_entry + jc f65x_err + cmp f65xx_sig,VALID_SIG + jne f65x_err ; If signature bad exit +f65x_32: + mov ah,MS_X_READ ; Read from country.sys header until + mov bx,c_handle ; Country/codepage found or NULL + mov cx,f65xx_ptable_len + mov dx,offset f65xx_code + call dos_entry + jc f65x_err + cmp f65xx_code,0 ; Found NULL so reqd combination + je f65x_err ; was not found + mov dx,f65xx_code ; Get the country/codepage values + mov bx,f65xx_cp ; read from Country.SYS + cmp dx,f65xx_country ; Check against the requested + jne f65x_32 ; Country. + cmp f65xx_codepage,0 ; If a codepage match is not + jz f65x_35 ; then return success + cmp bx,f65xx_codepage ; Check against the requested + jne f65x_32 ; Codepage +f65x_35: + mov f65xx_country,dx ; Force the Search Country and + mov f65xx_codepage,bx ; CodePage to be Updated +f65x_40: + pop es ; combination found so exit + ret + +f65x_err: + pop es + mov ah,MS_X_CLOSE ; On error close country.sys + mov bx,c_handle ; and set the carry flag before + call dos_entry ; leaving + stc + ret +; +; ************************************************** +; *** Load the type of information requested *** +; *** For the country currently active in the *** +; *** offset table *** +; ************************************************** +; +; Entry: al=type of info, dx=offset of buffer to read info into cx=no of bytes +; Exit : carry set, and country.sys closed if failure +; +f65x_load_info: + push es + push cx + push dx + push ds ; Make es=ds + pop es + dec al ; 1=Data , 2=uppercase, 4=fuppercase + sub bh,bh ; 5=filechars, 6=Collating table + mov bl,al ; 7=DBCS table + shl bx,1 ; Retrieve relevant offset + mov dx,f65xx_data[bx] + xor cx,cx ; Seek within country.sys + mov bx,c_handle + mov ax,(MS_X_LSEEK*256)+0 ; seek from begining + call dos_entry + pop dx ; Get buffer address back + pop cx ; and number of bytes to read + jc f65x_err + test ax,ax ; zero offset is a problem + jz f65x_err ; (probably DBCS with old COUNTRY.SYS) + mov ah,MS_X_READ ; Now read that info into our data area + mov bx,c_handle + call dos_entry ; Return when read is done + jc f65x_err + pop es + ret +endif + +; +; This function scans the complete device list and prepares +; all devices which support codepage. +; +; On Entry: +; BX = codepage +; On Exit: +; AX = error code + +DA_CODEPAGE equ DA_CHARDEV+DA_IOCTL+DA_GETSET + +f66_select_cp: +if NLSFUNC + mov ax,14ffh ; then call magic backdoor + jmps nlsfunc_int2f ; to do the hard work +else + push ds + mov f66_cp,bx ; Save requested CodePage + mov preperr,0000 ; Initialize Prepare Error + push ds ! pop es + mov bx,offset dev_root ; Get the Root of the Device List +f66_p10: ; Skip the NUL Device and check + lds bx,ds:DH_NEXT[bx] ; each character device for CodePage + cmp bx,0FFFFh ! jz f66_p50 ; Support. + mov ax,ds:DH_ATTRIB[bx] + and ax,DA_CODEPAGE ; Check for a Character Device which + cmp ax,DA_CODEPAGE ; supports IOCTL strings and GETSET + jne f66_p10 ; otherwise skip the device + + push bx + lea si,DH_NAME[bx] ; Found a matching device so + mov di,offset prepname ; open the device and select the + mov cx,8 ; requested codepage + +f66_p20: + lodsb + cmp al,' ' ! jz f66_p30 + stosb + loop f66_p20 + +f66_p30: + xor al,al ! stosb + mov ax,(MS_X_OPEN*256)+1 ; Open the device name for + mov dx,offset prepname ; Write Access + call dos_entry + jc f66_perr + mov bx,ax ; Save Device Handle in BX + + mov si,es:f66_cp ; Get Requested CodePage in SI + mov dx,offset cp_packet ; Offset of CodePage Struct + mov cx,006Ah ; Get Unknown CodePage + mov ax,(MS_X_IOCTL*256)+0Ch ; Generic IOCTL function + call dos_entry ; Make function Call + jc f66_p32 ; Error so Select requested Code Page + + cmp si,es:cp_cpid ! jz f66_p35 ; If this the currently selected +f66_p32: ; skip the select CodePage + mov es:cp_cpid,si + mov dx,offset cp_packet ; Offset of CodePage Struct + mov cx,004Ah ; Select Unkown CodePage + mov ax,(MS_X_IOCTL*256)+0Ch ; Generic IOCTL function + call dos_entry ; Make function Call + jnc f66_p35 ; No Error so skip the error +f66_p33: + mov es:preperr,ax ; save + +f66_p35: + mov ah,MS_X_CLOSE ; Close the device and check + call dos_entry ; for more devices to be prepared + jmps f66_p40 + +f66_perr: + mov es:preperr,ax ; Save the error code and try the +f66_p40: ; next device in the chain + pop bx ; Restore the Device offset + jmps f66_p10 ; and continue + +f66_p50: ; All device have been prepared + pop ds ; now return the last error code + mov ax,preperr ; in AX + or ax,ax + ret +endif + +PCMODE_DSIZE DSEG PARA + extrn swap_indos:word + +PCM_RODATA CSEG WORD +; +; Get Internal Data DOS function 5Dh +; +func5D_ft dw f5D00 + dw f5D01 ; Commit All + dw f5D02 ; Close File By Name + dw f5D03 ; Close All Host Files + dw f5D04 ; Close Process Host Files + dw f5D05 ; Get Open File List + dw f5D06 ; Get DOS Data Area + dw f5D_msnet ; f5D07 ; Get Truncate Flag used + ; with Redirected Dev I/O + dw f5D_msnet ; f5D08 ; Set Truncate Flag with + ; with Redirected Dev I/O + dw f5D_msnet ; f5D09 ; Close All Spool Streams + dw f5D0A ; Set Extended Error Info +func5D_ftl equ (offset $ - offset func5D_ft)/2 + dw invalid_function + +; +; Data used by the Binary format Time and Date routines +; +totaldays dw 0,31,59,90,120,151,181,212,243,273,304,334,0ffffh +monthdays db 31,28,31,30,31,30,31,31,30,31,30,31 + +parse_separators db TAB,'.,+:;=' +parse_terminators db '|"/\[]<>' + + +PCMODE_DATA DSEG WORD + extrn internal_data:word + extrn error_code:word + extrn error_class:byte + extrn error_action:byte + extrn error_locus:byte + extrn error_dev:word + + extrn indos_flag:word + extrn bootDrv:byte + extrn current_psp:word + extrn break_flag:byte + extrn dma_offset:word + extrn dma_segment:word + extrn fcb_search_buf:byte + extrn func52_data:byte ; Internal Data Table Area + extrn int21regs_ptr:dword + extrn lock_tables:dword + extrn unlock_tables:dword + extrn share_stub:dword + extrn remote_call:word ; set to FF if remote machine operation + extrn swap_always:word + extrn switch_char:byte + extrn owning_psp:word + extrn machine_id:word + extrn country_data:byte + extrn cur_country:word + extrn cur_cp:word + extrn verify_flag:byte + + extrn clk_device:dword ; Clock Device Driver Address + extrn biosDate:word + extrn daysSince1980:word + extrn yearsSince1980:word + extrn month:byte + extrn dayOfWeek:byte + extrn dayOfMonth:byte + extrn hour:byte + extrn minute:byte + extrn second:byte + extrn hundredth:byte +if DOS5 + extrn WindowsHandleCheck:byte +else + extrn win386_remote_machine:dword +endif + +SYS_CP equ 437 ; System CodePage + + +GLOBAL_DATA dseg word + +f38_flag dw 0 ; Country Code Selected Successfully + +if not NLSFUNC + extrn dev_root:dword + +f66_cp rw 1 ; INT21/66 Local Variable +cp_packet dw 2 ; Packet Size +cp_cpid dw 0 ; Request CodePage + db 0,0 ; Packet Terminators + +preperr rw 1 ; Prepare function Error Code +prepname rb 9 ; Reserved for ASCIIZ Device Name + +; +; Area for country.sys current pointer table +; (these are all offsets into country.sys) +; +f65xx_code rw 1 ; Country code +f65xx_cp rw 1 ; Code page + rw 1 ; +1 reserved +f65xx_data rw 1 ; Data area + rw 1 ; Upper case table + rw 1 ; +1 reserved + rw 1 ; Filename upper case table + rw 1 ; Legal file characters + rw 1 ; Collating table + rw 1 ; Double byte character set lead byte table +f65xx_ptable_len equ offset $ - offset f65xx_code + +f65xx_temp_area rb 256 ; Data area for extended country info +f65xx_codepage rw 1 +f65xx_country rw 1 +f65xx_sig rw 1 ; Signature +c_handle rw 1 + +endif ;not NLSFUNC + + end diff --git a/IBMDOS/MODFUNC.DEF b/IBMDOS/MODFUNC.DEF new file mode 100644 index 0000000..f92e8d5 --- /dev/null +++ b/IBMDOS/MODFUNC.DEF @@ -0,0 +1,328 @@ +; File : $MODFUNC.DEF$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +; +;****************************************************************; +;* *; +;* OS386 Inter-Module Function Definitions *; +;* *; +;****************************************************************; + +OS386_FUNC equ 2780h ; AX value +OS386_INT equ 02Fh ; interrupt number + + ; Module definitions +USER equ 0 +SUP equ 1 +RTM equ 2 +MEM equ 3 +DOM equ 4 +VM equ 5 +DPMI equ 6 +DPMS equ 7 +MIN_MODULE equ 5 +MAX_MODULE equ 15 + + ; Internal SUP functions +F_NotImp equ SUP + 0100h * 00 ; Function Not Implemented +F_Illegal equ SUP + 0100h * 01 ; Illegal Function +F_ModuleReg equ SUP + 0100h * 02 ; Register Module +F_SysDatAlloc equ SUP + 0100h * 03 ; allocate SYSDAT memory +F_SysDat equ SUP + 0100h * 04 ; return SYSDAT selector +F_MoveReal equ SUP + 0100h * 05 ; move real mode memory to protected mode +F_Reboot equ SUP + 0100h * 06 +F_Debug equ SUP + 0100h * 07 +F_ForeCheck equ SUP + 0100h * 08 ; Check for foreground +F_RegisterVxD equ SUP + 0100h * 09 ; Register VxD with system +F_UnloadVxD equ SUP + 0100h * 10 ; Unload VxD hook +F_PostInit equ SUP + 0100h * 11 ; end of initialisation phase +F_AllocWindow equ SUP + 0100h * 12 ; allocate a 4K mapping window +F_RegisterBoot equ SUP + 0100h * 13 ; register reboot addresses +F_EnquireBoot equ SUP + 0100h * 14 ; enquire if reboot active +F_GetDebugLevel equ SUP + 0100h * 15 ; get debug level +F_SetDebugLevel equ SUP + 0100h * 16 ; set debug level +F_Version equ SUP + 0100h * 17 ; version check +F_V86BPInstall equ SUP + 0100h * 18 ; install v86 break point +F_V86BPRemove equ SUP + 0100h * 19 ; remove v86 break point +F_V86BPOffer equ SUP + 0100h * 20 ; offer int 3 as v86 break point +F_LoaderCleanup equ SUP + 0100h * 21 ; offer the chance to cleanup +F_RegisterVxDWindow equ SUP + 0100h * 22 ; Register VxD mapping window +F_RegisterPNW equ SUP + 0100h * 23 ; Register PNW info + + ; Internal RTM functions +F_PDCount equ RTM + 0100h * 01 +F_FlgWait equ RTM + 0100h * 02 +F_FlgSet equ RTM + 0100h * 03 +F_QMake equ RTM + 0100h * 04 +F_QOpen equ RTM + 0100h * 05 +F_QDelete equ RTM + 0100h * 06 +F_QRead equ RTM + 0100h * 07 +F_CQread equ RTM + 0100h * 08 +F_QWrite equ RTM + 0100h * 09 +F_CQWrite equ RTM + 0100h * 10 +F_Delay equ RTM + 0100h * 11 +F_Dispatch equ RTM + 0100h * 12 +F_PTerm equ RTM + 0100h * 13 +F_PCreat equ RTM + 0100h * 14 +F_SetPrior equ RTM + 0100h * 15 +F_PDAddr equ RTM + 0100h * 16 +F_PAbort equ RTM + 0100h * 17 +F_Sleep equ RTM + 0100h * 18 +F_Wakeup equ RTM + 0100h * 19 +F_FindPDName equ RTM + 0100h * 20 +F_SetFlags equ RTM + 0100h * 21 +F_EndOfInterrupt equ RTM + 0100h * 22 ; Register PIC end of interrupt +F_NoAbort equ RTM + 0100h * 23 +F_OkAbort equ RTM + 0100h * 24 +F_FlagStatus equ RTM + 0100h * 25 +F_QRdMX equ RTM + 0100h * 26 +F_QWrMX equ RTM + 0100h * 27 +F_FlgAlloc equ RTM + 0100h * 28 +F_FlgFree equ RTM + 0100h * 29 +F_NumFlags equ RTM + 0100h * 30 +F_NDQRead equ RTM + 0100h * 31 +F_FlgWWTO equ RTM + 0100h * 32 +F_UdaAlloc equ RTM + 0100h * 33 +F_UdaFree equ RTM + 0100h * 34 +F_PFreeze equ RTM + 0100h * 35 +F_PThaw equ RTM + 0100h * 36 +F_CritEnter equ RTM + 0100h * 37 +F_CritExit equ RTM + 0100h * 38 +F_PCreate equ RTM + 0100h * 39 +F_PDList equ RTM + 0100h * 40 +F_PDToName equ RTM + 0100h * 41 +F_PDToStatus equ RTM + 0100h * 42 +F_PDToDomain equ RTM + 0100h * 43 +F_GetPrior equ RTM + 0100h * 44 +F_QDList equ RTM + 0100h * 45 +F_QDToName equ RTM + 0100h * 46 +F_QDToMsgLen equ RTM + 0100h * 47 +F_QDToMaxMsgs equ RTM + 0100h * 48 +F_QDToNqPD equ RTM + 0100h * 49 +F_QDToDqPD equ RTM + 0100h * 50 +F_QDToNumMsgs equ RTM + 0100h * 51 +F_QDToFlags equ RTM + 0100h * 52 +F_NameToQD equ RTM + 0100h * 53 +F_NameToPD equ RTM + 0100h * 54 +F_MutexAlloc equ RTM + 0100h * 55 +F_MutexFree equ RTM + 0100h * 56 +F_MutexEnter equ RTM + 0100h * 57 +F_MutexCEnter equ RTM + 0100h * 58 +F_MutexExit equ RTM + 0100h * 59 +F_Slice equ RTM + 0100h * 60 +F_TickLength equ RTM + 0100h * 61 +F_ProcessID equ RTM + 0100h * 62 +F_QClose equ RTM + 0100h * 63 +F_QDispose equ RTM + 0100h * 64 +F_PDToFlags equ RTM + 0100h * 65 +F_PDToDParam equ RTM + 0100h * 66 +F_ReleaseMX equ RTM + 0100h * 67 +F_SimulateInt equ RTM + 0100h * 68 +F_SetQFlags equ RTM + 0100h * 69 +F_TickRate equ RTM + 0100h * 70 + + ; Internal MEMORY functions +F_PdirGet equ MEM + 0100h * 01 +F_PdirSet equ MEM + 0100h * 02 +F_PageAlloc equ MEM + 0100h * 03 +F_RealAllocG equ MEM + 0100h * 04 +F_RealAllocI equ MEM + 0100h * 05 +F_PtblRead equ MEM + 0100h * 06 +F_PtblWrite equ MEM + 0100h * 07 +F_PageGet equ MEM + 0100h * 08 +F_PageSet equ MEM + 0100h * 09 +F_PagesAlloc equ MEM + 0100h * 10 +F_PageFree equ MEM + 0100h * 11 +F_MemAlloc equ MEM + 0100h * 12 +F_MemFree equ MEM + 0100h * 13 +F_MemSize equ MEM + 0100h * 14 +F_MemResize equ MEM + 0100h * 15 +F_DescAlloc equ MEM + 0100h * 16 +F_DescFree equ MEM + 0100h * 17 +F_DescGet equ MEM + 0100h * 18 +F_DescSet equ MEM + 0100h * 19 +F_DescMemAlloc equ MEM + 0100h * 20 +F_DescMemFree equ MEM + 0100h * 21 +F_DescMemSize equ MEM + 0100h * 22 +F_DescMemResize equ MEM + 0100h * 23 +F_PageLock equ MEM + 0100h * 24 +F_PageUnlock equ MEM + 0100h * 25 +F_PageLockAny equ MEM + 0100h * 26 +F_PageUnlockReuse equ MEM + 0100h * 27 +F_PageLockNone equ MEM + 0100h * 28 +F_PageUnlockNone equ MEM + 0100h * 29 +F_CallRealRaw equ MEM + 0100h * 30 ; Call real mode (SS:ESP supplied) +F_IntRealRaw equ MEM + 0100h * 31 ; Do real mode interrupt (SS:ESP supplied) +F_CallReal equ MEM + 0100h * 32 ; Call real mode with RETF frame +F_IntReal equ MEM + 0100h * 33 ; Do real mode interrupt +F_PagedCallReal equ MEM + 0100h * 34 ; Paged real mode call +F_PagedIntReal equ MEM + 0100h * 35 ; Paged real mode interrupt +F_CallIretReal equ MEM + 0100h * 36 ; Call real mode with IRET frame +F_CallIretRealRaw equ MEM + 0100h * 37 ; Call real mode with IRET frame (SS:ESP supplied) +F_CallProt16 equ MEM + 0100h * 38 ; Call protected mode 16 bit code +F_CallProt32 equ MEM + 0100h * 39 ; Call protected mode 32 bit code +F_IAddPage equ MEM + 0100h * 40 ; add kernel instance data +F_BankPageLock equ MEM + 0100h * 41 +F_BankPageUnlock equ MEM + 0100h * 42 +F_BankPageLockAny equ MEM + 0100h * 43 +F_BankPageUnlockReuse equ MEM+0100h * 44 +F_BankPageLockNone equ MEM + 0100h * 45 +F_BankPageUnlockNone equ MEM+ 0100h * 46 +F_GateAlloc equ MEM + 0100h * 47 +F_GateFree equ MEM + 0100h * 48 +F_MemTotalFree equ MEM + 0100h * 49 +F_AddressSpace equ MEM + 0100h * 50 +F_MemTotal equ MEM + 0100h * 51 +F_DescRead equ MEM + 0100h * 52 +F_DescWrite equ MEM + 0100h * 53 +F_GetStack equ MEM + 0100h * 54 +F_SetStack equ MEM + 0100h * 55 + + ; Internal DOMain functions + +F_DAlloc equ DOM + 0100h * 00 ; create a new domain +F_DFree equ DOM + 0100h * 01 ; free up a domain +F_DGet equ DOM + 0100h * 02 ; get current domain +F_DSet equ DOM + 0100h * 03 ; switch to another domain +F_SWIntHandler equ DOM + 0100h * 04 ; Install Software Interrupt handler +F_PFaultHandler equ DOM + 0100h * 05 ; Install Page Fault handler +F_IOExHandler equ DOM + 0100h * 06 ; Install I/O Exception handler +F_GenExHandler equ DOM + 0100h * 07 ; Install General Exception handler +F_HWIntHandler equ DOM + 0100h * 08 ; Install HW int handler +F_IOBitGet equ DOM + 0100h * 09 ; Get domain IO bitmap +F_IOBitSet equ DOM + 0100h * 10 ; Set domain IO bitmap +F_BankIOBitGet equ DOM + 0100h * 11 ; Get domain banked IO bitmap +F_BankIOBitSet equ DOM + 0100h * 12 ; Set domain banked IO bitmap +F_BankMemGet equ DOM + 0100h * 13 ; Read domain banked memory +F_BankMemSet equ DOM + 0100h * 14 ; Write domain banked memory +F_BankPageGet equ DOM + 0100h * 15 ; Get domain banked page table entry +F_BankPageSet equ DOM + 0100h * 16 ; Set domain banked page table entry +F_RegInstData equ DOM + 0100h * 17 ; register DOS instance data +F_NProcesses equ DOM + 0100h * 18 ; Get number of processes in domain +F_DFreeze equ DOM + 0100h * 19 ; Suspend domain +F_DThaw equ DOM + 0100h * 20 ; Unsuspend domain +F_DFork equ DOM + 0100h * 21 ; Fork domain +F_DAbort equ DOM + 0100h * 22 ; Abort all processes in domain +F_UnlinkHandler equ DOM + 0100h * 23 ; Uninstall a handler +F_HWIntDfltHandler equ DOM + 0100h * 24 ; Install HW int default handler +F_VHWIntHandler equ DOM + 0100h * 25 ; Install Virtual HW int handler +F_VHWIntDfltHandler equ DOM + 0100h * 26 ; Install Virtual HW int default handler +F_SwapInHandler equ DOM + 0100h * 27 ; Install process swap in handler +F_SwapOutHandler equ DOM + 0100h * 28 ; Install process swap out handler +F_DosStartup equ DOM + 0100h * 29 ; Statup a DOS session +F_DosShutdown equ DOM + 0100h * 30 ; Terminate a DOS session +F_PCreateHandler equ DOM + 0100h * 31 ; Install process create handler +F_PDeleteHandler equ DOM + 0100h * 32 ; Install process terminate handler +F_RootPD equ DOM + 0100h * 33 ; Get Domain Root Process +F_DForeground equ DOM + 0100h * 34 ; Domain has just switched to foreground +F_DBackground equ DOM + 0100h * 35 ; Domain will be switching to background +F_MapHMA equ DOM + 0100h * 36 ; Map Domains HMA +F_AddInstData equ DOM + 0100h * 37 ; add DOS instance data +F_DMemFree equ DOM + 0100h * 38 ; get memory available to this domain +F_DMemTotal equ DOM + 0100h * 39 ; get memory allocated to this domain +F_DGetMemLimit equ DOM + 0100h * 40 ; get limit on local memory allocations +F_DSetMemLimit equ DOM + 0100h * 41 ; set limit on local memory allocations +F_ReflectInt21 equ DOM + 0100h * 42 ; support for protected mode Int 21's +F_DTestRegion equ DOM + 0100h * 43 ; test region for global/local memory +F_Switcher equ DOM + 0100h * 44 ; make task switcher call +F_HandlerCleanup equ DOM + 0100h * 45 ; debugger hook - remove all handlers for a selector +F_DFlagGet equ DOM + 0100h * 46 ; get Domain Flags +F_DFlagSet equ DOM + 0100h * 47 ; set Domain Flags +F_DSwitchHandler equ DOM + 0100h * 48 ; Install domain switch handler +F_GIOExHandler equ DOM + 0100h * 49 ; Install Global I/O Exception handler + +;------------ + +; VM Functions + +F_VMProtInit equ VM + 0100h * 00 ; Protected Mode initialisation internal) + +F_LoadMT equ VM + 0100h * 01 ; Load MultiTasking +F_UnloadMT equ VM + 0100h * 02 ; Unload MultiTasking +F_ConsoleFree equ VM + 0100h * 03 ; Save Console if enabled, then free it +F_ConsoleGet equ VM + 0100h * 04 ; Get Console, then restore if enabled +F_ConsoleSaveEnable equ VM +0100h * 05 ; Enable Console save/restore +F_ConsoleSaveDisable equ VM +0100h * 06 ; Disable Console save/restore + +F_TMInit equ VM + 0100h * 07 ; Task Manager Init +F_GetKey equ VM + 0100h * 08 ; Domain Manager to Keyboard Handler +F_KeyScanEnable equ VM + 0100h * 09 ; Enable hotkey scanning +F_KeyScanDisable equ VM + 0100h * 10 ; Disable hotkey scanning +F_ConsoleOwner equ VM + 0100h * 11 ; Get console owner domain id +F_DMAHandlerEnable equ VM + 0100h * 12 ; Re-enable DMA address translation +F_DMAHandlerDisable equ VM + 0100h * 13 ; Disable DMA address translation +F_SetSerialTimeout equ VM + 0100h * 14 ; Set Serial Port Timeout +F_SetParallelTimeout equ VM+ 0100h * 15 ; Set Parallel Port Timeout +F_VCPIEntry equ VM + 0100h * 16 ; Domain is going into VCPI mode +F_VCPIExit equ VM + 0100h * 17 ; Domain has probably come out of VCPI mode +F_SetGlobalMsgMode equ VM + 0100h * 18 ; Enter global message display mode +F_DisplayGlobalMsg equ VM + 0100h * 19 ; Ditto, plus display message +F_ExitGlobalMsgMode equ VM + 0100h * 20 ; Exit global message display mode +F_SetDomainMsgMode equ VM + 0100h * 21 ; Enter domain message display mode +F_DisplayDomainMsg equ VM + 0100h * 22 ; Ditto, plus display message +F_ExitDomainMsgMode equ VM + 0100h * 23 ; Exit domain message display mode +F_DisplayFatalMsg equ VM + 0100h * 24 ; Display fatal message +F_SetSerialBase equ VM + 0100h * 25 ; Set Serial port base address +F_SetParallelBase equ VM + 0100h * 26 ; Set Parallel port base address +F_SetSerialIRQ equ VM + 0100h * 27 ; Set Serial port IRQ number +F_SetParallelIRQ equ VM + 0100h * 28 ; Set Parallel port IRQ number +F_ResetVideo equ VM + 0100h * 29 ; EMERGENCY reset of the video system +F_SetMouseIRQ equ VM + 0100h * 30 ; Set mouse IRQ +F_CheckNotIdle equ VM + 0100h * 31 ; Check if we are idle or not +F_GetMouseInfo equ VM + 0100h * 32 +F_GetSerialOwner equ VM + 0100h * 33 +F_GetSerialTimeout equ VM + 0100h * 34 +F_GetParallelOwner equ VM + 0100h * 35 +F_GetParallelTimeout equ VM+ 0100h * 36 + +LAST_VM_FUNC equ 36 + +;------------ + +; DPMI Functions + +; These "DPMI" functions are those that are provided by the DPMI module via the +; Vladivar interface. True DPMI functions should be accessed via int 31h as per +; the DPMI spec. + +F_InitDPMI equ DPMI + 0100h * 0 ; used internally by DPMI. Do not call. +F_DescAllocLDT equ DPMI + 0100H * 1 ; allocate an LDT descriptor +F_DescFreeLDT equ DPMI + 0100H * 2 ; free an LDT descriptor +F_DescGetLDT equ DPMI + 0100H * 3 ; same as F_DescGet, but for LDT +F_DescSetLDT equ DPMI + 0100H * 4 ; same as F_DescSet, but for LDT +F_DescAllocInt21 equ DPMI + 0100H * 5 ; allocate an LDT descriptor for pmode + ; int 21 memory allocation. +F_WhereIsDPMI equ DPMI + 0100H * 6 ; return address of DPMI global data + +LAST_DPMI_FUNC equ 6 + diff --git a/IBMDOS/MSDOS.EQU b/IBMDOS/MSDOS.EQU new file mode 100644 index 0000000..548d17c --- /dev/null +++ b/IBMDOS/MSDOS.EQU @@ -0,0 +1,130 @@ +; File : $MSDOS.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG + + +MS_P_TERMCPM equ 00H +MS_C_READ equ 01H +MS_C_WRITE equ 02H +MS_A_READ equ 03H +MS_A_WRITE equ 04H +MS_L_WRITE equ 05H +MS_C_RAWIO equ 06H +MS_C_RAWIN equ 07H +MS_C_NOECHO equ 08H +MS_C_WRITESTR equ 09H +MS_C_READSTR equ 0aH +MS_C_STAT equ 0bH +MS_C_FLUSH equ 0cH +MS_DRV_ALLRESET equ 0dH +MS_DRV_SET equ 0eH +MS_F_OPEN equ 0fH +MS_F_CLOSE equ 10H +MS_F_SFIRST equ 11H +MS_F_SNEXT equ 12H +MS_F_DELETE equ 13H +MS_F_READ equ 14H +MS_F_WRITE equ 15H +MS_F_MAKE equ 16H +MS_F_RENAME equ 17H +MS_DRV_GET equ 19H +MS_F_DMAOFF equ 1aH +MS_DRV_ALLOC equ 1bH +MS_DRV_ALLOCSPEC equ 1cH +MS_F_READRAND equ 21H +MS_F_WRITERAND equ 22H +MS_F_SIZE equ 23H +MS_F_RANDREC equ 24H +MS_S_SETINT equ 25H +MS_P_MKPSP equ 26H +MS_F_READBLK equ 27H +MS_F_WRITEBLK equ 28H +MS_F_PARSE equ 29H +MS_T_GETDATE equ 2aH +MS_T_SETDATE equ 2bH +MS_T_GETTIME equ 2cH +MS_T_SETTIME equ 2dH +MS_F_VERIFY equ 2eH +MS_F_DMAGET equ 2fH +MS_S_BDOSVER equ 30H +MS_P_TERMKEEP equ 31H +MS_S_BREAK equ 33H +MS_S_GETINT equ 35H +MS_DRV_SPACE equ 36H +MS_S_COUNTRY equ 38H +MS_X_MKDIR equ 39H +MS_X_RMDIR equ 3aH +MS_X_CHDIR equ 3bH +MS_X_CREAT equ 3cH +MS_X_OPEN equ 3dH +MS_X_CLOSE equ 3eH +MS_X_READ equ 3fH +MS_X_WRITE equ 40H +MS_X_UNLINK equ 41H +MS_X_LSEEK equ 42H +MS_X_CHMOD equ 43H +MS_X_IOCTL equ 44H +MS_X_DUP equ 45H +MS_X_DUP2 equ 46H +MS_X_CURDIR equ 47H +MS_M_ALLOC equ 48H +MS_M_FREE equ 49H +MS_M_SETBLOCK equ 4aH +MS_X_EXEC equ 4bH +MS_X_EXIT equ 4cH +MS_X_WAIT equ 4dH +MS_X_FIRST equ 4eH +MS_X_NEXT equ 4fH +MS_P_SETPSP equ 50H +MS_F_GETVERIFY equ 54H +MS_X_RENAME equ 56H +MS_X_DATETIME equ 57H +MS_M_STRATEGY equ 58h +MS_F_ERROR equ 59H +MS_X_MKTEMP equ 5aH +MS_X_MKNEW equ 5bH +MS_F_LOCK equ 5cH +MS_X_EXPAND equ 60H +MS_P_GETPSP equ 62H +MS_X_GETCP equ 6601h +MS_X_SETCP equ 6602h +MS_X_SETHC equ 67h +MS_X_COMMIT equ 68h + +DOS_INT equ 21h ; DOS Entry Point +; +STDIN equ 0 ; Standard Console Input Handle +STDOUT equ 1 ; Standard Console Output Handle +STDERR equ 2 ; Standard Error Output +STDAUX equ 3 ; Auxilary Device Handle +STDPRN equ 4 ; Printer Device Handle diff --git a/IBMDOS/MSERROR.EQU b/IBMDOS/MSERROR.EQU new file mode 100644 index 0000000..4a90079 --- /dev/null +++ b/IBMDOS/MSERROR.EQU @@ -0,0 +1,122 @@ +; File : $MSERROR.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG + +ED_FUNCTION equ -01 ; invalid function number +ED_FILE equ -02 ; file not found +ED_PATH equ -03 ; path not found +ED_HANDLE equ -04 ; too many open files +ED_ACCESS equ -05 ; file access denied +ED_H_MATCH equ -06 ; invalid handle number +ED_DMD equ -07 ; memory descriptor destroyed +ED_MEMORY equ -08 ; insufficient memory +ED_BLOCK equ -09 ; invalid memory block addr +ED_ENVIRON equ -10 ; invalid environment +ED_FORMAT equ -11 ; invalid format +ED_ACC_CODE equ -12 ; invalid access code +ED_DATA equ -13 ; invalid data +ED_DRIVE equ -15 ; invalid drive specified +ED_DIR equ -16 ; can't remove current dir +ED_DEVICE equ -17 ; not same device +ED_ROOM equ -18 ; no more files + +ED_PROTECT equ -19 ; disk write protected +ED_BADUNIT equ -20 ; invalid drive specified +ED_NOTREADY equ -21 ; drive doesn't respond +ED_BADCMD equ -22 ; invalid command to driver +ED_BADDATA equ -23 ; data CRC error +ED_BADRHLEN equ -24 ; (shouldn't happen) +ED_BADSEEK equ -25 ; can't seek to track +ED_BADMEDIA equ -26 ; unrecognizable medium +ED_RNF equ -27 ; record/sector not found +ED_NOPAPER equ -28 ; printer error +ED_WRFAIL equ -29 ; write failed +ED_RDFAIL equ -30 ; read failed +ED_GENFAIL equ -31 ; anything failed +ED_SHAREFAIL equ -32 ; sharing conflict +ED_LOCKFAIL equ -33 ; locking conflict +ED_DISKCHG equ -34 ; invalid disk change +ED_NOFCBS equ -35 ; FCB table exhausted +ED_NOLOCKS equ -36 ; lock list items exhausted +ED_NET equ -50 ; Network Request Not Supported + +ED_NETACCESS equ -65 ; file access denied + +ED_NETPWD equ -73 ; Server Password Error +ED_NETVER equ -74 ; Incorrect Server version +ED_NETREQ equ -75 ; No Local Network Resources +ED_NETTIME equ -76 ; Network Time Out Error +ED_NETCOMM equ -77 ; Network Communications Error +ED_NETSRVR equ -78 ; No Server Network Resources +ED_NETLOG equ -79 ; Server Not Logged In + +ED_EXISTS equ -80 ; file already exists +ED_MAKE equ -82 ; Cannot Make (Files ??) +ED_FAIL equ -83 ; FAIL code returned from INT 24 +ED_STRUCT equ -84 ; Out of Structures +ED_ASSIGN equ -85 ; Already Assigned +ED_PASSWORD equ -86 ; Invalid Password +ED_PARAM equ -87 ; Invalid Parameter +ED_NETWRITE equ -88 ; Network write fault +ED_NETFUNC equ -89 ; Function not supported on network +ED_COMPONENT equ -90 ; system component not installed +ED_LASTERROR equ -90 ; Last Error Number Used + + +CLASS_RESOURCE equ 1 ; Out of Resource +CLASS_TEMP equ 2 ; Temporary Situation +CLASS_AUTHOR equ 3 ; Authorization Error +CLASS_INTERNAL equ 4 ; Internal System Software Error +CLASS_HARDWARE equ 5 ; Hardware Failure +CLASS_SYSTEM equ 6 ; Serious System Failure +CLASS_APPLIC equ 7 ; Application Program Error +CLASS_LOST equ 8 ; File/Item Not Found +CLASS_FORMAT equ 9 ; File/Item Illegal Format +CLASS_LOCKED equ 10 ; File/Item Locked +CLASS_MEDIA equ 11 ; Media Failure +CLASS_EXISTS equ 12 ; Item Already Exists +CLASS_UNKNOWN equ 13 ; Unknown Classification + +ACT_RETRY equ 1 ; Retry a few times then prompt user +ACT_DELAY equ 2 ; Delay then as ACT_RETRY +ACT_USER equ 3 ; Prompt user to re-enter data +ACT_ABORT equ 4 ; Clean Up then ABORT the process +ACT_TERM equ 5 ; Terminate immeadiately NO CLEAN UP +ACT_IGNORE equ 6 ; Ignore the Error +ACT_URETRY equ 7 ; Retry the error after user intervention + +LOC_UNKNOWN equ 1 ; Unknown error location +LOC_BLOCK equ 2 ; Block Device Failure +LOC_NET equ 3 ; Network Failure +LOC_CHAR equ 4 ; Related to Serial/Character devices +LOC_MEMORY equ 5 ; Failure related to Memory diff --git a/IBMDOS/NETWORK.A86 b/IBMDOS/NETWORK.A86 new file mode 100644 index 0000000..613938b --- /dev/null +++ b/IBMDOS/NETWORK.A86 @@ -0,0 +1,151 @@ +; File : $NETWORK.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; ENDLOG +; +; DOS Network Function Calls + + include pcmode.equ + include i:mserror.equ + include i:redir.equ + include i:doshndl.def + +PCM_CODE CSEG BYTE + + extrn reload_ES:near + extrn return_AX_CLC:near + extrn return_CX:near + extrn error_exit:near + extrn get_ldt_raw:near + +; ***************************** +; *** DOS Function 5E *** +; *** Get Machine Name *** +; ***************************** +; + Public func5E +func5E: + cmp al,1 ! jb f5E00 ; Get Machine Name Sub-Function + je f5E01 ; Set Machine Name Sub-Function + mov ax,I2F_REDIR_5E ; magic int 2F number + jmp func5F_common ; use common routine +; +; Get the current Machine Name +; +f5E00: + mov di,dx ; Copy the 15 Byte Network Name + mov si,offset net_name + mov cx,16/2 + rep movsw +; mov ch,name_num ; 00 -> Undefined Name +; mov cl,netbios ; 00 -> Name Number + mov cx,word ptr netbios + call return_CX +f5E_success: + xor ax,ax ; return zero + jmp return_AX_CLC + +; +; Set the Network Name +; +f5E01: +; mov name_num,ch ; Get the Network and NetBios Nos. +; mov netbios,cl ; and save in local variables + mov word ptr netbios,cx + inc net_set_count + push ds ! push es + pop ds ! pop es ; Copy the specified name + mov si,dx ; to internal save area + mov di,offset net_name + mov cx,15 ; Copy 15 byte name leave + rep movsb ; Terminating 00 + push es ! pop ds + jmps f5E_success + + +; ***************************** +; *** DOS Function 5F *** +; *** Network Control *** +; ***************************** +; + Public func5F +func5F: + cmp al,07h + je func5F_10 + cmp al,08h + jne func5F_40 +func5F_10: + push ax + mov al,dl + call get_ldt_raw + pop ax + jc func5F_30 + cmp es:word ptr LDT_PDT[bx],1 + jb func5F_30 + or es:byte ptr LDT_FLAGS+1[bx],LFLG_PHYSICAL/100h + cmp al,07h + je func5F_30 + and es:byte ptr LDT_FLAGS+1[bx],(not LFLG_PHYSICAL)/100h +func5F_30: + jnc func5F_OK + mov ax,ED_DRIVE + jmp error_exit + +func5F_40: + mov ax,I2F_REDIR_5F ; magic int 2F number + +Public func5F_common +func5F_common: + push ds + push int21AX ; AX passed on the stack.. + push es + call reload_ES ; get the segment registers + pop ds ; back to entry state + stc ; assume it will fail + int 2fh ; pass it on to MSNET + pop ds ; throw away word on the stack + pop ds + jc func5F_error +func5F_OK: + jmp return_AX_CLC ; return the result +func5F_error: + neg ax ; our error convention is negative.. + jmp error_exit ; Error for all sub functions + +PCMODE_DATA DSEG WORD + + extrn net_name:byte + extrn net_set_count:byte + extrn name_num:byte + extrn netbios:byte + extrn int21AX:word + +end diff --git a/IBMDOS/PATCH.COD b/IBMDOS/PATCH.COD new file mode 100644 index 0000000..1778bc5 --- /dev/null +++ b/IBMDOS/PATCH.COD @@ -0,0 +1,104 @@ +; File : $PATCH.COD$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +;***************************************************** +;* +;* PATCH AREA -- 256 bytes long +;* +;***************************************************** + +patch: + + nop ! nop ! nop ! nop ! nop ! nop ;00-0f + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;10-1f + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;20-2f + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;30-3f + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;40-4f + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;50-5f + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;60-6f + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;70-7f + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;80-8f + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;90-9f + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;a0-af + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;b0-bf + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;c0-cf + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;d0-df + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;e0-ef + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop + + nop ! nop ! nop ! nop ! nop ! nop ;f0-ff + nop ! nop ! nop ! nop ! nop ! nop + nop ! nop ! nop ! nop diff --git a/IBMDOS/PCMIF.A86 b/IBMDOS/PCMIF.A86 new file mode 100644 index 0000000..a940e99 --- /dev/null +++ b/IBMDOS/PCMIF.A86 @@ -0,0 +1,1028 @@ +; File : $PCMIF.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log: $ +; PCMIF.A86 1.21 93/09/09 22:36:50 +; Int 21/59 uses error stack +; PCMIF.A86 1.20 93/08/27 18:56:30 +; Int 25/26 32 bit sector detection +; PCMIF.A86 1.19 93/07/22 19:30:54 +; chnage int 25/26 support for NDD +; PCMIF.A86 1.18 93/07/20 22:47:54 +; Even fewer checks on int 25/26 +; PCMIF.A86 1.14 93/05/06 19:28:31 +; Move int 23/28 support to CIO. +; PCMIF.A86 1.13 93/05/05 23:31:0 +; int 2A/84 is now only generated on input-and-wait functions +; PCMIF.A86 1.12 93/03/25 15:06:48 +; tweak int21 entry +; ENDLOG +; +; 24 Aug 87 The CARRY flag is now preserved for all DOS functions below +; 038h Get/Set Country Code. +; 04 Sep 87 Display the Interrupt Number and Registers when an illegal +; software interrupt is executed by an application. This +; is disabled by DBG OFF. +; 09 Sep 87 DDIO interface changed to support a Double Word sector +; number. +; 05 Oct 87 Critical Error abort routine now uses the correct +; terminate code. +; 14 Oct 87 INT2F responds like a Network Redirector +; 28 Oct 87 Preserve the state of the INDOS_INTERNAL flag during multiple +; calls through DOS_ENTRY +; 29 Oct 87 DS now points at the IBM PC ROS during an INT1B and INT1B +; moved into IBMROS. +; 7 Nov 87 Removal of development flags +; 5 Jan 88 Terminate CP/M applications making DOS Calls in Concurrent DOS +; 26 Feb 88 Terminate DOS applications making CP/M calls in DOSPLUS +; 26 Apr 88 INT25/26 error codes only translated for Concurrent +; 18 May 88 Prevent corruption of the EXIT_CODE by INT23 and INT24 +; when the application does not return. +; 23 May 88 Prevent termination during CONFIG.SYS processing in DOSPLUS +; 26 May 88 Force INDOS and ERROR flags to ZERO on terminate +; 1 Jun 88 Modify INT28 to execute delays and work with SideKick. +; 15 Jul 88 Support the IDLECNT field in the Process Descriptor and +; CCB BUSY bit. +; 07 Sep 88 PolyTron PolyWindows make DOS functions calls whenever +; CS < SS. Therefore during the INT21 Entry and Exit code +; interrupts must be disabled untill the stack swap occurs +; even though the INDOS_FLAG is non-zero. +; 24 Oct 88 File Lock/Unlock is now treated as an INACTIVE function. +; 4 Nov 88 Correct the INT25/26 Error Translation Code +; 21 Nov 88 Make INt25/26 Error Translation even better. +; 29 Nov 88 Command Line Editor Insert on by default. +; 21 Dec 88 IJs IDLE detection improvement only DELAY if someone else is +; ready to run. +; 11 Jan 89 Inc/Dec INTERNAL_FLAG to support DOS_ENTRY reentrancy. +; 30 Jan 89 Inc/Dec INDOS_FLAG to INT25/26 Direct Disk I/O (CHKDSK/PRINT) +; 19 Feb 89 Check the SHARE_FLAG for SHARING status in DR DOS +; 9 Mar 89 Save/Restore PSP_USERSP/SS round int28's (SKPLUS/LINK/CTRL-C) +; 18 Apr 89 ij Maintain the INDOS_FLAG correctly while processing INT 24 +; 18 Apr 89 Only take over INTs 5B and 5C for Debug Systems +; 22 May 89 Setup DS before testing the state of the Share Flag. +; 25 May 89 Support INT28_FLAG for functions 01 to 0C inclusive +; 31 May 89 Move break_sp into DOS internal data area +; 1 Jun 89 Save PSP_USERSS and SP during a critival Error (INT 24) +; 05 Jun 89 Return NOT present for ASSIGN command and TRUE state for APPEND +; 29 Jun 89 Save/restore retry_sp & retry_off around INT 24 +; 10 Jul 89 INT27 corrected to handle memory size of XXX1 (INFORM) +; 31 Jul 89 Move stacks to DATA.PCM (CDROM support under way...) +; 11 Aug 89 Create INT2F.PCM to support real INT 2F functions +; 6 Sep 89 INT2A/84 keyboard busy loop added to do_int28 +; 23 Oct 89 MON_PERM removed from func5D/func5E/func5F (pain with MSNET..) +; 9 Nov 89 Int 5B & 5C no longer taken over in DRDOS Debug versions +; (Conflicts with PC-Net) +; 15 Jan 90 pcmode_swapin/pcmode_swapout added for paged isr support +; 25/Jan/90 Support Idle Data Area +; 25/Jan/90 Add forth stack to support Japanese FEP and PTHOT. +; 29/Jan/90 keep int21 CS/IP/FLAGS on local stack +; 13/Feb/90 Added func63. +; 20/Feb/90 CDOS checks caller is DOS process and aborts if not. +; 22/Feb/90 Int25/26 checks disk label for passwords +; Also swaps to normal stack like others DOS's +; 7 Mar 90 Convert to register preserved function calls +; 16 Mar 90 Int25/26 checks out for Leopard Beta 2 +; 4 Jun 90 Int21/25&35 don't swap stacks-ANSI.SYS Framework DOS window bug +; 7 Jun 90 Print Rite fix moves to init.pcm +; 29 Jun 90 CDOS idle detection uses timer info +; 9 Aug 90 Int 8 tick count packed in P_CMOD +; 19 Sep 90 load current_psp before checking PSP_PIDF (thanks Datapac) +; 4 Oct 90 improved control break handling +; 11 Oct 90 dev_map now supported to set LPTn/COMn mapping +; 1 Nov 90 default Int 24 handler returns "Fail" +; 19 feb 91 do_int28 calls read_time_and_date (BIOS CLOCK needs a call +; every day) +; 14 jun 91 copy user regs to local copy after int24 for pcshell +; 8 aug 91 SI preserved on Int25/26 for SCAN 7.7 + + include pcmode.equ + include fdos.def + include vectors.def + include i:msdos.equ + include i:mserror.equ + include i:psp.def + include i:fdos.equ + +PCM_CODE CSEG BYTE + + extrn pcmode_dseg:word + extrn break_check:near ; Control-C Check + extrn error_exit:near + extrn fdos_nocrit:near + extrn get_ddsc:near + +eject +; +; This entry point is used when a CALLF PSP:0005 has been executed +; Here the function number is passed in CL and not AH and only +; functions 0 to 24 inclusive can be executed. +; +; Entry Stack -> INT 21 Stack +; +; SP + 04 Return Offset Current Flags +; SP + 02 PSP Segment PSP Segment +; SP + 00 000Ah Return Offset +; + Public call5_entry +call5_entry: + pop ax ; Remove 000Ah return Offset + pushf ; Save the Flags + push bp ! mov bp,sp ; Get Stack Frame Pointer + mov ax,02[bp] ; Get the FLAGS + xchg ax,06[bp] ; Swap with the return offset + mov 02[bp],ax ; and then save the return offset + pop bp ; Restore the BP register + mov ah,cl ; Make it look like an INT 21 + cmp ah,024h ; Check for a valid function for this + jbe int21_entry ; entry technique if not return +illegal_iret: + mov al,0 + iret + +int21_e01: + mov ds,word ptr .INT31_SEGMENT + jmps int21_e02 + +eject +; ++++++++++++++++++++++++++ +; Int 20 - Program Terminate +; ++++++++++++++++++++++++++ +; + Public int20_entry +int20_entry: + mov ah,00h +; jmps int21_entry ; and jump to the standard entry point + +eject +; +++++++++++++++++++++++++ +; Int 21 - Function Request +; +++++++++++++++++++++++++ +; + Public int21_entry +int21_entry: + cmp ah,pcmode_ftl ; is it in range ? + ja illegal_iret ; no, return BEFORE enabling ints + cld ; Clear the direction flag + PUSH$DOS ; Save User Registers + mov ds,pcmode_dseg ; get CS relative Data Segment + test pcmode_dseg,0FFFFh ; if Data Segment is zero then get + jz int21_e01 ; the Data segment address from +int21_e02: ; the segment portion of INT 31 + +; +; The following routines execute on the users stack without +; modifing the INDOS_FLAG etc. These routines should only read +; or update BASIC system variables. +; + cmp ah,33h ; Func 33h - Control Break + je int21_e10 + cmp ah,50h ; Func 50h - Set PSP + jb int21_e20 + cmp ah,51h ; Func 51h - Get PSP + jbe int21_e10 + cmp ah,62h ; Func 62h - Get PSP + jne int21_e20 +int21_e10: + mov bp,sp ; Calculate the Stack Frame address + call internal_func ; "jump" to appropriate routine + jmp int21_exit + +int21_e20: + inc indos_flag ; Increment the INDOS Flag + + mov int21AX,ax ; save function number + +if DOS5 + cmp WindowsHandleCheck,26h ; is windows active ? + jne int21_e30 + mov ax,LocalMachineID ; get local machine ID (zero unless + mov machine_id,ax ; we are multi-tasking) +else + callf win386_local_machine + cmp machine_id,0 ; did it nobble the machine ID + jnz int21_e30 ; if so leave it alone + + mov ax,LocalMachineID ; get local machine ID (zero unless + mov machine_id,ax ; we are multi-tasking) +endif +int21_e30: + mov ax,current_psp + mov owning_psp,ax + mov es,ax ; Get the PSP + + mov ax,sp + mov PSP_USERSP,ax ; Save the SS:SP pointer to + mov PSP_USERSS,ss ; the register image ready for any + ; Critical errors that might occur + + xchg ax,int21regs_off ; point to callers registers + mov prev_int21regs_off,ax ; while saving current + mov ax,ss ; pointer to cater for + xchg ax,int21regs_seg ; re-entrancy + mov prev_int21regs_seg,ax + + xor ax,ax + mov remote_call,ax ; indicate we are a local call + mov int28_flag,al ; Do NOT Generate INT 28s + + mov ax,ds + mov ss,ax ; swap initially to the error + mov sp,offset error_stack ; stack until we know better + mov ax,int21AX ; reload AX + + sti + cmp ah,59h ; Func 59h - Return Extended Error + je int21_e50 ; use the error stack + cmp ah,0Ch ; are we a character function + ja int21_e40 ; in range 01-0C ? + cmp ah,00h + je int21_e40 + cmp error_flag,0 ; Use the "ERROR" Stack for the above + jnz int21_e50 ; functions 01-0C if error_flag set + mov sp,offset indos_stack ; else use the "INDOS" stack for these + mov int28_flag,TRUE ; functions and generate INT 28s + jmps int21_e50 + +int21_e40: + mov error_flag,0 ; clear the error flag in case someone + ; hasn't returned from an Int 24 + push ax ; save function on stack + mov ah,82h ; magic number in AH + int 2ah ; call server hook + pop ax ; recover function number + + mov sp,offset normal_stack ; switch to the NORMAL stack + test break_flag,0FFh ; is the Break Flag ON + jz int21_e50 ; NO - So continue + call break_check ; Handle the Control-C +int21_e50: +if IDLE_DETECT + test idle_flags,IDLE_DISABLE ; don't break the pipeline unless + jz int21_idle ; IDLE checking enabled +int21_e60: +endif + call int21_func ; Execute the function + cli ; Stop anybody interfering + les bp,int21regs_ptr ; point to user stack + mov es:reg_AL[bp],al ; always return AL + mov ax,prev_int21regs_off + mov int21regs_off,ax + mov ax,prev_int21regs_seg + mov int21regs_seg,ax + mov ax,es + mov ss,ax ; back to users stack + mov sp,bp + dec indos_flag ; Decrement the INDOS_FLAG +; jmp int21_exit + + Public int21_exit +int21_exit: + POP$DOS ; Restore Registers + iret + +eject +if IDLE_DETECT +; Only called if Idle detection is enabled +; AH,DL as on Int 21 Entry +; Decide if function is active/inactive + +int21_idle: +;---------- +if IDLE_DETECT + mov bx,int28_reload ; reset the INT28 delay counter + mov int28_delay,bx ; with the Reload value +endif + cmp ah,5Ch ! je int21_inactive ; Treat Lock/Unlock as inactive some + ; applications poll locked record. + cmp ah,44h ! je int21_inactive ; IO Control Treated as Inactive + cmp ah,2Ch ! ja int21_active ; > Get Current Time all active + je int21_inactive ; Get Current Time inactive + cmp ah,2Ah ! je int21_inactive ; Get Current Date inactive + cmp ah,0Bh ! je int21_inactive ; Console Status + cmp ah,0Ch ! je int21_inactive ; Flush and Invoke Treated as Inactive + cmp ah,19h ! je int21_inactive ; Get Current Disk + cmp ah,06h ! jne int21_active ; Treat RAW_IO Status as Inactive + cmp dl,0FFh ! je int21_inactive ; + +int21_active: ; Active function Executed + or idle_flags,IDLE_DOSFUNC ; set DOSFUNC flag for BIOS + call active ; remember we were active + jmps int21_e60 ; continue execution + +int21_inactive: + call inactive ; Process this INACTIVE function + jmps int21_e60 + + + Public inactive +inactive: + push es ! push ax + + dec active_cnt ; Decrement the count + jnz inactive_10 ; Return if Non-Zero + + mov ax,idle_max ; Get the default count value + mov active_cnt,ax ; and reset the internal count + + test idle_flags,IDLE_DISABLE ; Has Idle Checking been enabled + jnz inactive_10 ; Skip if NO. + mov ax,PROC_IDLE ; Process is IDLE + callf idle_vec ; Call the IDLE Handler + +inactive_10: + pop ax ! pop es + ret +; +; This routine will reset the active count for functions which +; are treated as INACTIVE but which have active sub-functions. +; + Public active +active: + push ax + mov ax,idle_max ; Get the default count value + mov active_cnt,ax ; and reset the internal count + pop ax + ret +endif +; +; +; This function is invoked for functions number above the last +; supported function number. It forces AL to zero and returns. +; Just that and nothing more. +; +ms_zero_AL: + xor ax,ax ; AL = 0 for return + ret + +eject +; DOS_ENTRY is used to call DOS functions internally. +; eg. Func4B (exec) calls MS_X_OPEN, MS_X_READ, MS_X_CLOSE etc. +; It is the responsibilty of the caller to make sure that no side +; effects exist if this entry point is used. +; eg. critical error handling +; +; + Public dos_entry +dos_entry: + clc + cld + pushf ; look like Int21 registers + pushf ! pushf ; fake CS/IP positions + push ds ! push es ; Save registers on the USER stack + push bp ; no Stack Swap is executed and DS + push di ! push si ; and ES are swapped. + push dx ! push cx + push bx ! push ax + mov bp,sp ; Initialise Stack Frame + + call get_dseg ; Get our Data Area + + inc internal_flag + + push fdos_data+0*WORD ; save fdos pblk so we can + push fdos_data+1*WORD ; be re-entrant(ish) + push fdos_data+2*WORD + push fdos_data+3*WORD + push fdos_data+4*WORD + push fdos_data+5*WORD + push fdos_data+6*WORD + + push int21regs_off + push int21regs_seg + + mov int21regs_off,bp + mov int21regs_seg,ss + + call internal_func ; Execute the function + mov reg_AL[bp],al ; always return AL to caller + + pop int21regs_seg + pop int21regs_off ; restore previous pointer user REGS + + pop fdos_data+6*WORD + pop fdos_data+5*WORD + pop fdos_data+4*WORD + pop fdos_data+3*WORD + pop fdos_data+2*WORD + pop fdos_data+1*WORD + pop fdos_data+0*WORD ; restore fdos_pb for nested calls + + dec internal_flag + + pop ax ! pop bx ; Update the registers then + pop cx ! pop dx ; set the flags and return + pop si ! pop di ; to the user + pop bp + pop es ! pop ds + popf ; discard dos_IP + popf ; and dos_CS + popf ; get result + jnc dos_entry10 + neg ax ; return using our negative error + stc ; conventions +dos_entry10: + ret + + Public int21_func + +int21_func: +;---------- +; On Entry: +; AX, CX, DX, SI, DI as per Int 21 +; BX = ?? +; BP = ?? +; DS = pcmode data +; ES = ?? +; On Exit: +; (to client function) +; All general purpose registers as per Int 21 entry +; ES = dos_DS +; + + xor bx,bx ; BH = 0 + mov bl,ah ; BX = function number + shl bx,1 ; make it a word offset + push pcmode_ft[bx] ; save address of Function + les bp,int21regs_ptr + mov bx,es:reg_BX[bp] ; reload from dos_BX,dos_BP,and dos_DS + les bp,es:dword ptr reg_BP[bp] + ret + + +internal_func: +;------------- +; On Entry: +; All registers as per Int 21 EXCEPT +; DS = pcmode data +; BP = dos_REGS stack frame +; On Exit: +; (to client function) +; ES = dos_DS +; + mov al,ah ; function number in AL + cbw ; AH = 0 + xchg ax,bx ; get subfunction in BX + shl bx,1 ; make offset in the internal table + push pcmode_ft[bx] ; save address of Function + xchg ax,bx ; restore BX + mov ax,reg_AX[bp] ; recover function number + mov es,reg_DS[bp] ; ES = callers DS + ret ; "jump" to handler + +eject +; INT25 and INT26 direct disk I/O interface +; +;Standard DOS 1.xx - 3.30 INT25/26 Interface +;=========================================== +; +; entry: al = drive number +; ds = DMA segment +; bx = DMA offset +; cx = number of sectors +; dx = beginning relative sector +; +; +;Enhanced DOS 3.31 INT25/26 Interface +;==================================== +; +; If CX == 0FFFFh then the application is using the enhanced +; INT25/INT26 interface which allows access to more than 64K +; sectors. +; +; entry: al = drive number +; bx = Parameter block Offset +; ds = Parameter block Segment +; +; Parameter Block Format +;DS:BX -> DD Starting Sector No. +; DW Number of Sectors +; DD Transfer Address +; +; +; exit: C flag = 0 if successful +; = 1 if unsuccessful +; ax = error code(if CF = 1) +; ah physical error +; al logical error +; Users orginal flags left on stack +; +; +eject +DDIO_INT13 equ 0 +DDIO_READ_OP equ 1 +DDIO_WRITE_OP equ 2 + +; ++++++++++++++++++++++++++++ +; Int 26 - Absolute Disk Write +; ++++++++++++++++++++++++++++ +; + Public int26_entry +int26_entry: + mov ah,DDIO_WRITE_OP ; This is a WRITE operation + jmps int26_10 + + +; +++++++++++++++++++++++++++ +; Int 25 - Absolute Disk Read +; +++++++++++++++++++++++++++ +; + Public int25_entry +int25_entry: + mov ah,DDIO_READ_OP ; This is a READ operation +int26_10: ; Common Direct Disk I/O code + cld + push ds ! push es + push dx ; save DX for FLASHCARD + push ds ! pop es ; ES = callers DS + call get_dseg ; Get PCMODE Data Segment + inc indos_flag ; Update the INDOS_FLAG + mov normal_stack+2,ss ; save users SS:SP + mov normal_stack,sp + cli + push ds ! pop ss ; use normal stack when in here + mov sp,offset normal_stack + sti + inc cx ; CX = FFFF indicates this is + jz int26_30 +; CHECK FOR PARITIONS > 32 MBytes... + dec cx ; CX restored + push es + push ax + push bx + push dx + call get_ddsc ; ES:BX -> DDSC_ + mov di,0201h ; assume bad drive + jc int26_20 + mov di,0207h ; assume large media, and this error +if 0 +; This code works out the total number of sectors on a drive + mov ax,es:DDSC_NCLSTRS[bx] ; get last cluster # + dec ax ; make it # data clusters + xor dx,dx + mov dl,es:DDSC_CLMSK[bx] ; get sec/cluster -1 + inc dx ; DX = sec/cluster + mul dx ; DX:AX = # data sectors + add ax,es:DDSC_DATADDR[bx] ; add in address of 1st data sector + adc dx,0 +else + mov ax,es:DDSC_NCLSTRS[bx] ; get last cluster # + xor dx,dx + mov dl,es:DDSC_CLMSK[bx] ; get sec/cluster -1 + inc dx ; DX = sec/cluster + mul dx ; DX:AX is vaguely the # sectors + test dx,dx ; close enough for bill +endif + stc ; assume an error + jnz int26_20 + xor di,di ; DI = zero, no error +int26_20: + pop dx + pop bx + pop ax + pop es + jnc int26_40 + xchg ax,di ; AX = error code + jmps int26_60 ; return it +int26_30: + mov dx,es:word ptr 0[bx] ; Get Starting Sector Low + mov di,es:word ptr 2[bx] ; Get Starting Sector High + mov cx,es:word ptr 4[bx] ; Get No. of sectors to transfer + les bx,es:dword ptr 6[bx] ; Tranfer Address Offset +int26_40: + mov FD_DDIO_DRV_OP,ax ; save drive and operation + mov FD_DDIO_NSECTORS,cx ; No. of Sectors + mov FD_DDIO_STARTLOW,dx ; Starting Sector No. + mov FD_DDIO_STARTHIGH,di ; High Word of Sector Number + mov FD_DDIO_DMAOFF,bx ; DMA Offset + mov FD_DDIO_DMASEG,es ; DMA Segment + + mov FD_FUNC,FD_DDIO + call fdos_nocrit ; let the FDOS do the work + neg ax ; AX is DOS extended error + jz int26_exit + sub al,-ED_PROTECT ; get AL to Int24 error format + cmp al,-(ED_GENFAIL-ED_PROTECT) + jbe int26_50 + mov al,-(ED_GENFAIL-ED_PROTECT) +int26_50: ; no, make it general failure + mov ah,al ; save error in AH + mov bx,offset int13_error + xlat int13_error ; convert error to int13 format + xchg al,ah ; get errors in correct registers +int26_60: + stc ; Set the Carry Flag when an error +int26_exit: ; Occurs and return to the calling app. + cli + mov ss,normal_stack+2 ; back to user stack + mov sp,normal_stack + sti + dec indos_flag ; Update the INDOS_FLAG + sti + pop dx + pop es ! pop ds ; restore callers registers + retf ; leave flags on stack + +int13_error db 03h,02h,80h,01h,10h,02h,40h,02h,04h,02h,02h,02h,02h + +eject +; ++++++++++++++++++++++++++++++++++++ +; Int 27 - Terminate but Stay Resident +; ++++++++++++++++++++++++++++++++++++ +; + Public int27_entry +int27_entry: + mov ax,3100h ; Convert this to a DOS 'Terminate and + add dx,15 ; Stay Resident' function by converting the + rcr dx,1 ; memory size in bytes to paragraphs. + shr dx,1 ; On entry DX == memsize + 1 bytes therefore + shr dx,1 ; round upto a paragraph boundary by adding + shr dx,1 ; 15 then divide by 16 + jmp int21_entry + +eject +; +; DO_INT24: +; On Entry:- +; AH Set for INT 24 +; AL Drive Number (0 = A:) +; DI Error Code +; ES:SI Device Header Control Block +; +; On Exit:- +; AL Error Response Retry/Ignore/Fail +; +; INT 24 Critical Error:- +; On Entry:- AH/7 0 = Disk Device +; AH/5 0 = IGNORE is an Invalid Response +; AH/4 0 = RETRY in an Invalid Response +; AH/3 0 = FAIL is an Invalid Response +; AH/2-1 00= DOS Area +; 01= File Allocation Table +; 10= Directory +; 11= Data +; AH/0 0 = Read, 1 = Write +; +; AL 1 Retry the Operation +; BP:SI Device Header Control Block +; DI High Byte Undefined, Low Byte Error Code +; +; On Exit:- AL 0 = IGNORE Error +; 1 = RETRY the Operation +; 2 = TERMINATE using INT 23 +; 3 = FAIL the current DOS function +; + Public do_int24 +do_int24: + cmp error_flag,0 ; Skip the critical error routine + jz di24_05 ; if the handler is active + mov al,ERR_FAIL ; Then return the FAIL condition + ret ; to the calling routine +di24_05: + push ax ! push bp ; Save our Base Pointer and then the + cli ; Disable Interupts + + mov bp,es ; BP:SI points to dev header + mov es,current_psp ; Get the current PSP and USER Stack + + push PSP_USERSS ; Save the Users Real SS and SP + push PSP_USERSP ; on the internal Stack + push retry_sp ; also the retry info + push retry_off + push remote_call + push machine_id + + mov critical_sp,sp ; Internal Stack Pointer Offset + + inc error_flag ; Entering Critical Error Handler + dec indos_flag ; I may be gone some time.... + ; (an application error handler need + ; never return so tidy up first) + + mov ss,PSP_USERSS ; Switch to the Users Stack + mov sp,PSP_USERSP + + int 24h ; Call the Critical Error Handler + + cld + cli ; paranioa..... + call get_dseg ; Reload DS just in case someone at + ; A-T or Lotus cannot read + + push ds ! pop ss ; Swap back to the Internal stack + mov sp,critical_sp ; and process the returned info. + + pop machine_id + pop remote_call + pop retry_off ; restore retry info + pop retry_sp + mov es,current_psp ; Restore the Users original SS and + pop PSP_USERSP ; SP registers from the Stack + pop PSP_USERSS + + pop bp ! pop bx ; Restore BP and original AX + sti + + mov error_flag,0 + inc indos_flag + + cmp al,ERR_IGNORE ! jnz di24_10 ; Check for IGNORE and force + test bh,OK_IGNORE ! jnz di24_10 ; to become a FAIL if its an + mov al,ERR_FAIL ; invalid response. + +di24_10: + cmp al,ERR_RETRY ! jnz di24_20 ; Check for RETRY and force + test bh,OK_RETRY ! jnz di24_20 ; to become a FAIL if its an + mov al,ERR_FAIL ; invalid response. + +di24_20: + cmp al,ERR_FAIL ! jnz di24_30 ; Check for FAIL and force + test bh,OK_FAIL ! jnz di24_30 ; to become a ABORT if its an + mov al,ERR_ABORT ; invalid response. + +di24_30: + cmp al,ERR_ABORT ; Do not return if the ABORT option + jz di24_abort ; has been selected but execute + ; INT 23 directly + cmp al,ERR_FAIL ; All invalid reponses are converted + ja di24_abort ; to ABORT +di24_40: + ret + +di24_abort: ; Abort this Process + mov ax,current_psp ; check not root application because + mov es,ax ; it must not be terminated so force + cmp ax,PSP_PARENT ; Is this the root Process + mov al,ERR_FAIL ; convert the error to FAIL + je di24_40 ; if not we terminate + mov exit_type,TERM_ERROR ; Set the correct exit Type + mov ax,04C00h ; and return code. + mov int21AX,ax + jmp func4C ; Then terminate + +eject +; +; Get the PCMODE Emulator data Segment from the PD +; + Public get_dseg +get_dseg: + mov ds,pcmode_dseg ; get CS relative Data Segment + test pcmode_dseg,0FFFFh ; If Data Segment is zero then get + jz get_d10 ; the Data segment address from + ret ; the segment portion of INT 31 +get_d10: + mov ds,word ptr .INT31_SEGMENT + ret + + +; +;INVALID_FUNCTION is called when any unsupported function has been executed +; + Public invalid_function +invalid_function: + mov ax,ED_FUNCTION ; Mark as Invalid Function + jmp error_exit ; and Exit + + +eject + Public reload_registers +reload_registers: +;---------------- +; This routine is called to reload the registers we expect to have correct +; at the start of a PCMODE function. + push ds + lds bp,int21regs_ptr + mov ax,ds:reg_AX[bp] + mov bx,ds:reg_BX[bp] + mov cx,ds:reg_CX[bp] + mov dx,ds:reg_DX[bp] + mov si,ds:reg_SI[bp] + mov di,ds:reg_DI[bp] + les bp,ds:dword ptr reg_BP[bp] + pop ds + ret + +PCMODE_DATA DSEG WORD + + extrn retry_sp:word + extrn retry_off:word + + extrn break_flag:byte + extrn current_psp:word + extrn current_dsk:byte + extrn dma_offset:word + extrn dma_segment:word + extrn error_flag:byte + extrn error_stack:word + extrn exit_type:byte + extrn int21regs_ptr:dword + extrn int21regs_off:word + extrn int21regs_seg:word + extrn prev_int21regs_ptr:dword + extrn prev_int21regs_off:word + extrn prev_int21regs_seg:word + extrn indos_flag:byte + extrn indos_stack:word + extrn LocalMachineID:word + extrn machine_id:word + extrn int21AX:word + extrn normal_stack:word + extrn owning_psp:word + extrn remote_call:word +if DOS5 + extrn WindowsHandleCheck:byte +else + extrn win386_local_machine:dword +endif + +if IDLE_DETECT + extrn active_cnt:word + extrn idle_max:word + extrn idle_flags:word + extrn idle_vec:dword + extrn int28_delay:word + extrn int28_reload:word +endif + + extrn critical_sp:word + extrn internal_flag:byte + extrn int28_flag:byte + +PCM_CODE CSEG BYTE +; +; The following Function tables are forced onto a word boundary +; because of the word alignment of the PCMODE_RODATE segment. +; Only word based Read Only data is held in this segment. +; + extrn func00:near, func01:near, func02:near, func03:near + extrn func04:near, func05:near, func06:near, func07:near + extrn func08:near, func09:near, func0A:near, func0B:near + extrn func0C:near, func0D:near, func0E:near, func0F:near + extrn func10:near, func11:near, func12:near, func13:near + extrn func14:near, func15:near, func16:near, func17:near + extrn func19:near, func1A:near, func1B:near, func1C:near + extrn func1F:near, func21:near, func22:near, func23:near + extrn func24:near, func25:near, func26:near, func27:near + extrn func28:near, func29:near, func2A:near, func2B:near + extrn func2C:near, func2D:near, func2E:near, func2F:near + extrn func30:near, func31:near, func32:near, func33:near + extrn func34:near, func35:near, func36:near, func37:near + extrn func38:near, func39:near, func3A:near, func3B:near + extrn func3C:near, func3D:near, func3E:near, func3F:near + extrn func40:near, func41:near, func42:near, func43:near + extrn func44:near, func45:near, func46:near, func47:near + extrn func48:near, func49:near, func4A:near, func4B:near + extrn func4C:near, func4D:near, func4E:near, func4F:near + extrn func50:near, func51:near, func52:near, func53:near + extrn func54:near, func55:near, func56:near, func57:near + extrn func58:near, func59:near, func5A:near, func5B:near + extrn func5C:near, func5D:near, func5E:near, func5F:near + extrn func60:near, func62:near, func63:near, func65:near + extrn func66:near, func67:near, func68:near, func69:near + extrn func6C:near + +PCM_RODATA CSEG WORD + Public pcmode_ft, pcmode_ftl +pcmode_ft rw 0 + dw func00 ; (00) Terminate Program + dw func01 ; (01) Read Keyboard and Echo + dw func02 ; (02) Display Character + dw func03 ; (03) Auxilary Input + dw func04 ; (04) Auxilary Output + dw func05 ; (05) Print Character + dw func06 ; (06) Direct Console I/O + dw func07 ; (07) Direct Console Input + dw func08 ; (08) Read Keyboard + dw func09 ; (09) Display String + dw func0A ; (0A) Buffered Keyboard Input + dw func0B ; (0B) Check Keyboard Status + dw func0C ; (0C) Flush Buffer, Read Keyboard + dw func0D ; (0D) Reset Disk + dw func0E ; (0E) Select Disk + dw func0F ; (0F) Open File + dw func10 ; (10) Close File + dw func11 ; (11) Search for First + dw func12 ; (12) Search for Next + dw func13 ; (13) Delete File + dw func14 ; (14) Sequential Read + dw func15 ; (15) Sequential Write + dw func16 ; (16) Create File + dw func17 ; (17) Rename File + dw ms_zero_AL ; (18) Unused DOS function (AL = 0) + dw func19 ; (19) Current Disk + dw func1A ; (1A) Set Disk Transfer Address + dw func1B ; (1B) *Get Default Drive Data + dw func1C ; (1C) *Get Drive Data + dw ms_zero_AL ; (1D) Unused DOS function (AL = 0) + dw ms_zero_AL ; (1E) Unused DOS function (AL = 0) + dw func1F ; (1F) Get Default DPB + dw ms_zero_AL ; (20) Unused DOS function (AL = 0) + dw func21 ; (21) Random Read + dw func22 ; (22) Random Write + dw func23 ; (23) File Size + dw func24 ; (24) Set Relative Record + dw func25 ; (25) Set Interrupt Vector + dw func26 ; (26) Duplicate PSP + dw func27 ; (27) Random Block Read + dw func28 ; (28) Random Block Write + dw func29 ; (29) Parse File Name + dw func2A ; (2A) Get Date + dw func2B ; (2B) Set Date + dw func2C ; (2C) Get Time + dw func2D ; (2D) Set Time + dw func2E ; (2E) Set/Reset Verify Flag + dw func2F ; (2F) Get Disk Transfer Address + dw func30 ; (30) Get Version Number + dw func31 ; (31) Keep Process + dw func32 ; (32) Get DPB + dw func33 ; (33) CONTROL-C Check + dw func34 ; (34) Get the Indos Flag + dw func35 ; (35) Get Interrupt Vector + dw func36 ; (36) Get Disk Free Space + dw func37 ; (37) Get/Set Switch Character + dw func38 ; (38) Return Country Dependant Info + dw func39 ; (39) Create Sub-directory + dw func3A ; (3A) Remove Sub-directory + dw func3B ; (3B) Change Sub-directory + dw func3C ; (3C) Create a File + dw func3D ; (3D) Open a File Handle + dw func3E ; (3E) Close a File Handle + dw func3F ; (3F) Read from a File/Device + dw func40 ; (40) Write to a File/Device + dw func41 ; (41) Delete a Directory Entry + dw func42 ; (42) Move a File Pointer + dw func43 ; (43) Change Attributes + dw func44 ; (44) I/O Control + dw func45 ; (45) Duplicate File Handle + dw func46 ; (46) Force a Duplicate File Handle + dw func47 ; (47) Return Text of Current Directory + dw func48 ; (48) Allocate Memory + dw func49 ; (49) Free Allocated Memory + dw func4A ; (4A) Modify Allocated Memory + dw func4B ; (4B) Load and Execute Program + dw func4C ; (4C) Terminate a Process + dw func4D ; (4D) Get Return Code + dw func4E ; (4E) Find Matching File + dw func4F ; (4F) Find Next Matching File + dw func50 ; (50) Set Current PSP + dw func51 ; (51) Get Current PSP + dw func52 ; (52) *Get In Vars + dw func53 ; (53) *Build DPB from BPB + dw func54 ; (54) Return Verify State + dw func55 ; (55) Create a New PSP + dw func56 ; (56) Move a Directory Entry + dw func57 ; (57) Get/Set File Date and Time + dw func58 ; (58) Memory Allocation Strategy + dw func59 ; (59) Get Extended Error + dw func5A ; (5A) Create Temporary File + dw func5B ; (5B) Create New File + dw func5C ; (5C) File Lock Control + dw func5D ; (5D) Internal DOS Function + dw func5E ; (5E) Control Local Machine Data + dw func5F ; (5F) Get Network Assignments + dw func60 ; (60) Perform Name Processing + dw ms_zero_AL ; (61) ?? Parse Path (AL = 0) + dw func62 ; (62) Get Current PSP + dw func63 ; (63) Get Lead Byte Table + dw invalid_function ; (64) *Saves AL and Returns + dw func65 ; (65) Get Extended Country Information + dw func66 ; (66) Get/Set Global Code Page + dw func67 ; (67) Set Handle Count + dw func68 ; (68) Commit File + dw func69 ; (69) Get Serial number + dw func68 ; (6A) Commit File (again) + dw invalid_function ; (6B) Unknown DOS 4 + dw func6C ; (6C) Extended Open/Create +pcmode_ftl equ (offset $ - offset pcmode_ft)/2 + ;************************** + ;* Do Not Move This Entry * + ;************************** + dw ms_zero_AL ; Illegal Function Handler + + end diff --git a/IBMDOS/PCMODE.EQU b/IBMDOS/PCMODE.EQU new file mode 100644 index 0000000..77cde61 --- /dev/null +++ b/IBMDOS/PCMODE.EQU @@ -0,0 +1,179 @@ +; File : $PCMODE.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +; This file contains all the general purpose definitions +; and equates used by the PCMODE Module. +; + +TRUE equ 0FFFFh ; value of TRUE +FALSE equ 0 ; value of FALSE + +TRUE_VERSION equ 6 + +IDLE_DETECT equ TRUE ; Check for IDLE Process's + +if IDLE_DETECT +IDLE_COMMAND equ 0001h ; Command Processor Active +IDLE_DOSFUNC equ 0002h ; DOS Function Called +IDLE_INT28 equ 0004h ; INT 28 Called + +IDLE_ON equ 4000h ; ReSet when Idle Checking Enabled +IDLE_INIT equ 8000h ; ReSet when $IDLE$ Loaded and Active +IDLE_DISABLE equ IDLE_INIT + IDLE_ON + +PROC_IDLE equ 0001 ; Process is IDLE +PROC_INT28 equ 0002 ; INT28 Polling Loop +PROC_KEYIN equ 0003 ; Keyboard Input +PROC_DEVIN equ 0004 ; Device Input Routine +endif + + +STACK_SIZE equ 192 ; Local Stack Size (Levels) +MAX_PATHLEN equ 80 ; Maximum Path length +MAX_FILELEN equ 13 + +; +; DOS process termination Codes +; +TERM_NORMAL equ 0 ; Normal Termination +TERM_BREAK equ 1 ; Termination by Control Break +TERM_ERROR equ 2 ; Termination by Critical Error +TERM_RESIDENT equ 3 ; Terminate and Stay Resident + +; +; Critical Error responses from the default INT 24 handler and +; the DO_INT24 routine. +; +ERR_IGNORE equ 0 ; Ignore Error +ERR_RETRY equ 1 ; Retry the Operation +ERR_ABORT equ 2 ; Terminate the Process +ERR_FAIL equ 3 ; Fail Function +; +OK_FAIL equ 0000$1000b ; Fail is a Valid Response +OK_RETRY equ 0001$0000b ; Retry is a Valid Response +OK_IGNORE equ 0010$0000b ; Ignore is a valid Response +OK_RIF equ 0011$1000b ; All Responsese are Valid +OK_RI equ 0011$0000b ; Retry and Ignore are Valid +OK_RF equ 0001$1000b ; Retry and Fail are Valid +; +NO_CRIT_ERRORS equ 0100$0000b ; critical error shouldn't be generated + ; warning - must match FDOS.A86 +; +eject +; The following equates define the format in which the users registers +; are saved on the stack. This format is also seen by an application +; when a critical error occurs. +; +CodeMacro POP$DOS ; Pop User Registers a la MS-DOS + db 058h ! db 05Bh ; pop AX ! pop BX + db 059h ! db 05Ah ; pop BX ! pop CX + db 05Eh ! db 05Fh ; pop SI ! pop DI + db 05Dh ; pop BP + db 01Fh ! db 007h ; pop DS ! pop ES +EndM + +CodeMacro PUSH$DOS ; Push User Registers + db 006h ! db 01Eh ; push ES ! push DS + db 055h ; push BP + db 057h ! db 056h ; push DI ! push SI + db 052h ! db 051h ; push DX ! push CX + db 053h ! db 050h ; push BX ! push AX +EndM + +reg_AX equ word ptr .00 +reg_AL equ byte ptr .00 +reg_AH equ byte ptr .01 + +reg_BX equ word ptr .02 +reg_BL equ byte ptr .02 +reg_BH equ byte ptr .03 + +reg_CX equ word ptr .04 +reg_CL equ byte ptr .04 +reg_CH equ byte ptr .05 + +reg_DX equ word ptr .06 +reg_DL equ byte ptr .06 +reg_DH equ byte ptr .07 + +reg_SI equ word ptr .08 +reg_DI equ word ptr .10 +reg_BP equ word ptr .12 + +reg_DS equ word ptr .14 +reg_ES equ word ptr .16 + +reg_IP equ word ptr .18 +reg_CS equ word ptr .20 +reg_FLAGS equ word ptr .22 + +; Processor Flags +CARRY_FLAG equ 0001h ; Carry Flag +ZERO_FLAG equ 0040h ; Zero Flag +SIGN_FLAG equ 0080h ; Sign Flag +INT_FLAG equ 0200h ; Interrupt Flag +DIR_FLAG equ 0400h ; Direction Flag +OFLW_FLAG equ 0800h ; OverFlow Flag + +DMD_ID equ es:byte ptr .0 ; id code ('M' or 'Z') +DMD_PSP equ es:word ptr .1 ; owner of memory block +DMD_LEN equ es:word ptr .3 ; length of memory block +DMD_IDLE_FLAGS equ es:word ptr .6 ; idle flags live here +DMD_NAME equ es:byte ptr .8 ; ASCIIZ name field +DMD_NAME_LEN equ 8 ; 8 Bytes long +IDM equ 'M' ; not last id code +IDZ equ 'Z' ; last id code + +PCMCODE GROUP PCM_HEADER, PCM_CODE, BDOS_CODE, PCM_RODATA +PCMCODE GROUP PCM_HISTORY, PCM_ICODE, PCM_CODEND + +PCM_HEADER CSEG PARA +PCM_CODE CSEG BYTE +PCM_RODATA CSEG WORD +BDOS_CODE CSEG WORD +PCM_HISTORY CSEG BYTE +PCM_ICODE CSEG BYTE +PCM_CODEND CSEG PARA + + +PCMDATA GROUP PCMODE_DATA, FDOS_DSEG, FIXED_DOS_DATA +PCMDATA GROUP PCMODE_CODE, GLOBAL_DATA, BDOS_DATA, PCMODE_DSIZE + +PCMODE_DATA DSEG WORD ; DOS Data +FDOS_DSEG DSEG WORD COMMON ; FDOS Parameter Block +fdos_data rw 7 +FIXED_DOS_DATA CSEG WORD 'DATA' ; Fixed DOS Data Area +PCMODE_CODE CSEG WORD 'DATA' ; DATA relative CODE +GLOBAL_DATA DSEG WORD ; GLOBAL DOS DATA (Process Independant) +BDOS_DATA DSEG WORD ; BDOS Data Area +PCMODE_DSIZE DSEG PARA ; End of DOS Data Area diff --git a/IBMDOS/PROCESS.A86 b/IBMDOS/PROCESS.A86 new file mode 100644 index 0000000..1f21df2 --- /dev/null +++ b/IBMDOS/PROCESS.A86 @@ -0,0 +1,1493 @@ +; File : $PROCESS.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; $Log$ +; PROCESS.A86 1.25 94/07/13 16:15:27 +; Int21/26 (create PSP) copies 1st 20 entries of parental XFT +; PROCESS.A86 1.24 94/06/28 11:15:28 +; Don't issue an int 21 to get curret psp while within int21/4B load overlay +; PROCESS.A86 1.20 93/09/28 19:44:03 +; Don't lose 8th character of name in DMD during exec +; PROCESS.A86 1.14 93/06/18 21:00:57 +; Support for Int 21/4B05 added +; PROCESS.A86 1.13 93/06/11 02:11:20 +; GateA20 disabled on EXEC for EXEPACKED apps +; Fix termination code +; ENDLOG +; + + include pcmode.equ + include fdos.def + include i:psp.def + include i:mserror.equ + include vectors.def + include i:msdos.equ + include i:exe.def + include i:char.def + include i:redir.equ + include i:doshndl.def + +HILOAD equ TRUE + +PCM_CODE CSEG BYTE + extrn check_dmd_id:near + extrn dbcs_lead:near + extrn error_exit:near + extrn fdos_nocrit:near + extrn free_all:near + extrn get_dseg:near ; Get the PCMODE Data Segment + extrn int21_exit:near + extrn invalid_function:near + extrn dos_entry:near + extrn return_AX_CLC:near + extrn set_owner:near + extrn strlen:near + extrn toupper:near + extrn valid_drive:near +; +; +;PC-DOS PSP Creation Update and Maintance routines +; +; ***************************** +; *** DOS Function 55 *** +; *** Create New PSP *** +; ***************************** +; +; entry: DX = New PSP Segment +; SI = Top of Available +; +; This function copies the existing PSP and generates a new Process +; environment. The file table is updated and dos_SI is used to determine +; the process' memory size. The PSP is then made the CURRENT_PSP + + Public func55 +func55: + mov cx,PSPLEN/2 ; copy whole PSP + call create_psp + mov al,0F0h + ret + +create_psp: + mov ax,current_psp ; All based on the Current PSP + call copy_psp ; Do the Basic Copy + mov ax,current_psp ; get the Current PSP address + mov PSP_PARENT,ax ; and save it in child's psp + + cmp ax,dx ; Is this the ROOT level DOS process + jz create_psp10 ; Yes because Current PSP == New PSP + ; therefore skip the EXEC function + ; because this is done by P_CREATE + + mov FD_FUNC,FD_EXEC ; Must Update the Open Counts ETC. + mov FD_PSPSEG,dx ; New PSP address + call fdos_nocrit + +create_psp10: + mov current_psp,es ; set the New PSP address + ret + +; +; ***************************** +; *** DOS Function 26 *** +; *** Create New PSP *** +; ***************************** +; +; entry: DX = New PSP Segment +; + Public func26 +func26: + les di,int21regs_ptr ; Get pointer to INT 21 structure of + mov es,es:reg_CS[di] ; IP/CS/Flags and get the USER CS this + mov si,PSP_MEMORY ; is used as the PSP for this function + mov ax,es ; call and NOT current_psp + mov cx,PSPLEN/2 ; copy whole PSP + push dx + call copy_psp + pop es + mov cx,20 ; default XFT table has twenty files + mov di,offset PSP_XFT ; and is in the PSP at this offset + mov PSP_XFNMAX,cx ; say we have 20 files max + mov PSP_XFTOFF,di + mov PSP_XFTSEG,es + push ds + mov ds,current_psp ; we copy 1st 20 entries of current + lds si,ds:PSP_XFTPTR ; XFT to the child PSP + rep movsb ; we do not update file handle use + pop ds ; counts, unlike Int21/55 + ret + +copy_psp: +; copy CX words from AX:0 to DX:0, SI = memory top + push si ; Save the Memory TOP + push ds + mov es,dx ; Point ES to the New PSP + mov ds,ax ; Get the current PSP for this function + xor ax,ax + mov di,ax ! mov si,ax + rep movsw ; Copy into New PSP + + mov ds,ax ; Copy the current Terminate, Critical + mov si,INT22_OFFSET ; Error and Control Break Handlers + mov di,offset PSP_TERM_IP ; into the new PSP + mov cl,6 + rep movsw ; BREAK,TERM, CRIT ERR SAVED HERE + pop ds + pop PSP_MEMORY + + mov PSP_INT20,020CDh ; Interrupt 20h Terminate + mov PSP_RES1,0FFFFh + mov PSP_RES2,0FFFFh + mov PSP_DOSCALL,021CDh ; INT 21h Function Call + mov PSP_DOSRETF,0CBh ; RETF + + mov PSP_LONGCALL,09Ah ; CALLF AnySeg:MemSize + mov ax,PSP_MEMORY ; Get the Top of Memory + sub ax,dx ; Convert it to Memory Size + cmp ax,1000h ; Check for Over 64Kb + mov bx,0FEF0h ; Assume Over 64Kb + jae sce_10 + mov bx,ax ; Convert the Paragragh Length + mov cl,4 ; to a Byte Length + shl bx,cl + sub bx,110h ; Reserve 110h Bytes for .COM Stack +sce_10: + push dx + mov PSP_LONGOFF,bx ; Save the Byte Length + xor dx,dx ; Call 5 Entry Segment + mov ax,INT30_OFFSET ; Call 5 Entry Offset + mov cl,4 + shr ax,cl ; Entry Offset/16 => EO + shr bx,cl ; Jump Offset/16 => JO + add ax,dx ; EO + ES + sub ax,bx ; EO + ES - JO => JS + mov PSP_LONGSEG,ax + pop dx + ret + +; +; ***************************** +; *** DOS Function 50 *** +; *** Set Current PSP *** +; ***************************** +; + Public func50 + +; WARNING - called on USER stack + +func50: + mov current_psp,bx + ret + +; ***************************** +; *** DOS Function 51/62 *** +; *** Get Current PSP *** +; ***************************** +; + Public func51, func62 + +; WARNING - called on USER stack + +func51: +func62: + mov bx,current_psp + mov reg_BX[bp],bx + ret + +eject +;************************************************** +;************************************************** +;*** *** +;*** Process Control Functions *** +;*** *** +;************************************************** +;************************************************** + +; ***************************** +; *** DOS Function 31 *** +; *** Terminate and Keep *** +; ***************************** +; + Public func31 +func31: + mov ax,6 ; make 6 paragraphs our minimum size + cmp ax,dx ; Are we at our minimum size ? + jb func31_05 + xchg ax,dx ; no, enforce 6 paragraphs +func31_05: + mov exit_type,TERM_RESIDENT ; Exit by Terminate and Stay Resident + mov bx,current_psp ; and set the termination PSP to + mov term_psp,bx ; be the Current PSP + + push ds ; Attempt to modify the memory + mov ds,bx ; partition size to that given in DX + mov bx,dx ; Remember DS and ES are swapped for + call mem_setblock ; the internal function. + + mov ax,ds ; Now update the PSP_MEMORY field to + add ax,bx ; reflect the memory available to + mov ds:PSP_MEMORY,ax ; to the application now. Required by + pop ds ; MicroPro WordFinder + + mov load_psp,0000 ; Do not free PSP memory + jmp f31_term ; Common terminate handler + +; +; ***************************** +; *** DOS Function 4B *** +; *** Load or Execute Prog *** +; ***************************** +; +; An extra sub-function has been defined which is used by the +; ROOT DOS process loader to ensure compatibility between the +; Initial Register conditions for the ROOT DOS process and that +; of any child process. +; +; 4B80h - GO Sub-Function expects all the internal and +; external data areas to have been setup by a +; previous 4B01h function. Never Fails ! +; +; Undocumented feature: +; AX=4B03 returns SETVER version in AX, or zero +; + + Public func4B +func4B: + cmp al,80h ; Is this the special GO sub-function + jnz f4B_01 ; No Process Normally + jmp start_child ; Go for It every thing else OK + +f4B_01: + cmp al,5 ! je f4B05 ; Sub-Func 5:- Exec Hook + cmp al,3 ! je f4B_02 ; Sub-Func 3:- Load Overlay + cmp al,1 ! jbe f4B_02 ; Sub-Func 1:- Load and No Execute + ; Sub-Func 0:- Load and Execute +f4B_invalid: + jmp invalid_function ; Otherwise illegal Sub-Function + +f4B05: +;----- +; On Entry: +; ES:DX -> ExecState +esReserved equ word ptr 0 ; reserved, must be zero +esFlags equ word ptr 2 ; type flags +esProgName equ dword ptr 4 ; points to ASCIIZ name +esPSP equ word ptr 8 ; PSP of new program +esStartAddress equ dword ptr 10 ; CS:IP of new program +esProgSize equ dword ptr 14 ; program size, including PSP +; +; type flags +ES_EXE equ 0001h +ES_OVERLAY equ 0002h +; +; On Exit: +; None (A20 gate disabled) +; + mov di,dx ; ES:DI -> ExecState + test es:esFlags[di],not ES_EXE + jnz f4B_invalid ; only COM or EXE supported + call return_AX_CLC ; assume success + lds si,es:esProgName[di] ; DS:SI -> ASIIZ name + mov es,es:esPSP[di] ; ES = PSP + push es ; save for DX on exit + call SetPspNameAndVersion ; set up the name/version fields + pop dx ; DX = PSP + push ss + pop ds ; DS = pcmode data again + cli ; Stop anybody interfering + les bp,int21regs_ptr ; point to user stack + mov es:reg_AX[bp],0 ; return successful + and es:reg_FLAGS[bp],not CARRY_FLAG + mov ax,prev_int21regs_off + mov int21regs_off,ax + mov ax,prev_int21regs_seg + mov int21regs_seg,ax + dec indos_flag ; no longer in DOS + jmpf func4B05_stub ; exit via stub code + + +f4B_02: + xor ax,ax + mov load_env,ax ; Load environment NOT allocated + mov load_psp,ax ; Load memory NOT allocated + dec ax + mov load_handle,ax ; Mark Load file as CLOSED + + push es ! push dx ; expand the filename to a + call get_filename ; full path to be inherited + pop dx ! pop es ; in the environment + jc f4B_10 ; Exit on error + mov ax,(MS_X_OPEN*256)+20h ; Open File +; mov al,0$010$0$000B ; ReadOnly & DenyWrite + call dos_entry + jnc f4B_05 ; Save Handle if No Error + + cmp ax,ED_SHAREFAIL ; Check for a Sharing Error or Access + jz f4B_04 ; Denied if neither error codes then + cmp ax,ED_ACCESS ; Don't retry the Open function + jnz f4B_10 ; in compatibility + +f4B_04: + mov ax,(MS_X_OPEN*256)+0 ; retry the open in read-only +; mov al,0$000$0$000B ; compatibility mode + call dos_entry + jc f4B_10 ; Stop On error + +f4B_05: + push ds ! pop es ; ES local again + mov load_handle,ax ; Save for Error Handling + xchg ax,bx ; Get the File Handle + mov si,offset exe_buffer + call get_execdata + jc f4B_10 + call point_param_block ; CL = subfunc, ES:DI -> param block + cmp cl,3 ; Sub-Func 3:- Load Overlay + jne f4B_go ; Sub-Func 0:- Load and Execute + ; Sub-Func 1:- Load and No Execute + + mov si,es:2[di] ; si = Relocation Factor + mov di,es:[di] ; di = Load Segment + + call loadimage ; load and relocate image + jc f4B_10 ; f4B_error - Return with an error +if DOS5 + mov si,offset load_file ; Copy the process name into the DMD + call FindName ; DS:SI -> start of name + call GetVersion ; AX = version to return + mov es,current_psp ; poke the current psp + mov PSP_VERSION,ax ; with the version number +endif + jmp return_AX_CLC ; All done +f4b_10: + jmp f4B_error + + +; +; F4B_GO loads and executes the file whose handle is in BX. +; This routine corresponds to sub-functions 0 and 1. +; +f4B_go: + xor ax,ax + mov si,offset exe_buffer ; .COM and .EXE file loading + mov exe_loadhigh,al ; Reset the Load High Flag + cmp ax,EXE_MAXPARA[si] + jnz f4B_g15 ; Load High Flag (MAXPARA == 0) + dec ax + mov exe_loadhigh,al ; Set the internal LOADHIGH flag + mov EXE_MAXPARA[si],ax ; and allocate all memory +f4B_g15: + mov ax,es:[di] ; get ENV pointer from param block + call build_env ; Build the environment + jc f4B_error ; Stop on error + + call calc_psp ; calculate new psp + jc f4B_error ; Stop on error + call pblk_to_psp ; Copy parameters into PSP + mov si,load_image ; read the Load image + mov di,si ; to previously calculated address + call loadimage ; load in com file + jc f4B_error ; quit if no memory + call set_up_psp ; build child's psp + mov dx,load_psp ; point at PSP seg + + mov exit_type,TERM_NORMAL ; Initialise the Return code type + mov si,offset exe_buffer ; to normal an go + call check_exe + jc f4B_go_com + + mov dx,load_image ; Get the Load Paragraph + add EXE_CS[si],dx ; bias the code segment + add EXE_SS[si],dx ; and the stack segment too + jmp start_child ; goodbye! + +; +f4B_go_com: ; Go for it .COM +; mov dx,load_psp ; based at PSP seg + mov EXE_CS[si],dx ; set up initial cs:ip + mov EXE_IP[si],100h ; and ss:sp for child + mov EXE_SS[si],dx + mov es,dx + mov bx,PSP_LONGOFF ; ax = segment size in bytes + add bx,110h - 2 ; Initialise stack in reserved area + mov EXE_SP[si],bx ; save as stack ptr + mov es:word ptr[bx],0 ; put one zero on the stack + jmp start_child ; goodbye! + +; +; Function 4B Error Handler. This exit routine will free all +; resources allocated to a process during the EXEC function and +; exit to the standard error handler with the original error code +; if any further errors occur they are ignored. +; +f4B_error: + push ax ; Save the return Code + mov bx,load_handle ; Is the load file still open ? + inc bx ; (FFFF = closed) + jz f4B_e10 ; YES then Close + dec bx + mov ah,MS_X_CLOSE + call dos_entry +f4B_e10: ; Now Free any memory allocated + mov cx,load_psp ; during the execution of FUNC4B + call conditional_mem_free ; firstly free PSP/code/data memory + mov cx,load_env ; Secondly free the memory allocated + call conditional_mem_free ; to hold the ENVIRONMENT + pop ax ; Restore the return code and exit + mov valid_flg,OK_RF ; fiddle to resume func 4B if we get + mov retry_sp,sp ; a critical error + mov retry_off,offset func4B + call error_exit ; call the standard error handler + cmp ax,-ED_FORMAT ; errors less than ED_FORMAT are OK. + jb f4B_e20 ; (eg. ED_MEMORY, ED_FILE) + mov ax,load_handle ; if we didn't manage to open exec file + inc ax ; load_handle=FFFF and we want to + mov al,-ED_PATH ; return ED_PATH + jz f4B_e20 ; else we had an error during the load + mov al,-ED_FORMAT ; and should return ED_FORMAT +f4B_e20: + ret + +eject +start_child: + mov es,current_psp ; ds -> psp + mov dx,0080h ; default dma offset + mov ah,MS_F_DMAOFF ; Set the DMA address + call dos_entry ; set child's dma address + mov si,offset exe_buffer ; Get EXE Buffer Offset + call point_param_block ; CL = subfunc, ES:DI -> param block + cmp cl,1 + jne start_child_go ; load restisters and go +; +; The following code updates the Extended parameter block +; used with the LOAD for DEBUG sub-function. +; + add di,DWORD*3+WORD ; skip user supplied info + mov ax,EXE_SP[si] + dec ax ! dec ax ; return ss:sp-2 + stosw + xchg ax,bx ; save SP for later + mov ax,EXE_SS[si] + stosw + + push ds + mov ds,ax + mov word ptr [bx],0 ; zero on user stack + pop ds + + lea si,EXE_IP[si] ; point at IP + lodsw ! stosw ; copy it, and get in AX for return + movsw ; copy EXE_CS too + jmp return_AX_CLC ; all went OK + +start_child_go: +;-------------- +; +; Set the initial registers conditions for a DOS process +; Check the validity of the drives specified in FCB 1 and FCB 2 +; of the loading PSP and initialise the AX register accordingly. +; + xor dx,dx ; start with valid drives + mov es,current_psp ; Get the PSP Address and check + push dx + mov al,PSP_FCB1 ; if the drive specifier for FCB1 + call valid_drive ; is invalid set AL to FF + pop dx + jz reg_s10 + mov dl,0FFh +reg_s10: + push dx + mov al,PSP_FCB2 ; if the drive specifier for FCB2 + call valid_drive ; is invalid set AH to FF + pop dx + jz reg_s20 + mov dh,0FFh +reg_s20: + mov di,EXE_SP[si] ; Get the new stack address + push di ; save it + mov cl,4 + shr di,cl ; convert SP to para's + jnz reg_s30 + mov di,1000h ; if 0k make it 64k +reg_s30: + mov ax,load_max ; find top of prog area + sub ax,EXE_SS[si] ; find para's left for stack + cmp di,ax ; SP too high ? + pop di ; assume OK + jb reg_s40 + mov di,ax ; no, so lower SP + shl di,cl ; convert to bytes +reg_s40: + mov cx,EXE_SS[si] ; CX:DI -> initial stack + les si,dword ptr EXE_IP[si] ; get initial CS:IP + cli + mov ax,current_psp ; AX = PSP we are going to use + xchg ax,dx + mov indos_flag,0 ; zap the indos flag +if 0 + mov ss,cx ; switch to new USER stack + mov sp,di + push es + push si ; CS:IP on USER stack + mov ds,dx ; DS = ES = PSP we are exec'ing + mov es,dx + xor bx,bx ; BX = zero, set flags + sti + retf ; lets go! +else + jmpf exec_stub +endif + +eject +; ***************************** +; *** DOS Function 00 *** +; *** Terminate Process *** +; ***************************** +; +; This code is executed for both INT 20 and INT 21/00 and they both +; implicitly set the current PSP to the users calling CODE segment. +; This overwrites the correct value held in CURRENT_PSP. +; + Public func00 +func00: + mov byte ptr int21AX,0 ; force return code of zero + les di,int21regs_ptr + mov bx,es:reg_CS[di] ; normally users CS is current_psp + mov ax,current_psp ; but application call here + cmp ax,bx ; with an Int 20 at funny moments + je func4c ; (I have "NOW!" in mind) + mov es,bx ; fiddle CS PSP parent so we return to + mov PSP_PARENT,ax ; current_psp then fiddle current_psp + mov current_psp,bx ; to be user CS + +; ***************************** +; *** DOS Function 4C *** +; *** Terminate Process *** +; ***************************** +; + Public func4C +func4c: + mov ax,current_psp ; the current PSP is terminating + mov term_psp,ax ; so set term_psp and load_psp + mov load_psp,ax ; to that value + +f31_term: ; INT27 and INT21/31 Entry Point + push ds + mov ds,term_psp + xor ax,ax + mov es,ax ; Copy the Three interrupt vectors + mov si,offset PSP_TERM_IP ; saved on process creation from the + mov di,INT22_OFFSET ; termination PSP to the interrupt + mov cx,6 ; vector table. + rep movsw + mov ax,8200h ; call the REDIR hooks to clean up + int 2ah ; first the server hook + mov ax,I2F_PTERM ; then call cleanup code + int 2fh ; via magic INT 2F call + pop ds ; back to PCMODE data + mov al,byte ptr int21AX ; Get the User Return Code + mov user_retcode,al ; Save the User Ret Code and Set the + mov al,TERM_NORMAL ; Now get the Termination Type + xchg al,exit_type ; and exchange with the default value + mov system_retcode,al ; EXIT_TYPE is set so Non-Zero values + ; when a Special Form of termination + ; takes place. ie INT 27h + +; But thence came VTERM, and it looked upon terminating the ROOT process, +; and saw that it was good. +; +; VTERM gives access to the cmdline by doing func31 and becoming a TSR. You can +; then re-invoke it with a hot-key but the next time you invoke the cmdline +; option does a func4C in whatever context it was re-invoked in. This will +; either blow away an application, or try and terminate the ROOT process. + + + mov es,term_psp ; make the terminating PSP's + mov ax,es:PSP_PARENT ; parental PSP into the + mov bx,current_psp + cmp ax,bx ; Is the user trying to terminate + jz f4C_20 ; the ROOT DOS process if YES then + ; skip freeing resources (VTERM) + + mov cx,load_psp ; if we are TSR'ing + jcxz f4C_20 ; skip the free + + push ax ; save parental PSP + mov es,bx ; ES = current PSP + xor bx,bx ; start with handle zero +f4C_10: + mov ah,MS_X_CLOSE ; close this handle + call dos_entry ; so freeing up PSP entry + inc bx ; onto next handle + cmp bx,PSP_XFNMAX ; done them all yet? + jb f4C_10 + mov FD_FUNC,FD_EXIT ; Must Close all Open FCB's + call fdos_nocrit + push ds ; We have already closed all the + pop es ; open MSNET files we know about + mov ax,I2F_PCLOSE ; but we will call the MSNET + int 2fh ; extention's cleanup code anyway + + push ss ! pop ds ; reload DS with data segment + + mov bx,current_psp ; free all memory associated + call free_all ; with this PSP + + pop ax ; recover parental PSP +f4C_20: + mov current_psp,ax ; make current PSP = parental PSP + +; +; Function 4C requires a different termination technique. It needs +; to return to the parent process on the stack that was used on the +; function 4B. The interrupt structure has been forced to contain +; the interrupt 22 vector. Therefore all registers will contain +; their original values unless the stack has been overlayed +; +; + cli ; Stop anybody interfering + mov indos_flag,0 ; Force the INDOS_FLAG to 0 for PCTOOLS + mov error_flag,0 ; and SideKick Plus. + mov ax,retcode + mov ds,current_psp + mov ss,ds:PSP_USERSS ; Retrieve the entry SS and SP from + mov sp,ds:PSP_USERSP ; the PSP and return with all + mov bp,sp ; registers as on user entry + mov ss:reg_AX[bp],ax ; Set AX to the Process RETCODE + xor ax,ax + mov ds,ax + mov ax,ds:word ptr .INT22_OFFSET + mov ss:reg_IP[bp],ax ; PSP_TERM_IP + mov ax,ds:word ptr .INT22_OFFSET+WORD + mov ss:reg_CS[bp],ax ; PSP_TERM_CS + mov ss:reg_FLAGS[bp],0b202h ; force flags to 0F202h + ; ie Interrupts enabled and + ; NEC processor Mode Switch SET + ; changed to B202 to have clear + ; NT flag (DPMS doesn't like it) + jmp int21_exit ; Jump to the Exit routine + + +eject +; ***************************** +; *** DOS Function 4D *** +; *** Get Sub-Func Ret-Code *** +; ***************************** +; + Public func4D +func4D: + xor ax,ax ; Zero the return code for + xchg ax,retcode ; subsequent calls and return the + jmp return_AX_CLC ; saved value to the caller + +eject +;**************************************** +;* * +;* Process Control Subroutines * +;* * +;**************************************** + +; +; We need a full pathname for the application to inherit in it's environment. +; MS_X_EXPAND can't do the job - it returns a PHYSICAL path which may be +; unreachable (bug circa DRDOS 3.41). +; On Entry: +; ES:DX Points to the Original FileName +; On Exit: +; None +; + +get_filename: + push ds + push es ; swap ES and DS + pop ds + pop es + mov si,dx ; DS:SI -> filename + mov di,offset load_file ; ES:DI -> local buffer + mov cx,MAX_PATHLEN-4 ; max length (allow for d:\,NUL) + lodsw ; get 1st two chars in filename + cmp ah,':' ; is a drive specified ? + je get_filename10 + dec si ! dec si ; forget we looked + mov al,ss:current_dsk ; and use the default drive + add al,'A' +get_filename10: + stosb ; put in the drive + and al,1fh ; convert from ASCII to 1 based + xchg ax,dx ; keep in DL for ms_x_curdir + mov ax,':'+256*'\' ; make it "d:\" + stosw + lodsb ; do we start at the root ? + cmp al,'\' + je get_filename20 + cmp al,'/' + je get_filename20 + dec si ; forget we looked for a root + push si ; save where we were + mov ah,MS_X_CURDIR + mov si,di ; ES:SI -> buffer + call dos_entry ; get current directory + xor ax,ax + repne scasb ; look for NUL + xchg ax,si ; AX = start of path + pop si ; recover pointer to source + jne get_filename30 + dec di ; point at NUL + cmp ax,di ; are we at the root ? + je get_filename20 + mov al,'\' + stosb ; no, append a '\' +get_filename20: + rep movsb ; copy the remainder of the string +get_filename30: + xor ax,ax + stosb ; ensure we are terminated + push es + pop ds ; DS back to nornal + ret + + +; +; BUILD_ENV determines the size of the Source environment and +; allocates memory and finally copies it. +; +; ON entry AX contains the segment address of the environment +; to be used or zero if the parents is to be copied. +build_env: + mov es,ax ; Assume user has specified the + or ax,ax ; environment to be used. If AX is + jnz b_e10 ; 0000 then use the current environment + mov es,current_psp + mov cx,PSP_ENVIRON ; Current Environment Segment + mov es,cx ; If the current environment segment + mov di,cx ; is zero then return a size of + jcxz b_e35 ; zero bytes + +b_e10: + xor ax,ax ; Now determine the Environment size + mov cx,32*1024 ; CX is maximum size + mov di,ax +b_e20: + repnz scasb ; Look for two zero bytes which + jcxz b_e40 ; mark the end of the environment + cmp al,es:byte ptr [di] ; continue search till the end is found + jnz b_e20 + dec di ; DI == Environment Size - 2 + +b_e30: + mov si,offset load_file ; Get the Load pathname length + call strlen ; String length returned in CX + inc cx ; Add in the terminator + + push bx + mov bx,cx ; Get the String Length + add bx,di ; Add the environment size + add bx,15 + 4 ; and convert to paragraphs + shr bx,1 ! shr bx,1 + shr bx,1 ! shr bx,1 + mov load_envsize,bx ; Save the Environment Size + call mem_alloc ; allocate the memory + pop bx + jc b_e50 + mov load_env,ax ; Save the Environment location + push cx ! push di ; Save STRLEN and Offset + push ds ; Save DS + push es + mov es,ax ; Point ES at the NEW environment + pop ds ; Point DS at the Old environment + mov cx,di ; Get the environment size + xor si,si ! mov di,si ; Initialize the pointers + rep movsb ; and copy. Nothing moves if CX == 0 + pop ds + + pop di ! pop cx ; Get the string pointers + xor ax,ax ! stosw ; Add terminating zeros + inc ax ! stosw ; Initialise the String COUNT field + + + mov si,offset load_file ; and size information and + rep movsb ; copy the load filename. +b_e35: + clc ; Return with no errors + ret +b_e40: + mov ax,ED_ENVIRON ; Invalid environment +b_e50: + stc + ret + + +; Calculate the new program segment prefix +; save: bx -> Handle +calc_psp: + push bx + mov si,offset exe_buffer ; Calculate the Minimum and Maximum + ; amount of memory required to load + call image_size ; the program image (Returned in DX) + add dx,PSPLEN/16 ; Do not forget the PSP + mov cx,dx ; Save the Load Image Size + mov bx,dx ; BX will be memory required + mov ax,ED_MEMORY + add dx,EXE_MINPARA[si] ; force DX to be the minimum and if + jc cp_exit ; more than 1 MByte exit with error + add bx,EXE_MAXPARA[si] ; add the maximum amount of memory + jnc c_p10 ; to the load image size + mov bx,0FFFFh ; clipping to 1 MByte +c_p10: +if HILOAD + test mem_strategy,80h ; HILOAD ON ? + jz c_p15 + mov bx,dx ; use minimum amount of memory + add bx,40h ; add 1 K extra for luck (stack etc) + call mem_alloc ; Allocate the requested block + jc cp_exit ; if alloc fails exit with error + push ds + mov ds,ax + mov bx,0ffffh ; find how much we can grow this block + call mem_setblock + call mem_setblock ; then grow it to that size + mov ax,ds ; ax = base of the block again + pop ds + jmps c_p20 +c_p15: +endif + call mem_alloc ; allocate size and if error occurs + jnc c_p20 ; then the maximum size is greater + cmp bx,dx ; than the minimum required + jc cp_exit ; if not exit with error + + call mem_alloc ; Allocate what we've got + jc cp_exit ; Exit on error +c_p20: + mov load_psp,ax ; Save the load paragraph == PSP + add bx,ax ; Save the block top + mov load_top,bx + mov load_max,bx ; save top of block for SP adjust + add ax,PSPLEN/16 ; Set AX to be the Relocation Paragraph + + cmp exe_loadhigh,0 ; Should the Load Image be + jz c_p30 ; forced into to High Memory with the + mov ax,bx ; data area and PSP loaded low. + sub ax,cx ; Subtract the Load Image Size from + mov cx,PSPLEN/16 ; the top of allocated memory and + add ax,cx ; load at that address. + +c_p30: + mov load_image,ax ; Save the Address of the Load Image +cp_exit: + pop bx + ret + +eject +;LOADIMAGE: +; +; This function reads in the load image of the file into memory +; (Paragraph DI) asserting the relocation factor (SI) if any relocation +; items exist in the file. The size of the load image is calculated +; using the EXE_SIZE and EXE_FINAL fields enough memory exists at DI +; to load the image. The valid .EXE header has been moved to exe_buffer. +; +; Read in and relocate the EXE image +; entry: bx -> handle +; di = load segment +; si = reloc segment +; exit: cf = 1, ax = Error Code if load fails +; +loadimage: +;--------- + call readfile ; Read the load image into memory + jc load_error ; Exit if error + + mov cx,exe_buffer+EXE_RELCNT + ; get number of reloc entries + jcxz load_done ; if none there, forget it .COM's + ; drop out here because RELCNT is zero + + push cx ; seek to 1st relocation entry + xor cx,cx ; in the file + mov dx,exe_buffer+EXE_RELOFF + mov ax,(MS_X_LSEEK*256)+0 + call dos_entry + pop cx + jc load_error ; stop on error + xchg ax,cx ; AX = # items to relocate + call reloc_image ; relocate the image + jc load_error +load_done: + mov load_handle,-1 + mov ah,MS_X_CLOSE ; and close the loadfile + jmp dos_entry ; close the com file + +load_error: ; Error exit from relocation + push ax ; save error code + call load_done ; close the file + pop ax ; recover error code + stc ; say we had an error + ret + +; +; The following code will relocate CX items from the open handle BX +; +reloc_image: +; On Entry: +; BX = handle +; AX = # items to relocate +; SI = relocation segment +; DI = relocation fixup +; +; On Exit: +; CY clear if OK, else AX = error code + + + push ds ! pop es ; ES -> Local Buffer Segment + mov dx,offset reloc_buf ; DX -> Local Buffer Offset + + mov cx,RELOC_CNT ; AX -> Buffer Size + shl cx,1 ; convert reloc size from paras + shl cx,1 ; to an item count + sub ax,cx ; buffer. which contains a maximum + jnc reloc_i10 ; of RELOC_SIZE items. + add cx,ax ; CX contains # of items to Read + xor ax,ax ; AX contains # left to read +reloc_i10: + push ax ; save # items left to read + push cx ; and # reloc to read + shl cx,1 ! shl cx,1 ; calculate # byte to read + mov ah,MS_X_READ ; relocation buffer. + call dos_entry + pop cx + jnc reloc_i20 ; Exit on Error + pop cx ; clean up stack + ret ; return with error + +reloc_i20: + push bx ; save handle + xchg ax,di ; AX = reloc fixup + + mov bx,dx ; Get buffer offset +reloc_i30: + add word ptr 2[bx],ax ; Correct segment to Load Seg + les di,dword ptr [bx] ; es:di = reloc entry + add es:[di],si ; add reloc seg into image + add bx,4 ; and update for next entry + loop reloc_i30 + + xchg ax,di ; restore fixup to DI + pop bx ; recover handle + pop ax ; recover # left to do + test ax,ax + jnz reloc_image ; keep going until all done + ret + +;READFILE +; +; This function reads in the load image of the file into memory +; (Paragraph DI) the size of the load image is calculated using +; the EXE_SIZE and EXE_FINAL fields enough memory exists at DI +; to load the image. The valid .EXE header has been moved to +; exe_buffer. +; +; Read in a Binary Image .COM or .EXE +; entry: bx -> handle +; di = load segment +; +; exit: bx, si, di Preserved +; cf = 1, ax = Error Code if load fails +; +MAX_READPARA equ 3200 ; Maximum Number of Paragraphs to + ; read in one command 50Kb +readfile: + push si ! push di + mov si,offset exe_buffer ; Get the .EXE header + mov dx,EXE_HEADER[si] ; get the header size in paragraphs + mov cx,4 ; and seek to that offset in the + rol dx,cl ; file before reading any data + mov cl,dl + and cx,0Fh ! and dx,not 0Fh + mov ax,(MS_X_LSEEK*256)+0 + call dos_entry ; Execute LSEEK Function + jc rf_error + call image_size ; Get the Load Image Sizes in Paras + mov si,dx ; Returned in DX save in SI +rf_10: + mov es,di ; Set the Buffer address + sub dx,dx ; es:dx -> load segment + + cmp si,MAX_READPARA ; Can we read the rest of the file + jbe rf_20 ; in one command jif YES + sub si,MAX_READPARA ; Decrement the Image Size + mov cx,MAX_READPARA * 16 ; Number of bytes to read + add di,MAX_READPARA ; Number of Paragraphs Read + mov ah,MS_X_READ ; Read the Block into the + call dos_entry ; buffer Exit if Error + jc rf_error + jmps rf_10 ; Else go for the next bit + +rf_20: ; Now reading the last part of + mov cl,4 ; the image so convert remainder + shl si,cl ; in SI to bytes and Read File + mov cx,si + mov ah,MS_X_READ ; Read data into the buffer + call dos_entry + jc rf_error ; Stop on Error + xor ax,ax ; Reset the carry Flag and Zero AX +rf_error: ; Error exit Carry Flag Set and AX + pop di ! pop si ; contains the error code. + ret + +; Copy old PSP contents to new PSP. +; Parameter block supplied by user contains command line +; and default FCB's - copy these into the load_psp. +; save: bx -> Handle +pblk_to_psp: + push ds ; Save the PcMode Data Segment + push bx ; and file handle + mov dx,load_psp + call point_param_block ; ES:DI -> users parameter block + + push es ! push di + lds si,es:dword ptr 2[di] ; Get the Source Pointer + mov cx,128 ; Copy the complete command line + mov di,offset PSP_COMLEN ; because BASCOM places a segment value + mov es,dx ; after the CR which was not previously + rep movsb ; copied. + pop di ! pop es + + lds si,es:dword ptr 6[di] ; get 1st FCB address + mov ax,offset PSP_FCB1 ; First FCB Offset + call copy_fcb ; copy FCB + lds si,es:dword ptr 10[di] ; Get the Source Pointer + mov ax,offset PSP_FCB2 ; Second FCB Offset + call copy_fcb ; copy FCB + pop bx ; file handle back again + pop ds ; Restore PcMode Data Segment + ret + +copy_fcb: +;-------- +; On Entry: +; DS:SI -> source +; DX:AX -> destination +; On Exit: +; None +; ES:DI, DX preserved +; + push es + push di + mov es,dx + xchg ax,di ; ES:DI -> destination + mov cx,12 ; Copy Drive, Name and Extension + rep movsb ; and copy it + xchg ax,cx ; AX = 0 + stosw ! stosw ; zero last 4 bytes + pop di + pop es + ret + + + +; Set up a new psp for the child +; +set_up_psp: + mov ax,load_psp ; Change the ownership of the + mov bx,load_env ; Environment and Load Memory + call set_owner ; partitions. + mov ax,load_psp + mov bx,ax + call set_owner + + cmp current_psp,1 ; Is This the ROOT DOS process + jnz setup_psp10 ; No! Continue as Normal + + mov ax,load_psp ; Force the LOAD_PSP to + mov current_psp,ax ; to be the current PSP + + mov es,ax ; Now Zero Fill the New PSP + mov cx,(offset PSP_FCB1)/2 ; up to user supplied parameters + xor ax,ax ! mov di,ax + rep stosw + jmps setup_psp20 ; and skip the INT22 Fudge + +setup_psp10: ; Get the Function return address + xor di,di ! mov es,di ; and force into INT 22 + mov di,INT22_OFFSET ; Set Interrupt Vectors 22 + push ds + lds si,int21regs_ptr + lea si,reg_IP[si] ; DS:SI -> callers IP + movsw ; Save User IP + movsw ; Save User CS + pop ds +setup_psp20: + mov dx,load_psp ; Get the new PSP address + mov si,load_top ; Get the last paragraph allocated + mov cx,(offset PSP_FCB1)/2 ; Copy PSP up to user supplied bits +; +; CREATE_PSP is a local function called by the DOS EXEC function (4B) +; to create a new PSP and initialize it as a new process. +; +; The PSP_MEMORY field was original calculated as the highest memory +; location that could be allocated to a process. However this caused +; Carbon Copy Plus to Fail so the routine now uses the LOAD_TOP +; value calculated by the CALC_PSP function. This is the last +; paragraph allocated to the current PSP. +; + call create_psp ; Create the New Process + mov ax,load_env ; Now Update the Environment + mov PSP_ENVIRON,ax + mov si,offset load_file ; Copy the process name into the DMD +; jmp SetPspNameAndVersion + +SetPspNameAndVersion: +;--------------------- +; On Entry: +; ES = PSP +; DS:SI -> pathaname (nb. DS need not be dos data seg!) +; On Exit: +; None +; + mov bx,es + dec bx + mov es,bx ; ES points at DMD (We Hope) + call check_dmd_id ; Check for a valid DMD + jc SetPspNameAndVersion10 ; bail out now if none +if DOS5 + inc bx ; BX -> PSP again + push bx ; keep it on the stack +endif + call FindName ; DS:SI -> start of name + push si + call SetName ; update the name field + pop si +if DOS5 + call GetVersion ; AX = version to return + pop es ; ES = PSP + mov PSP_VERSION,ax ; set version number +endif +SetPspNameAndVersion10: + ret + +FindName: +;-------- +; On Entry: +; DS:SI -> pathname of file +; On Exit: +; DS:SI -> final leaf name of file +; CX = length of leaf name +; + mov cx,si ; remember start of leaf +FindName10: + lodsb + cmp al,' ' ; end of the name ? + jbe FindName30 + call dbcs_lead ; is it a double byte pair ? + jne FindName20 + lodsb ; include the second byte + jmps FindName10 +FindName20: + cmp al,'\' ; is it a seperator ? + je FindName + cmp al,'/' + je FindName + jmps FindName10 +FindName30: + xchg cx,si ; SI -> start of leaf name + sub cx,si + dec cx ; CX = length + ret + + +SetName: +;------- +; On Entry: +; DS:SI -> leaf name to update +; ES = DMD to update +; On Exit: +; CX preserved +; + mov di,offset DMD_NAME ; point at the owners name field +SetName10: + lodsb + cmp al,' ' ; end of the name ? + jbe SetName30 + call dbcs_lead ; is it a double byte pair ? + jne SetName20 + stosb ; copy 1st byte of pair + cmp di,(offset DMD_NAME)+DMD_NAME_LEN + jae SetName30 ; don't overflow if name too long + movsb ; and the second + jmps SetName10 + +SetName20: + stosb + cmp al,'.' ; discard all following '.' + je SetName30 + cmp di,(offset DMD_NAME)+DMD_NAME_LEN + jb SetName10 ; don't overflow if name too long + ret + +SetName30: + dec di + xor ax,ax +SetName40: + stosb ; zero the '.' + cmp di,(offset DMD_NAME)+DMD_NAME_LEN + jb SetName40 ; zero the rest of the name + ret + +if DOS5 +GetVersion: +;---------- +; On Entry: +; DS:SI -> start of name +; CX = length +; On Exit: +; AX = dos version to return +; + les di,ss:setverPtr + mov ax,es + or ax,di ; check for a setver list + jnz GetVersion30 +GetVersion10: + mov ax,ss:dos_version ; better use default version + ret + +GetVersion20: + mov al,es:0FFFFh[di] ; skip the name + cbw + inc ax ! inc ax ; skip the version + add di,ax ; try the next entry +GetVersion30: + mov al,es:byte ptr [di] ; get length field + test al,al ; end of the list ? + jz GetVersion10 + + inc di ; point at potential name + cmp al,cl ; do the lengths match ? + jne GetVersion20 + xor bx,bx ; start scan with 1st character +GetVersion40: + mov ax,ds:[bx+si] ; get a character from filename + call dbcs_lead ; is it a DBCS character ? + jne GetVersion50 + inc bx ; we will skip 2 characters + cmp ax,es:[bx+di] ; do both character match ? + jmps GetVersion60 + +GetVersion50: + call toupper ; upper case it + mov ah,al ; save it + mov al,es:[bx+di] ; get a character from setver list + call toupper ; upper case it + cmp al,ah ; do we match ? +GetVersion60: + jne GetVersion20 ; no, try next name in list + inc bx ; we match, have we done them all ? + cmp bx,cx ; check against length + jb GetVersion40 + mov ax,es:[bx+di] ; get version number from setver list + ret +endif + +eject +; +; GET_DATA reads the EXE header using the handle passed in BX +; + +get_execdata: +; On Entry: +; BX = handle +; ES:SI = buffer +; On Exit: +; CY set if error, AX = error code +; BX/SI preserved + + mov ah,MS_X_READ + mov cx,EXE_LENGTH ; read the exe header + mov dx,si ; ES:DX -> buffer + call dos_entry ; try and read the data + jc gd_exit ; Error Exit + mov EXE_FINAL[si],0200h ; Force value to Full Page + call check_exe ; all done if it's an .EXE + jnc gd_exit + mov ax,(MS_X_LSEEK*256)+2 ; it's a .COM + xor cx,cx ; seek to end of file + xor dx,dx + call dos_entry ; get file length in DX:AX + jc gd_exit + xchg al,ah ! mov ah,dl ; DX:AX / 512 + shr dx,1 ! rcr ax,1 + inc ax ; Handle Final Partial Page + mov EXE_SIZE[si],ax ; No. of 512 Byte Pages + xor ax,ax + mov EXE_HEADER[si],ax ; Load Image starts a 0000 + mov EXE_RELCNT[si],ax ; No Relocation Items + dec ax ; Force Maximum Memory Allocation + mov EXE_MAXPARA[si],ax ; to the .COM + mov EXE_MINPARA[si],0010h ; give it at least an extra 100h + ; bytes for the Default Stack +gd_exit: + ret + +eject +; +; Determine if the file to be loaded is a DOS EXE format file +; if YES then return with the carry flag reset. Assume that the +; header has already been read into EXE_HEADER +; + public check_exe +check_exe: + cmp EXE_SIGNATURE[si],'ZM' ; look for exe signature + jz check_e10 + cmp EXE_SIGNATURE[si],'MZ' ; look for exe signature + jz check_e10 + stc ; flag the error +check_e10: + ret + +; +; IMAGE_SIZE assumes SI points to a valid EXE header and from this +; it calculates the size of the load image and returns this value +; in paragraphs in DX. AX and CX are corrupted. +; + Public image_size +image_size: + mov dx,EXE_SIZE[si] ; No of 512 pages in System Image + dec dx ; Adjust for Final Partial Page + mov cl,5 ! shl dx,cl ; No. 512 Byte Blocks to Para + sub dx,EXE_HEADER[si] ; Remove the Header Size + + mov ax,EXE_FINAL[si] + add ax,15 + dec cl ! shr ax,cl ; AX is Partial Block in PARA + add dx,ax ; DX is Image Size in PARA's + ret + +mem_alloc: + mov ah,MS_M_ALLOC ; call DOS to allocate + jmp dos_entry ; some memory + +mem_setblock: + mov ah,MS_M_SETBLOCK ; call DOS to ajust + jmp dos_entry ; a memory block + +conditional_mem_free: +; On Entry: +; CX = para to free +; (0 = none to free) +; On Exit: +; None +; + jcxz cmem_free10 ; only free up allocated + push ds ; memory + mov ds,cx + mov ah,MS_M_FREE ; free up a memory block + call dos_entry + pop ds +cmem_free10: + ret + +point_param_block: +;----------------- +; On Entry: +; None +; On Exit: +; CL = subfunction number (callers AL) +; ES:DI -> parameter block (callers ES:BX) +; AX corrupted +; + les di,int21regs_ptr ; point at callers registers + mov cl,es:reg_AL[di] ; CL = subfunction# (range-checked) + mov ax,es:reg_BX[di] + mov es,es:reg_ES[di] ; callers ES:BX -> parameter block + xchg ax,di ; ES:DI -> parameter block + ret + + + +PCMODE_DATA DSEG WORD + extrn current_dsk:byte + extrn current_psp:word + extrn retcode:word ; Complete return code passed to F4B + extrn user_retcode:byte ; User retcode set by funcs 4C and 31 + extrn system_retcode:byte ; System retcode returns the cause of + extrn switch_char:byte + extrn mem_strategy:byte ; memory allocation strategy + extrn int21AX:word ; Int 21's AX + extrn indos_flag:byte + extrn int21regs_ptr:dword + extrn int21regs_off:word + extrn int21regs_seg:word + extrn prev_int21regs_off:word + extrn prev_int21regs_seg:word + extrn error_flag:byte + extrn exe_buffer:word + extrn valid_flg:byte + extrn retry_off:word + extrn retry_sp:word + extrn last_drv:byte + extrn exec_stub:dword + extrn func4B05_stub:dword + +if DOS5 + extrn dos_version:word + extrn setverPtr:dword +endif + +eject +; To improve Network performance the EXE relocation items are +; now read into the following buffer. All the data items contained +; between RELOC_BUF and RELOC_SIZE are destroyed by the LOADIMAGE +; sub-routine when it relocates a DOS .EXE file. +; +; Only variables which are unused after the LOADIMAGE function can +; be placed in this buffer. +; +; ******** Start of .EXE Relocation Buffer ******** +; + +; We can re-use the MSNET pathname buffers during an EXEC + + extrn reloc_buf:byte + extrn load_file:byte + extrn RELOC_CNT:abs + +; +; ******** End of .EXE Relocation Buffer ******** +; + + extrn exit_type:byte + extrn term_psp:word + extrn load_handle:word + extrn load_env:word ; Paragraph of the new environment + extrn load_envsize:word ; Size of new environment + extrn load_psp:word ; Paragraph of the new PSP. + extrn load_image:word ; Paragraph of the Load Image. + extrn load_top:word ; Last paragraph of Allocated Memory + extrn load_max:word ; ditto, but not messed with + extrn exe_loadhigh:byte ; load high flag + + end diff --git a/IBMDOS/PSP.DEF b/IBMDOS/PSP.DEF new file mode 100644 index 0000000..a66a161 --- /dev/null +++ b/IBMDOS/PSP.DEF @@ -0,0 +1,108 @@ +; File : $PSP.DEF$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +; +; Program Segment Prefix +; ---------------------- +; This structure holds vital information for DOS programs +; +;******************************************************************************* +;* +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 00 | int 20 | memory | *** | jmpf|longjmp off| +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 08 |longjmp seg| int22 Off | int22 Seg | int22 Off | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 10 | int22 Seg | int24 Off | int24 Seg | Parent | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 18 | Default Handle Table | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 20 | XFT (20 entries) | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 28 | XFT contd. | Environ | User SP | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 30 | User SS | xfnmax | xftoff | xftseg | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 38 | res1 | res2 | ric | *** | ********* | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 40 | version | ********* | ********* | ********* | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 48 | ********* | ********* | ********* | ********* | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 50 | int 21 | retf| *** | ********* | ********* | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ +;* 58 | ********* | ********* | PSP fcb 1 | +;* +-----+-----+-----+-----+-----+-----+-----+-----+ + +PSP_INT20 equ es:word ptr .0000h +PSP_MEMORY equ es:word ptr .0002h +;PSP_??? equ es:byte ptr .0004h +PSP_LONGCALL equ es:byte ptr .0005h +PSP_LONGOFF equ es:word ptr .0006h +PSP_LONGSEG equ es:word ptr .0008h +PSP_TERM_IP equ es:word ptr .000Ah +PSP_TERM_CS equ es:word ptr .000Ch +PSP_BREAK_IP equ es:word ptr .000Eh +PSP_BREAK_CS equ es:word ptr .0010h +PSP_ERROR_IP equ es:word ptr .0012h +PSP_ERROR_CS equ es:word ptr .0014h +PSP_PARENT equ es:word ptr .0016h +PSP_XFT equ es:byte ptr .0018h +; +; The Default Handle Table is HERE !! +; +PSP_ENVIRON equ es:word ptr .002ch +PSP_USERSP equ es:word ptr .002eh +PSP_USERSS equ es:word ptr .0030h +PSP_XFNMAX equ es:word ptr .0032h +PSP_XFTPTR equ es:dword ptr .0034h +PSP_XFTOFF equ es:word ptr .0034h +PSP_XFTSEG equ es:word ptr .0036h +PSP_RES1 equ es:word ptr .0038h ; DOS Reserved 0FFFFh +PSP_RES2 equ es:word ptr .003Ah ; DOS Reserved 0FFFFh +PSP_RIC equ es:byte ptr .003Ch ; Return Interim Character flag +PSP_VERSION equ es:word ptr .0040h ; DOS version number + + +PSP_DOSCALL equ es:word ptr .0050h +PSP_DOSRETF equ es:byte ptr .0052h + +PSP_FCB1 equ es:byte ptr .005Ch +PSP_FCB2 equ es:byte ptr .006Ch +PSP_COMLEN equ es:byte ptr .0080h +PSP_COMLINE equ es:byte ptr .0081h + +XFNMAX equ 20 + +PSPLEN equ 100h +PSPILEN equ 60h diff --git a/IBMDOS/REDIR.A86 b/IBMDOS/REDIR.A86 new file mode 100644 index 0000000..2f4102c --- /dev/null +++ b/IBMDOS/REDIR.A86 @@ -0,0 +1,1722 @@ +title 'REDIR - DOS file system network redirector interace support' +; File : $REDIR.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; $Log: $ +; REDIR.A86 1.30 94/12/01 10:05:21 +; added attribute support for open/move/unlink +; REDIR.A86 1.29 94/11/11 15:10:03 +; Code at redir_lseek30 changed to ensure that the file offset is +; updated. Previously, this did not happen when INT 21/4202 (seek from +; end of file) was called, and consequently the game MYST could not +; be installed under NWDOS7. +; REDIR.A86 1.28 94/10/03 15:41:12 +; fix problem where VLM network mapping gets deleted if you try to access +; a path greater than 66 characters long on a network drive. +; REDIR.A86 1.27 94/02/22 18:05:09 +; fix problem with "d:\\filename.ext" (Netware 4 LOGIN) +; REDIR.A86 1.26 94/01/10 16:42:16 +; File delete uses file attributes of 06, not 16 (no directory bit) +; REDIR.A86 1.25 93/12/10 00:03:09 +; Move non-inherited bit to correct place in file handle +; REDIR.A86 1.22 93/11/19 23:59:00 +; If a read/write returns ED_LOCKFAIL turn into ED_ACCESS on shared files +; REDIR.A86 1.21 93/09/24 19:50:50 +; Tidy up code on rename +; REDIR.A86 1.15 93/06/16 16:22:21 +; Always initialise file search attributes to 16h (ie. sys+hidden+dir) +; REDIR.A86 1.14 93/06/11 15:08:09 +; Return 0 from search first/next +; REDIR.A86 1.13 93/06/11 02:06:53 +; zero space adjust on getddsc +; ENDLOG + + eject ! include i:psp.def + eject ! include i:fdos.equ + eject ! include i:msdos.equ + eject ! include i:mserror.equ + eject ! include i:doshndl.def ; DOS Handle Structures + eject ! include i:f52data.def ; DRDOS Structures + eject ! include i:redir.equ + +FD_EXPAND equ 55h + + eject + +PCMODE_DATA dseg + + extrn current_dsk:byte + extrn current_ddsc:dword + extrn current_dhndl:dword + extrn current_filepos:dword + extrn current_ldt:dword + extrn dma_offset:word + extrn dma_segment:word + extrn err_drv:byte + extrn file_attrib:word + extrn ldt_ptr:dword + extrn last_drv:byte + extrn phys_drv:byte + extrn pri_pathname:byte + extrn remote_call:word + extrn sec_pathname:byte + extrn srch_buf:byte + +; Data for some int2f commands + + extrn int2f_cmd:word + extrn int2f_stack:word + extrn file_mode:word + +BDOS_CODE cseg + + Public islocal + Public redir_asciiz_dev_offer + Public redir_asciiz_offer + Public redir_asciiz_file_offer + + Public redir_drv_offer + Public redir_dhndl_offer + Public redir_move_offer + Public redir_snext_offer + + extrn toupper:near + extrn check_delim:near + extrn check_slash:near + extrn check_dslash:near + extrn copy_asciiz:near + extrn unparse:near + extrn find_xfn:near + extrn find_dhndl:near + extrn ifn2dhndl:near + extrn get_xftptr:near +if KANJI + extrn dbcs_lead:near +endif + + +redir_dhndl_offer: +;================ +; The FDOS has called this hook to see if we are operating on an MSNET drive. +; We return if we are not, or stay and process function here if we are + test es:byte ptr DHNDL_WATTR+1[bx],DHAT_REMOTE/100h + jnz redir_dhndl_accept + ret +redir_dhndl_accept: +; copy some info from DHNDL_ to local variables + push ds + push ss ! pop ds + mov ax,es:DHNDL_DEVOFF[bx] + mov word ptr current_ddsc,ax + mov ax,es:word ptr DHNDL_DEVSEG[bx] + mov word ptr current_ddsc+WORD,ax + mov ax,es:word ptr DHNDL_POS[bx] + mov word ptr current_filepos,ax + mov ax,es:word ptr DHNDL_POS+2[bx] + mov word ptr current_filepos+2,ax + pop ds + jmps redir_accept ; now we can process the call + + +redir_asciiz_dev_offer: +;====================== +; The FDOS has called this hook to see if we are opening a redirected device. +; We return if we are not, or stay and process function here if we are + +; Before we build it all ourselves do the appropriate INT 2F to allow +; other people to process the path themselves + + call redir_dev_check ; is it a device ? + jnc redir_accept ; it's been recognised + ret + +redir_move_offer: +;================ +; The FDOS has called this hook to see if the rename operation is on a +; redirected drive. Lantastic relies on the path check broadcast's being +; done in the order new_name, old_name. + + mov word ptr current_ldt,0ffffh + mov err_drv,DHAT_DRVMSK + push ds + mov si,2[bp] ; SI -> parameter block + lds si,10[si] ; DS:SI -> user supplied name + push ss ! pop es + mov di,offset sec_pathname ; DI -> where to build pathname + push ds ! push si ! push di ! push bp + mov ax,I2F_PPATH + int 2fh ; offer path build to someone else + pop bp ! pop di ! pop si ! pop ds + mov cx,0 ; if accepted then it's a remote drive + jnc redir_move_offer10 + call build_remote_path ; build path if it a remote drive +redir_move_offer10: + pop ds + jc redir_asciiz_error ; return error's if we have any + jcxz redir_asciiz_offer ; it's a valid remote path + ret ; it's not a remote path + +redir_asciiz_offer: +;================== +; The FDOS has called this hook to see if we are operating on an redirected +; drive. We return if we are not, or stay and process function here if we are. + call redir_dev_check ; is it a device ? + jnc redir_accept ; it's been recognised +; jmp redir_asciiz_file_offer ; now try offering as a file + +redir_asciiz_file_offer: +;======================= +; entry: SS:BP -> function #, parameter address +; 1st level call (MXdisk not owned) +; exit: ZF = 1 if not networked +; +; This function is only called after an Int 2F/I2F_PPATH callout has been +; made and failed. On some functions (Open/Create) we do a check for devices +; between the redir_dev_offer and redir_asciiz_file offer + +; We look for a "\\" as the start of "\\server\dir\file" form + + push ds ; save DS + mov si,2[bp] ; SI -> parameter block + lds si,2[si] ; get ASCIIZ # from parameter block + mov di,offset pri_pathname ; SS:DI -> path buffer + call build_remote_path ; build path if it a remote drive + pop ds ; restore DS + jc redir_asciiz_error ; return error's if we have any + jcxz redir_accept ; it's a valid remote path + ret ; it's not a remote path + +redir_asciiz_error: +; On Entry: +; BX = error code +; DS on stack +; On Exit: +; DS restored, BX preserved +; near return on stack discarded, and error returned to fdos_entry +; + pop ax ; discard "offer" near ret + ret ; drop straight back to caller + +redir_drv_offer: +;=============== +; The FDOS has called this hook to see if we are operating on an MSNET drive. +; We return if we are not, or stay and process function here if we are +; +; entry: SS:BP -> function #, parameter address +; (MXdisk not owned) +; exit: return if not networked + + mov dl,current_dsk ; assume it's the default drive + mov si,2[bp] ; SI -> parameter block + mov ax,2[si] ; get drive # from parameter block + test al,al ; test if default drive + jz redir_drv_offer10 ; skip if default drive + dec ax ; else decrement for 0..26 + xchg ax,dx ; and use that +redir_drv_offer10: + call isremote + jnz redir_accept + ret ; return if not + +redir_snext_offer: +;================= +; The FDOS has called this hook to see if we are operating on an MSNET drive. +; We return if we are not, or stay and process function here if we are + + call redir_restore_srch_state + test al,80h ; MSNET drive ? + jnz redir_accept + ret + + +redir_accept: +;============ +; We have decided to accept an FDOS function. +; Note by this time the functions have been validated as legal + mov file_attrib,16h ; default search attribs to all + pop si ; discard the near return address + mov si,2[bp] ; SI -> parameter block + mov si,ds:[si] ; fdos code number + add si,si ; make it a word offset + jmp cs:redir_tbl-(39h*WORD)[si] ; call the relevant function + + +redir_badfunc: +;------------- + mov bx,ED_FUNCTION ; bad function number + ret ; (shouldn't get here...) + +redir_tbl dw redir_mkdir ; 39-make directory + dw redir_rmdir ; 3A-remove directory + dw redir_chdir ; 3B-change directory + dw redir_creat ; 3C-create file + dw redir_open ; 3D-open file + dw redir_close ; 3E-close file + dw redir_read ; 3F-read from file + dw redir_write ; 40-write to file + dw redir_unlink ; 41-delete file + dw redir_lseek ; 42-set file pointer + dw redir_chmod ; 43-get/set file attributes + dw redir_badfunc ; 44-IOCTL emulation + dw redir_badfunc ; 45-duplicate handle + dw redir_badfunc ; 46-force duplicate handle + dw redir_badfunc ; 47-get current directory + dw redir_getdpb ;*48*disk information + dw redir_badfunc ;*49*flush buffers + dw redir_badfunc ;*4A*drive select + dw redir_badfunc ;*4B*create child PSP + dw redir_badfunc ;*4C*close child PSP + dw redir_badfunc ;*4D*generic FCB call + dw redir_first ; 4E-find first matching file + dw redir_next ; 4F-find next matching file + dw redir_commit ;*50*commit file + dw redir_mknew ;*51*make new file + dw redir_lock ;*52*lock/unlock block + dw redir_badfunc ; 53 build DDSC from BPB + dw redir_badfunc ;*54*Int 25/26 emulation + dw redir_expand ; 55 expand file name + dw redir_move ; 56-rename file + dw redir_dattim ; 57-get/set file name + + Public get_ldt + +; To support func5D00 remote server calls we must bypass the LDT and +; go directly to the physical drive. To allow support of CDROM's etc +; on servers we do use the LDT's where no corresonding physical drive +; exists. + +get_ldt: +;------- +; On Entry: +; AL = drive (0 based) +; On Exit: +; ES:BX -> LDT for that drive, set CY if no valid LDT +; (All other regs preserved) +; + cmp al,ss:phys_drv ; if there is no conflict with + jae get_ldt_raw ; physical drives it's OK + test ss:remote_call,0ffh ; remote calls must get to physical + jz get_ldt_raw ; for server support + mov bx,ED_DRIVE ; invalid drive + stc ; no-go + ret + + Public get_ldt_raw + +get_ldt_raw: +;----------- +; On Entry: +; AL = drive (0 based) +; On Exit: +; ES:BX -> LDT for that drive, set CY if no valid LDT +; (All other regs preserved) +; + push ax + mov bx,ED_DRIVE ; assume invalid drive + cmp al,ss:last_drv ; do we have an LDT for this drive ? + jae get_ldt10 ; if not we can't have an LDT + cmp ss:word ptr ldt_ptr+2,0 ; are the LDT's allocated yet ? + je get_ldt10 ; if not return an error + mov bl,LDT_LEN + mul bl ; AX = offset of LDT entry for drive + les bx,ss:ldt_ptr ; get base of LDT's + add bx,ax ; DS:BX -> LDT for this drive + stc ; ie. CLC on exit +get_ldt10: + cmc + pop ax + ret + +get_ldt_flags: +;------------- +; entry: DL = drive number +; exit: AX = LDT_FLAGS entry for that drive +; (All other regs preserved) +; + push es + push bx + xor ax,ax ; assume no LDT around... + xchg ax,dx ; AL = drive number + call get_ldt ; ES:BX -> LDT + xchg ax,dx ; restore drive to DX + jc glf10 ; AX = zero if no LDT + mov ss:word ptr current_ldt,bx ; set current_ldt + mov ss:word ptr current_ldt+2,es + mov ax,es:LDT_FLAGS[bx] ; return real flags +glf10: + pop bx + pop es + ret + +islocal: +;------- +; entry: AL = drive number (zero based) +; exit: CY = set if drive is remote +; (All other regs preserved) +; + push ax + push dx + xchg ax,dx + call get_ldt_flags +if JOIN + test ax,LFLG_JOINED+LFLG_NETWRKD + ; are REMOTE/JOINED bits set ? +else + test ax,LFLG_NETWRKD ; is REMOTE bit set ? +endif + jz islocal10 + stc ; indicate it's not local +islocal10: + pop dx + pop ax + ret + +isremote: +;-------- +; entry: DL = drive number +; exit: ZF = clear if drive is remote +; CY = set if drive is JOIN'd +; (Only AX corrupted) +; + call get_ldt_flags +if JOIN + test ax,LFLG_JOINED ; is JOINED bit set ? + jnz isremote10 +endif + test ax,LFLG_NETWRKD ; is REMOTE bit set ? + ret +if JOIN +isremote10: + test ax,LFLG_NETWRKD ; is REMOTE bit set ? + stc ; STC to indicate JOIN'd + ret +endif + +redir_dev_check: +;--------------- +; Offer the name to the network as a device +; On Entry: +; PB+2 = dword ptr to ascii name +; DI -> buffer to parse into +; On Exit: +; CY set if not recognised +; + mov word ptr current_ldt,0ffffh + mov err_drv,DHAT_DRVMSK + push ds ! push bp + mov si,2[bp] ; SI -> parameter block + lds si,2[si] ; DS:SI -> user supplied name + mov dx,si ; DS:DX as well.. + push ss ! pop es + mov di,offset pri_pathname ; DI -> where to build pathname + mov ax,I2F_PPATH + int 2fh ; offer path build to someone else + pop bp ! pop ds + ret + +build_remote_path: +;----------------- +; On Entry: +; DS:SI -> path to check +; SS:DI -> position to build remote path +; On Exit: +; CY clear, CX == 0 if it's a valid remote path +; CY clear, CX <> 0 if it's a local path +; CY set if there is an error to be returned (BX = error code) +; + mov cx,si ; save source path in CX + mov dl,ss:current_dsk ; assume current disk + lodsw ; get 1st two characters + test al,al ; make sure it's not a NUL string + jz build_remote_path10 ; before we check it it's a + cmp ah,':' ; drive specified + jne build_remote_path10 ; we want to find "d:\\" format too + mov bx,ED_DRIVE ; assume "invalid drive" error + and al,not 'a'-'A' ; cheap upper case + sub al,'A' + jb build_remote_path30 ; return "invalid drive" if error + cmp al,ss:last_drv ; check if > 'Z' + ja build_remote_path30 ; return "invalid drive" if error + xchg ax,dx ; DL = ASCIIZ supplied drive + lodsw ; get possible '\\' +build_remote_path10: + mov ss:word ptr current_ldt,0ffffh + call check_dslash ; is it "\\" + je build_remote_path20 ; if so forget about the drive # + call isremote ; test if drive DL is remote +if JOIN + jb build_remote_path30 ; return "invalid drive" if JOINed +endif + jnz build_remote_path20 ; it's remote, go build a path + xor cx,cx ; CY clear (no error) + inc cx ; CX <> 0, (non-remote drive) + ret + +build_remote_path20: +; Build a path from the CSD and the pathname in the parameter block + mov si,cx ; DS:SI -> source ASIIZ name + push ss ! pop es ; ES:DI -> MSNET buffer + call redir_build_path + jc build_remote_path30 + xor cx,cx ; CY clear, CX == 0 + ret ; it's a valid remote path + +build_remote_path30: + stc ; CY set, we have error BX + ret + + + +eject +; MAKE DIRECTORY (MKDIR) + +; +----+----+----+----+----+----+ +; | 39 | name | +; +----+----+----+----+----+----+ + +; entry: +; ------ +; name: segmented address of ASCIIZ name + +; exit: +; ----- +; BX: 0000 or error code ( < 0) + +redir_mkdir: + mov ax,I2F_MKDIR ; it's a make dir + jmps redir_pathop_common + + +eject +; REMOVE DIRECTORY (RMDIR) + +; +----+----+----+----+----+----+ +; | 3A | name | +; +----+----+----+----+----+----+ + +; entry: +; ------ +; name: segmented address of ASCIIZ name + +; exit: +; ----- +; BX: 0000 or error code ( < 0) + + +redir_rmdir: + mov ax,I2F_RMDIR ; it's a remove dir +; jmp redir_pathop_common + +redir_pathop_common: + push ds + push ss ! pop ds + call int2f_ldt + pop ds + jc redir_pathop_common10 + xor ax,ax ; no problems +redir_pathop_common10: + xchg ax,bx ; return result in BX + ret + + + +eject +; CHANGE DIRECTORY (CHDIR) + +; +----+----+----+----+----+----+ +; | 3B | name | +; +----+----+----+----+----+----+ + +; entry: +; ------ +; name: segmented address of ASCIIZ name + +; exit: +; ----- +; BX: 0000 or error code ( < 0) + +redir_chdir: +;------------ +; The following code throws out the ASSIGN/SUBST form "f:=d:\" +; The alternative is to allow the Extentions to throw it out as a bad path +; but this is safer, and doesn't cost us much. + + push ds + mov bx,ED_PATH ; assume we have a problem + ; BX = ED_PATH ready for error + + mov si,2[bp] ; SI -> parameter block + lds si,ds:2[si] ; DS:SI -> ASCIIZ string + cmp ds:word ptr 1[si],'=:' ; 'd:=' specification? + je redir_chdir40 + + push ss ! pop ds ; DS = PCMODE + + cmp word ptr current_ldt,-1 + je redir_chdir40 ; we reject any chdir of the form + ; "\\server\path" + mov ax,I2F_CHDIR + call int2f_ldt ; is this a valid path ? + jc redir_chdir30 + push ds ! pop es + mov si,offset pri_pathname + +; DGM - don't allow path greater than 66 chars + mov cx, LDT_FLAGS-LDT_NAME ; calculate max pathlen from LDT + mov di, si + sub ax,ax + repne scasb + mov ax, ED_PATH ; assume path too long + jne redir_chdir30 ; jump if path too long + + les di,current_ldt ; ES:DI -> path for this drive + call copy_asciiz ; copy new path to LDT current dir + xor ax,ax ; no errors +redir_chdir30: + xchg ax,bx ; return result in BX +redir_chdir40: + pop ds + ret + + +eject +; CREATE FILE (CREAT) + +; +----+----+----+----+----+----+----+----+ +; | 3C | name | mode | +; +----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; name: segmented address of ASCIIZ name +; mode: attribute for file + +; exit: +; ----- +; BX: file handle or error code ( < 0) + + +redir_creat: + call get_attrib_mode ; AX = mode, CX = attrib + xchg ax,cx + or ax,20h ; set the ARCHIVE bit on create + mov file_attrib,ax + mov int2f_stack,ax ; attrib on stack + mov int2f_cmd,I2F_CREATE + cmp word ptr current_ldt,-1 ; valid LDT ? + jne redir_creat10 ; no, modify create function + mov int2f_cmd,I2F_XCREATE +redir_creat10: + jmp redir_open_create_common + + +eject +; OPEN FILE (OPEN) + +; +----+----+----+----+----+----+----+----+----+----+ +; | 3D | name | mode | attrib | +; +----+----+----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; name: segmented address of ASCIIZ name +; mode: open mode +; attrib: file attrib for search (default = 16h) + +; exit: +; ----- +; BX: file handle or error code ( < 0) + +redir_open: +;---------- +; + call get_attrib_mode ; AX = mode, CX = attrib + and ax,7fh ; remove inheritance bit + mov int2f_stack,ax + mov int2f_cmd,I2F_OPEN +redir_open_create_common: + call find_xfn ; get external file handle in DI + mov bx,ED_HANDLE ; assume no handles + jc redir_open20 + push di + call redir_openfile ; now do the open + pop di + jc redir_open20 +; On Entry: +; AL = IFN +; DI = XFN +; ES:BX -> DHNDL_ +; On Exit: +; PSP fixed up +; + mov bx,di + call get_xftptr ; ES:DI -> XFN table + jc redir_open10 ; no PSP, skip xfn stuff + add di,bx ; add external file # + stosb ; update table entry + ret + +redir_open10: + xchg ax,bx ; no PSP, return XFN in BX +redir_open20: + ret + + +redir_openfile: +;-------------- +; On Entry: +; pri_pathname and file_attrib have been set up +; On Exit: +; AL = IFN +; ES:BX = DHNDL_ +; CY set on error, BX = error code +; We should set up COUNT, MODE, UID, PSP, and SHARE + call find_dhndl ; find DHNDL_ + jc redir_openf40 ; return if a problem with this + push ax ; save IFN + push es ! push bx ; save DHNDL_ + + mov ax,file_mode + and al,not DHM_LOCAL + mov es:DHNDL_MODE[bx],ax ; save mode in DOSHNDL + mov es:DHNDL_SHARE[bx],0 ; zero share record + + mov ax,int2f_cmd ; either open or create + call int2f_dhndl ; lets try the command + + pop bx ! pop es ; recover DHNDL_ + pop dx ; recover IFN + jc redir_openf30 ; on error discard the handle + xchg ax,dx ; return AL = IFN + mov es:DHNDL_COUNT[bx],1 ; handle now properly in use + mov cx,file_mode + test ch,DHM_FCB/256 ; is this an FCB open ? + jz redir_openf10 + or es:byte ptr DHNDL_MODE+1[bx],DHM_FCB/100h +redir_openf10: + test cl,DHM_LOCAL ; is it a "private" file ? + jz redir_openf20 + or es:byte ptr DHNDL_WATTR+1[bx],DHAT_LOCAL/100h +redir_openf20: + ret + +redir_openf30: + xchg ax,bx ; returning error in BX + ret + +redir_openf40: + mov bx,ED_HANDLE ; no handles are left + ret + +eject +; CLOSE FILE (CLOSE) + +; +----+----+----+----+ +; | 3E | handle | +; +----+----+----+----+ + +; entry: +; ------ +; handle: open file handle to be closed + +; exit: +; ----- +; BX: 0000 or error code ( < 0) + +redir_close: +;------------ +; + mov si,2[bp] ; SI -> parameter block + mov ax,2[si] ; get external file # + call get_xftptr ; ES:DI -> xft table + jc redir_close10 + add di,ax ; add in XFN + mov ax,0FFh ; get "unused" value for XFT + xchg al,es:[di] ; release file & get internal # +redir_close10: ; we can now do the actual close + call ifn2dhndl ; ES:BX -> DHNDL_ + jc redir_close30 ; exit if error occurrs + mov ax,es:DHNDL_COUNT[bx] + mov ah,3eh ; count, AH = 3E + push ax + mov ax,I2F_CLOSE + call int2f_dhndl ; close it + pop bx + jnc redir_close20 ; errors ? + xchg ax,bx ; recover return code +redir_close20: + ret +redir_close30: + mov bx,ED_H_MATCH ; assume invalid IFN + ret + +eject +; READ FROM FILE (READ) + +; +----+----+----+----+----+----+----+----+----+----+ +; | 3F | handle | buffer | count | +; +----+----+----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; handle: open file handle +; buffer: buffer to read into +; count: max. number of bytes to read + +; exit: +; ----- +; BX: error code ( < 0) + +redir_read: +;---------- + mov ax,I2F_READ +redir_rw_handle: + mov si,2[bp] ; SI -> parameter block + mov cx,8[si] ; CX = Count + push ds + lds dx,4[si] ; DS:DX = DMA address + call redir_rw + pop ds + mov si,2[bp] ; SI -> parameter block + mov 8[si],cx ; CX = Count + ret + +eject +; WRITE TO FILE (WRITE) + +; +----+----+----+----+----+----+----+----+----+----+ +; | 40 | handle | buffer | count | +; +----+----+----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; handle: open file handle +; buffer: buffer to be wriiten +; count: max. number of bytes to write + +; exit: +; ----- +; BX: error code ( < 0) + +redir_write: +;----------- + mov ax,I2F_WRITE + jmps redir_rw_handle + +redir_rw: +;-------- +; On Entry: +; AX = command code +; ES:BX = DHNDL_ +; CX = count +; DS:DX = buffer +; On Exit: +; CX = count transferred +; BX = zero or error code +; + cmp ax,I2F_WRITE ; is it a write ? + jne redir_rw10 + and es:DHNDL_WATTR[bx],not (DHAT_CLEAN+DHAT_TIMEOK) +redir_rw10: + push ss:dma_offset + push ss:dma_segment + push cx + mov cl,4 + mov di,dx ; save dma offset + and dx,15 ; make offset within para + shr di,cl ; convert offset to para offset + mov si,ds ; add to segment + add di,si ; DI:DX -> DMA address + ja redir_rw15 ; are we within normal TPA ? + inc di ; no adjust to offset within + shl di,cl ; magic segment FFFF + add dx,di + mov di,0ffffh ; use magic segment +redir_rw15: + pop cx + mov ss:dma_offset,dx ; save for xfer + mov ss:dma_segment,di + call int2f_dhndl ; try the xfer + pop ss:dma_segment + pop ss:dma_offset + mov bx,0 ; assume no error + jnc redir_rw20 + xchg ax,bx ; return error code + cmp bx,ED_LOCKFAIL ; is it a lockfail error ? + jne redir_rw20 ; no, just return it + les di,ss:current_dhndl ; compatibility modes should generate + test es:DHNDL_MODE[di],DHM_SHAREMSK + jz redir_rw20 ; critical errors fro ED_LOCKFAIL + mov bx,ED_ACCESS ; sharing modes return access denied +redir_rw20: + ret + + +eject +; DELETE FILE (UNLINK) + +; +----+----+----+----+----+----+ +; | 41 | name | +; +----+----+----+----+----+----+ + +; entry: +; ------ +; name: segmented address of ASCIIZ name + +; exit: +; ----- +; BX: 0000 or error code ( < 0) + + +redir_unlink: + mov ax,I2F_DEL ; it's a delete +; mov file_attrib,6 ; only delete files +redir_unlink_move_common: + push ax + call get_attrib_mode ; allow overrides for server calls + pop ax + jmp redir_pathop_common + +eject +; GET/SET FILE POSITION (LSEEK) + +; +----+----+----+----+----+----+----+----+----+----+ +; | 42 | handle | offset | method | +; +----+----+----+----+----+----+----+----+----+----+ + +; On Entry: +; ES:BX = DHDNL_ +; method: 0 = begin, 1 = current, 2 = end of file +; +; On Exit: +; BX = Error Code, offset updated with new value +; + +redir_lseek: +;----------- + mov di,bx ; ES:DI -> DHNDL_ + mov si,2[bp] ; SI -> parameter block + mov dx,4[si] ; get 32-bit file offset + mov cx,6[si] ; into CX,DX + mov ax,8[si] ; get seek mode + test ax,ax + jz redir_lseek20 ; seek from beginning + dec ax + jz redir_lseek10 ; seek from current position + dec ax + jz redir_lseek30 ; seek from end + mov bx,ED_DATA ; else invalid seek mode + ret + +redir_lseek10: ; seek mode 1: relative to position + add dx,es:DHNDL_POSLO[di] ; add position + offset + adc cx,es:DHNDL_POSHI[di] +; jmps redir_lseek20 + +redir_lseek20: ; seek mode 0: set absolute position + mov es:DHNDL_POSLO[di],dx ; set new file offset + mov es:DHNDL_POSHI[di],cx ; SI = error code/0 at this point +; jmps redir_lseek90 + +redir_lseek90: + mov 4[si],dx ; set 32-bit file offset + mov 6[si],cx ; for return + xchg ax,bx ; error code in BX + ret + +redir_lseek30: ; seek mode 2: relative to end + mov bx,es:DHNDL_MODE[di] ; ask MSNET if anyone else can write + and bl,DHM_SHAREMSK ; isolate sharing bits + cmp bl,DHM_DENY_READ ; Only DENY_READ and DENY_NONE a + jb redir_lseek40 ; problem - others might write to + push si ; the file so we must ask the server + ; how long the file is now + mov ax,I2F_LSEEK ; CX:DX = position now + call int2f_dhndl ; do a remote seek + pop si ; DX:AX = EOF relative position + jc redir_lseek90 ; (unless we have an error) + xchg ax,dx ; AX:DX = new EOF relative position + xchg ax,cx ; and finally get into CX:DX + xor ax,ax ; no problems... + ;jmps redir_lseek90 ; MYST-removed,file offset wasn't updated + jmps redir_lseek20 ; MYST-added,go and update the new file offset. +redir_lseek40: + add dx,es:DHNDL_SIZELO[di] ; add file size + offset + adc cx,es:DHNDL_SIZEHI[di] + jmps redir_lseek20 + + +eject +; GET/SET FILE ATTRIBUTES (CHMOD) + +; +----+----+----+----+----+----+----+----+----+----+ +; | 43 | name | flag | attrib | +; +----+----+----+----+----+----+----+----+----+----+ +; | size | +; +----+----+----+----+ + +; entry: +; ------ +; name: pointer to ASCIIZ file name +; flag: 0 = get attribute, +; 1 = set attribute, +; 2-5 = passwords (ignored) +; attrib: new attribute if flag = 1 +; password mode if flag = 3 +; +; exit: +; ----- +; BX: 0000 or error code ( < 0) +; attrib: file's attribute if flag = 0 +; size: file's size + +redir_chmod: +;----------- +; + mov bx,2[bp] ; BX -> parameter block + mov cx,8[bx] ; get attribs + mov bx,6[bx] ; get access flag + mov ax,I2F_SET_ATTR ; assume it's a set + cmp bl,1 ; is it a set ? + je redir_chmod10 ; if not then + mov ax,I2F_GET_ATTR ; assume it's a get + mov cx,16h ; with everything attribs + jb redir_chmod10 ; was it ? + mov ax,ED_ACCESS ; no, return access denied + jmps redir_chmod20 ; cause it DR password stuff +redir_chmod10: + mov int2f_stack,cx ; attribs on the stack + call int2f_ldt ; do the Int 2F + jc redir_chmod20 + mov si,2[bp] ; SI -> parameter block + mov 8[si],ax ; return attribute + mov 10[si],di + mov 12[si],bx + xor ax,ax ; success +redir_chmod20: + xchg ax,bx ; return result in BX + ret + +eject +; GET DISK PARAMETER BLOCK + +; +----+----+----+----+----+----+----+----+----+----+ +; | 48 | drive | dpb | adjust | +; +----+----+----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; drive: drive to get information about + +; exit: +; ----- +; BX: 0000 or error code ( < 0) +; dpb: address of DOS DPB (offset/segment) +; adjust: delwatch adjustment of free space + +; NB. We only fill in the fields required by the Disk Free Space call. + +redir_getdpb: +;------------ + mov ax,I2F_SPACE + call int2f_ldt ; get the info + jnc redir_getdpb10 ; if we get an error then make CLMSK=FE + mov al,0ffh +redir_getdpb10: + mov si,offset sec_pathname ; let's re-use this as a temp DPB + dec al ; make cluster mask + mov ds:DDSC_CLMSK[si],al ; and stuff into DPB + mov ds:DDSC_FREE[si],dx + mov ds:DDSC_SECSIZE[si],cx + inc bx ; inc number of clusters + mov ds:DDSC_NCLSTRS[si],bx + mov al,err_drv ; also fill in drive number + mov ds:DDSC_UNIT[si],al + mov si,2[bp] ; DI -> parameter block + mov 4[si],offset sec_pathname + mov 6[si],ds ; point to my dummy DPB + mov word ptr 8[si],0 ; zero adjust value + mov bx,0ffh ; return 0xFF (ie. bad drive) + ret + +eject +; FIND FIRST FILE + +; +----+----+----+----+----+----+----+----+----+----+ +; | 4E | name | ***** | attrib | +; +----+----+----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; name: pointer to ASCIIZ file name +; attrib: attribute to be used in search +; +; exit: +; ----- +; BX: 0001 or error code ( < 0) + +; Note: This call returns matching files in +; the current DMA address and also saves +; the BDOS state in the there. +; +; If there is space for multiple file names we +; could return as many as will fit into the DTA +; but it's easier just to return 1 file +; + +redir_first: ; 13-find first matching file +;---------- +; ONLY 1 file returned for now..... +; + call get_attrib_mode ; AX = mode, CX = attrib + mov ax,I2F_SFIRST ; srch first, valid LDT + les di,current_ldt + cmp di,-1 ; valid LDT ? + jne redir_first10 + mov ax,I2F_XSFIRST ; srch first, no valid LDT +redir_first10: + jmps srch_buf_common + +eject +; FIND NEXT FILE + +; +----+----+ +; | 4F | +; +----+----+ +; +; entry: +; ------ +; +; exit: +; ----- +; BX: 0000 or error code ( < 0) + +; Note: This call returns matching files in +; the current DMA address and also saves +; the BDOS state in the there. + +redir_next: ; 14-find next matching file +;--------- +; ONLY 1 file returned for now..... +; + push ss ! pop es + mov di,offset srch_buf ; point ES:DI -> search buffer + mov ax,I2F_SNEXT +srch_buf_common: + push dma_offset + push dma_segment + mov dma_offset,offset srch_buf + mov dma_segment,ds + call int2f_op + + pop dma_segment + pop dma_offset + jc srch_buf_common10 + call redir_save_srch_state ; if no error save state + xor ax,ax ; return AX = 1 file found +srch_buf_common10: + xchg ax,bx ; return code in BX + ret + + +redir_save_srch_state: +; On entry DS=PCMODE + les di,dword ptr dma_offset ; ES:DI -> search state in DMA address + + mov si,offset srch_buf + mov cx,21 ; save 1st 21 bytes + rep movsb + + push si ; save name/ext + add si,11 ; skip to name/ext + movsb ; copy the attribute + add si,10 ; skip reserved bytes + movsw ; copy the time + movsw ; copy the date + add si,2 ; skip starting cluster + movsw ; copy the file size + movsw + pop bx ; recover name + jmp unparse ; unparse the name + +; Restore DOS search area from user DTA +; +redir_restore_srch_state: +;------------------------ +; On Entry: +; DS = SYSDAT +; On Exit: +; AL = 1st byte of srch buf +; DS preserved +; + push ss + pop es + mov di,offset srch_buf ; ES:DI -> internal state + push ds + lds si,ss:dword ptr dma_offset + lodsb ; DS:SI -> search state in DMA address + stosb + mov cx,20 ; copy 1st 21 bytes + rep movsb + pop ds + ret + +eject +; COMMIT FILE (COMMIT) + +; +----+----+----+----+ +; | 50 | handle | +; +----+----+----+----+ + +; entry: +; ------ +; handle: open file handle to be flushed + +; exit: +; ----- +; BX: 0000 or error code ( < 0) + +redir_commit: + test es:DHNDL_MODE[bx],DHM_WO+DHM_RW + jz redir_commit10 ; we don't need to commit it + mov ax,I2F_COMMIT + call int2f_dhndl ; commit this file + jc redir_commit20 +redir_commit10: + xor ax,ax ; success +redir_commit20: + xchg ax,bx ; return result in BX + ret + + +eject +; CREATE NEW FILE + +; +----+----+----+----+----+----+----+----+ +; | 51 | name | mode | +; +----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; name: segmented address of ASCIIZ name +; mode: attribute for file + +; exit: +; ----- +; BX: file handle or error code ( < 0) + +; Note: The function is identical to CREATE FILE +; with the exception that an error is returned +; if the specified file already exists. + +redir_mknew: + call get_attrib_mode ; AX = mode, CX = attrib + xchg ax,cx + or ax,120h ; set ARCHIVE + MKNEW bits + mov file_attrib,ax + mov int2f_stack,ax + mov int2f_cmd,I2F_CREATE + mov file_mode,DHM_RW ; Open Compatibility mode, Read/Write + jmp redir_open_create_common + +eject +; LOCK/UNLOCK FILE DATA (LOCK/UNLOCK) + +; +----+----+----+----+----+----+----+----+ +; | 52 | handle | offset | +; +----+----+----+----+----+----+----+----+ +; | length | lock | +; +----+----+----+----+----+----+ + +; entry: +; ------ +; handle: open file handle +; offset: long integer offset +; length: long integer byte count +; lock: 0 = lock, 1 = unlock + +; exit: +; ----- +; BX: byte count or error code ( < 0) + +redir_lock: +; Lock uses I2F_LOCK, with CX,DX,SI as per INT 21, DI on stack +; Unlock uses I2F_UNLOCK with same. + mov bx,2[bp] ; BX -> parameter block +if DOS5 + push bp + lea bp,4[bx] ; BP -> parameter block + mov dx,bp ; as does DX + mov ax,I2F_LOCK + mov bl,ds:byte ptr 12[bx] + mov bh,5Ch ; lock/unlock in BX + call int2f_dhndl ; try the operation + pop bp +else + mov dx,ds:4[bx] ; get low word of offset in DX + mov cx,ds:6[bx] ; and the hi word in CX + mov di,ds:8[bx] ; get low word of length in DI + mov si,ds:10[bx] ; and high in SI + mov int2f_stack,di ; length low is on stack + mov ax,I2F_LOCK ; assume lock + cmp ds:word ptr 12[bx],0 + je redir_lock10 + mov ax,I2F_UNLOCK ; no, it must be unlock +redir_lock10: + call int2f_dhndl ; try the operation +endif + jc redir_lock20 + xor ax,ax ; success +redir_lock20: + xchg ax,bx ; return result in BX + ret + + +eject +; EXPAND FILE + +; +----+----+----+----+----+----+----+----+----+----+ +; | 55 | old name | new name | +; +----+----+----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; old name: segmented address of ASCIIZ name +; new name: segmented address of ASCIIZ name + +; exit: +; ----- +; BX: 0000 or error code ( < 0) + +; If we got here pri_pathname already contains expanded name - just copy it +; back to the users buffer. + +redir_expand: +;------------ + mov si,2[bp] ; SI -> parameter block + les di,10[si] ; ES:DI -> user supplied name + mov si,offset pri_pathname + call copy_asciiz + xor bx,bx ; no errors + ret + +eject +; RENAME FILE + +; +----+----+----+----+----+----+----+----+----+----+ +; | 56 | old name | new name | +; +----+----+----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; old name: segmented address of ASCIIZ name +; new name: segmented address of ASCIIZ name + +; exit: +; ----- +; BX: 0000 or error code ( < 0) + +; Note: R/O files can be renamed. +; --- + +redir_move: + mov ax,I2F_REN ; it's a rename + jmp redir_unlink_move_common + +eject +; GET/SET FILE DATE/TIME + +; +----+----+----+----+----+----+----+----+----+----+ +; | 57 | handle | mode | date | time | +; +----+----+----+----+----+----+----+----+----+----+ + +; entry: +; ------ +; handle: open file handle +; mode: 0 = get date/time, 1 = set date/time +; date: date as in directory FCB +; time: time as in directory FCB + +; exit: +; ----- +; BX: 0000 or error code ( < 0) +; date: date of last modification if mode = 0 +; time: date of last modification if mode = 0 + +redir_dattim: +;------------ + mov si,2[bp] ; DS:SI -> param block + cmp ds:word ptr 4[si],1 ; is it set ? + ja redir_dattim30 ; if illegal say so + je redir_dattim10 + mov ax,es:DHNDL_DATE[bx] ; we need to copy the file date + mov word ptr 6[si],ax ; into the parameter block + mov ax,es:DHNDL_TIME[bx] + mov word ptr 8[si],ax ; and the time + jmps redir_dattim20 +redir_dattim10: + mov ax,word ptr 6[si] ; copy the date we are given + mov es:DHNDL_DATE[bx],ax ; into the DOSHNDL + mov ax,word ptr 8[si] ; and the time + mov es:DHNDL_TIME[bx],ax + or es:DHNDL_WATTR[bx],DHAT_TIMEOK + and es:DHNDL_WATTR[bx],not DHAT_CLEAN +redir_dattim20: + xor bx,bx ; all went OK + jmps redir_dattim40 +redir_dattim30: + mov bx,ED_FUNCTION ; bad function number +redir_dattim40: + ret + + Public redir_build_path + +; AH contains state of path processing, and is normally zero + +BP_DOT equ 1 ; we have had a DOT end are processing the .EXT +BP_WILD equ 2 ; we have encountered a wild card +BP_BSLASH equ 4 ; the last character was a BSLASH + +; May be called with or without MXDisk + +redir_build_path: +;---------------- +; On Entry: +; DS:SI -> source name +; ES:DI -> destination name (in PCMODE data segment) +; current_ldt -> LDT_ for specified drive +; On Exit: +; CY clear if we could build the path +; +; firstly we discard any drive portion + lodsw ; get 1st two characters + cmp ah,':' ; is a drive specified ? + jne redir_bp10 ; discard "d:" if so + lodsw +redir_bp10: +; Is it a "\\server\sharename\subdir\filename.ext" format ? + call check_dslash ; if it is \\ + je redir_bp20 ; then just copy the lot +; it's a normal "A:\subdir\filename.ext" pathname format + dec si ; we have swallowed the 1st two + dec si ; chars - now we change our mind + push ds ! push si + lds si,es:current_ldt + mov cx,ds:LDT_ROOTLEN[si] ; copy the root portion of the name + rep movsb ; copy the server stub name + mov dx,di ; ES:DX -> root position + call check_slash ; do we start from the root ? + je redir_bp11 ; yes, then that's all + call copy_asciiz ; no, copy the rest of the path + call redir_bp_append_slash ; append '\' for our path processing +redir_bp11: + pop si ! pop ds + jmps redir_bp_next_level ; continue processing given path + +redir_bp20: +; It is a "\\server\sharename\subdir\filename.ext" format + stosw ; copy the "\\" + xor ax,ax ; clear "flags" in AH +redir_bp21: + lodsb ; work along the name + test al,al ; unexpected end of name ? + jz redir_bp_exit20 ; go with what we've got.... + call check_slash ; have we found the root '\' ? + je redir_bp23 +if KANJI + call dbcs_lead ; is it the 1st of a kanji pair + jne redir_bp22 ; no, onto next char + stosb ; copy the 1st character + movsb ; copy 2nd byte of KANJI pair + jmps redir_bp21 ; now we can move onto next char +redir_bp22: +endif + call toupper ; upper case the character + stosb ; copy the character + jmps redir_bp21 ; go and do another one + +redir_bp23: + mov dx,di ; bodge root to the top +; mov al,'\' + stosb ; put in a '\' + jmps redir_bp_next_level ; yes, this is the new "root" + +; We have reached the terminating NUL +redir_bp_exit: + test ah,BP_WILD ; did we get any wildcards ? + je redir_bp_exit10 + mov si,2[bp] ; SS:SI -> parameter block + mov al,ss:[si] ; fdos code number + cmp al,MS_X_FIRST ; search first ? + je redir_bp_exit10 + cmp al,FD_EXPAND ; expand pathname + je redir_bp_exit10 + cmp ss:remote_call,0 ; should we wildcard REN/DEL ? + je redir_bp_ED_PATH ; reject as not allowed here + cmp al,MS_X_RENAME ; rename ? + je redir_bp_exit10 + cmp al,MS_X_UNLINK ; delete ? + jne redir_bp_ED_PATH ; reject as not allowed here +redir_bp_exit10: + xor al,al ; make sure our string is zero + stosb ; terminated + call redir_bp_append_slash ; append a trailing '\' if we don't + dec di ; have one so we can remove it + cmp di,dx ; are we talking about the root ? + jne redir_bp_exit20 + cmp es:byte ptr 0FFFFh[di],':' + jne redir_bp_exit20 ; if we have a trailing ':' allow + inc di ; a '\' at the root +redir_bp_exit20: + xor al,al ; KANJI aware way of removing trailing + stosb ; '\' from the path.... +; clc + ret + + +redir_bp_next_level: +; DS:SI -> source pathname, ES:DI -> destination pathname, ES:DX -> root +; AH = current status + mov cx,8 ; expansion count ready + xor ax,ax +redir_bp_next_char: + lodsb + test al,al ; end of the line ? + jz redir_bp_exit ; do the exit + +; Is it a '\' ? +redir_bp40: + call check_slash ; was it a seperator ? + jne redir_bp50 + test ah,BP_WILD ; have we encountered wildcards ? + jnz redir_bp_ED_PATH ; reject as not allowed here + mov al,'\' ; make sure it's a BSLASH + stosb + jmps redir_bp_next_level ; start at a new level + +; Is it a '.' ? +redir_bp50: + cmp al,'.' ; seperator ? + jne redir_bp60 + lodsb ; get next letter + test al,al ; is it trailing '.' ? + je redir_bp_exit ; then exit now + cmp cx,8 ; check for '.' and '..' + je redir_bp52 ; if at start of field +redir_bp51: ; othewise it's a ".EXT" + mov bx,ED_FILE ; assume we have a problem + test ah,BP_DOT ; have we had an extention before ? + jnz redir_bp_err ; we've got a problem + dec si ; rewind a character + mov ax,'.'+256*BP_DOT ; so we are back to the '.' + stosb ; store the '.' in destination + mov cx,3 ; expand the extention + jmps redir_bp_next_char +redir_bp52: ; It might be a "." or ".." + call check_slash ; is it '.\' + je redir_bp_next_char ; discard them both + cmp al,'.' ; is it '..' ? + jne redir_bp51 ; no, must be an extention after all + call redir_bp_ddot ; rewind a level + jnc redir_bp_next_level ; onto next level +redir_bp_ED_PATH: +; set CY flag to indicate error then return + mov bx,ED_PATH ; return "invalid path" error +redir_bp_err: + stc + ret + +; Is it a '*' ? +redir_bp60: + call check_delim ; is it a delimiter ? + jz redir_bp_ED_PATH ; thats illegal at this point + cmp al,'*' ; wildcards ? + jne redir_bp70 + mov al,'?' + rep stosb ; expand it +; or ah,BP_WILD ; remember wild-card encountered +; jmps redir_bp_next_char ; check for wildcards +; +; ; we can just fall through +; +redir_bp70: + cmp al,'?' ; wild card is possibly OK + jne redir_bp80 + or ah,BP_WILD ; remember wild-card encountered +redir_bp80: +; Normal Character +; AL contains a normal character for us to process. +; Uppercase the character, look out for KANJI etc + jcxz redir_bp_next_char ; discard if no space is left + dec cx ; one less to expand +if KANJI + call dbcs_lead ; is it the 1st of a kanji pair + jne redir_bp90 + inc si ; skip 2nd byte + jcxz redir_bp_next_char ; discard if no room for kanji char + dec cx ; one less to expand + stosb ; store 1st byte of kanji character + dec si ; point at 2nd byte again + movsb ; copy 2nd byte of kanji character + jmps redir_bp_next_char +redir_bp90: +endif + call toupper ; make it upper case + stosb ; plant the character + jmps redir_bp_next_char + + +redir_bp_ddot: +; We have encountered a '..' in a pathname, so rewind up a level +; On Entry: +; DS:SI -> source position, ES:DI -> destination position +; ES:DX -> root position, AL = Character +; On Exit: +; ES:DI -> start of field one level up, unless we get an error when CY set. + lodsb ; look at char after '..' + call check_slash ; is it '..\' + je redir_bp_ddot10 + test al,al ; is it a trailing '..' + jnz redir_bp_ED_PATH ; no, anything else is bad... + dec si ; trailing '..', rewind to NUL +redir_bp_ddot10: + dec di ; move back to last '\' + cmp di,dx ; are we at the root anyway ? + jle redir_bp_ED_PATH ; then don't discard any +; We now start at ES:DX and work along till ES:DI -> char after last '\' + push ds ! push si + push es ! pop ds + mov si,dx ; DS:SI -> char after root + mov cx,dx ; last '\' position in CX +redir_bp_ddot20: + lodsb + cmp si,di ; end of the line yet ? + jae redir_bp_ddot30 ; yes, stop now +if KANJI + call dbcs_lead ; is it 1st of a kanji pair ? + jne redir_bp_ddot25 + lodsb ; skip the 2nd too + jmps redir_bp_ddot20 ; then go on to next char +redir_bp_ddot25: +endif + call check_slash ; is it a '\' + jne redir_bp_ddot20 ; no, do next + mov cx,si ; save position after the '\' + jmps redir_bp_ddot20 +redir_bp_ddot30: + mov di,cx ; last '\' was here.. + pop si ! pop ds + clc ; no errors + ret + +redir_bp_append_slash: +; On Entry: +; ES:DX -> ASCIIZ string to append a '\' to +; On Exit: +; ES:DI -> terminating NUL +; All but AX preserved +; + xor ax,ax ; AH = 0, initially no previous char + mov di,dx ; start processing from here +redir_bp_append_slash10: + mov ah,al ; save previous char in AH + mov al,es:[di] ; get a character + inc di ; point to next + test al,al ; is it NUL ? +if KANJI + je redir_bp_append_slash20 + call dbcs_lead ; is it 1st of a kanji pair ? + jne redir_bp_append_slash10 + inc di ; skip the 2nd too + jmps redir_bp_append_slash10 ; (it might be '\') +redir_bp_append_slash20: +else + jnz redir_bp_append_slash10 +endif + mov al,ah ; get previous char + call check_slash ; did we have a '\' ? + je redir_bp_append_slash30 + dec di ; ES:DI -> existing NUL + mov ax,'\' + stosw ; new terminating '\' +redir_bp_append_slash30: + dec di ; ES:DI -> NUL + ret + + + +get_attrib_mode: +;--------------- +; On Entry: +; SS:2[BP] -> param block +; On Exit: +; AX = file mode +; CX = file attributes +; + mov si,2[bp] ; SI -> parameter block + mov ax,ds:6[si] ; get mode + mov cx,ds:8[si] ; get attribs + mov file_mode,ax ; save open mode + mov file_attrib,cx ; save file attribute + ret + +int2f_ldt: +;--------- +; On Entry: +; AX = Int2F command +; On Exit: +; CY clear, AX returned unchanged +; CY set, AX = Our Negative Error Code +; + les di,ss:current_ldt + jmps int2f_op + +int2f_dhndl: +;---------- +; On Entry: +; AX = Int2F command +; On Exit: +; CY clear, AX returned unchanged +; CY set, AX = Our Negative Error Code +; + les di,ss:current_dhndl +int2f_op: + push ds + push ss ! pop ds + push int2f_stack ; put word on stack + int 2fh ; get the info + pop int2f_stack ; clean up the stack + pop ds + jnc int2f_op10 + neg ax ; AX = we keep error codes negative +; stc ; we have a problem +int2f_op10: + ret + +end diff --git a/IBMDOS/REDIR.EQU b/IBMDOS/REDIR.EQU new file mode 100644 index 0000000..7e93da8 --- /dev/null +++ b/IBMDOS/REDIR.EQU @@ -0,0 +1,67 @@ +; File : $REDIR.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +; Int 2F AH=11 msnet redirector hook equates + +I2F_PRESCENCE equ 1100h +I2F_RMDIR equ 1101h +I2F_MKDIR equ 1103h +I2F_CHDIR equ 1105h +I2F_CLOSE equ 1106h +I2F_COMMIT equ 1107h +I2F_READ equ 1108h +I2F_WRITE equ 1109h +I2F_LOCK equ 110Ah +I2F_UNLOCK equ 110Bh +I2F_SPACE equ 110Ch +I2F_SET_ATTR equ 110Eh +I2F_GET_ATTR equ 110Fh +I2F_REN equ 1111h +I2F_DEL equ 1113h +I2F_OPEN equ 1116h +I2F_CREATE equ 1117h +I2F_XCREATE equ 1118h +I2F_XSFIRST equ 1119h +I2F_SFIRST equ 111Bh +I2F_SNEXT equ 111Ch +I2F_PCLOSE equ 111Dh +I2F_REDIR_5F equ 111Eh +I2F_REDIR_5E equ 111Fh +I2F_FLUSH equ 1120h +I2F_LSEEK equ 1121h +I2F_PTERM equ 1122h +I2F_PPATH equ 1123h +I2F_CTLP_ERR equ 1124h +I2F_REDIR_5D equ 1125h +I2F_CTLP equ 1126h + diff --git a/IBMDOS/REQHDR.EQU b/IBMDOS/REQHDR.EQU new file mode 100644 index 0000000..753461a --- /dev/null +++ b/IBMDOS/REQHDR.EQU @@ -0,0 +1,166 @@ +; File : $REQHDR.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG + +CMD_INIT equ 0 ; Initialize the Device Driver +CMD_MEDIA_CHECK equ 1 ; Request Media Check +CMD_BUILD_BPB equ 2 ; Build Drive BPB +CMD_INPUT_IOCTL equ 3 ; IOCTL input +CMD_INPUT equ 4 ; Input +CMD_INPUT_NOWAIT equ 5 ; Non destructive input no wait +CMD_INPUT_STATUS equ 6 ; Input status +CMD_INPUT_FLUSH equ 7 ; Input flush +CMD_OUTPUT equ 8 ; Output +CMD_OUTPUT_VERIFY equ 9 ; Output with verify +CMD_OUTPUT_STATUS equ 10 ; Output status +CMD_OUTPUT_FLUSH equ 11 ; Output flush +CMD_OUTPUT_IOCTL equ 12 ; IOCTL output +CMD_DEVICE_OPEN equ 13 ; Device OPEN +CMD_DEVICE_CLOSE equ 14 ; Device CLOSE +CMD_FIXED_MEDIA equ 15 ; Removeable Media Check +CMD_GENERIC_IOCTL equ 19 ; Generic IOCTL +CMD_GET_DEVICE equ 23 ; Get the Logical Device +CMD_SET_DEVICE equ 24 ; Set the Logical Device +CMD_QUERY_IOCTL equ 25 ; query ioctl support + +; Generic Request Header Format + +RH_LEN equ es:byte ptr 0[bx] +RH_UNIT equ es:byte ptr 1[bx] +RH_CMD equ es:byte ptr 2[bx] +RH_STATUS equ es:word ptr 3[bx] + RHS_DONE equ 0100h + RHS_BUSY equ 0200h + RHS_IC equ 0400h ; Interim Character + RHS_RM equ 0800h + RHS_ERROR equ 8000h + +;****** +;* No longer safe to use - some device drivers trample on them.... +;* +;* RH_STRATEGY equ es:dword ptr 5[bx] ; Device Strategy Routine +;* RH_STRATOFF equ es:word ptr 5[bx] ; Strategy Offset +;* RH_STRATSEG equ es:word ptr 7[bx] ; Strategy Segment +;* RH_INTERRUPT equ es:dword ptr 9[bx] ; Device Interrupt Routine +;* RH_INTOFF equ es:word ptr 9[bx] ; Intterupt Offset +;* RH_INTSEG equ es:word ptr 11[bx] ; Interrupt Segment +;***** + +; Request header for initialization + +RH0_NUNITS equ es:byte ptr 13[bx] +RH0_RESIDENT equ es:word ptr 14[bx] +RH0_BPBOFF equ es:word ptr 18[bx] +RH0_BPBSEG equ es:word ptr 20[bx] +RH0_DRIVE equ es:byte ptr 22[bx] +RH0_LEN equ 22 + +; Request header for media check + +RH1_MEDIA equ es:byte ptr 13[bx] ; BDOS: current media byte +RH1_RETURN equ es:byte ptr 14[bx] ; driver: return code (00, 01, FF) +RH1_VOLID equ es:dword ptr 15[bx] ; driver: volume label address +RH1_LEN equ 15 + +; Request header for "build BPB" + +RH2_MEDIA equ es:byte ptr 13[bx] ; BDOS or driver? +RH2_BUFFER equ es:dword ptr 14[bx] ; BDOS: scratch buffer for driver use +RH2_BPB equ es:dword ptr 18[bx] ; same as the following: +RH2_BPBOFF equ es:word ptr 18[bx] ; driver: address of new BPB +RH2_BPBSEG equ es:word ptr 20[bx] +RH2_LEN equ 24 + +; Request header for input/output + +RH4_MEDIA equ es:byte ptr 13[bx] ; BDOS: current media byte +RH4_RIC equ es:byte ptr 13[bx] ; BDOS: Return Interim Char flg +RH4_BUFFER equ es:dword ptr 14[bx] ; BDOS: disk transfer address +RH4_BUFOFF equ es:word ptr 14[bx] ; BDOS: Buffer Offset +RH4_BUFSEG equ es:word ptr 16[bx] ; BDOS: Buffer Segment +RH4_COUNT equ es:word ptr 18[bx] ; BDOS: sector count +RH4_SECTOR equ es:word ptr 20[bx] ; BDOS: starting sector +RH4_VOLID equ es:dword ptr 22[bx] ; driver: volume if illegal disk change +RH4_BIGSECTOR equ es:dword ptr 26[bx] +RH4_BIGSECTORLO equ es:word ptr 26[bx] +RH4_BIGSECTORHI equ es:word ptr 28[bx] + +RH4_LEN equ 30 + +; Request Header for Non-Destructive Input + +RH5_CHAR equ es:byte ptr 13[bx] ; Character Read from Device +RH5_RIC equ es:byte ptr 13[bx] ; BDOS: Return Interim Char flg +RH5_LEN equ 14 + +; Request Header for Device Open + +RH13_LEN equ 13 + +; Request Header for Device Close + +RH14_LEN equ 13 + +; Request header for generic IOCTL + +RH19_CATEGORY equ es:word ptr 13[bx] ; BDOS: major/minor function number +RH19_MAJOR equ es:byte ptr 13[bx] ; BDOS: Major Function Number +RH19_MINOR equ es:byte ptr 14[bx] ; BDOS: Minor Function Number +RH19_SI equ es:word ptr 15[bx] ; BDOS: User SI +RH19_DI equ es:word ptr 17[bx] ; BDOS: User DI +RH19_GENPB equ es:dword ptr 19[bx] ; BDOS: extra parameters +RH19_LEN equ 23 + +RQ19_SET equ 40h ; set device parameters +RQ19_GET equ 60h ; get device parameters +RQ19_WRITE equ 41h ; write tracks +RQ19_READ equ 61h ; read tracks +RQ19_FORMAT equ 42h ; format tracks +RQ19_VERIFY equ 62h ; verify tracks + +RQ19_PRP_START equ 4Ch ; start of codepage prepare +RQ19_PRP_END equ 4Dh ; end of codepage prepare +RQ19_SELECT equ 4Ah ; select code page +RQ19_QRY_SEL equ 6Ah ; query selected code page +RQ19_QRY_PRP equ 6Bh ; query prepared code page(s) +RQ19_DSP_SET equ 5Fh ; set display information +RQ19_DSP_GET equ 7Fh ; get display information + +; Request header for get/set drive + +RH24_CMD equ es:byte ptr 14[bx] ; BDOS: Command Code +RH24_STATUS equ es:word ptr 15[bx] ; BDOS: Status +RH24_RESVD equ es:dword ptr 17[bx] ; BDOS: Reserved +RH24_LEN equ 21 + +RH_SIZE equ 30 ; maximum size of request header diff --git a/IBMDOS/RH.EQU b/IBMDOS/RH.EQU new file mode 100644 index 0000000..d3c8361 --- /dev/null +++ b/IBMDOS/RH.EQU @@ -0,0 +1,134 @@ +; File : $RH.EQU$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG +; +; Request command equates + +CMD_INIT equ 0 ; Initialize the Device Driver +CMD_MEDIA_CHECK equ 1 ; Request Media Check +CMD_BUILD_BPB equ 2 ; Build Drive BPB +CMD_INPUT_IOCTL equ 3 ; IOCTL input +CMD_INPUT equ 4 ; Input +CMD_INPUT_NOWAIT equ 5 ; Non destructive input no wait +CMD_INPUT_STATUS equ 6 ; Input status +CMD_INPUT_FLUSH equ 7 ; Input flush +CMD_OUTPUT equ 8 ; Output +CMD_OUTPUT_VERIFY equ 9 ; Output with verify +CMD_OUTPUT_STATUS equ 10 ; Output status +CMD_OUTPUT_FLUSH equ 11 ; Output flush +CMD_OUTPUT_IOCTL equ 12 ; IOCTL output +CMD_DEVICE_OPEN equ 13 ; Device OPEN +CMD_DEVICE_CLOSE equ 14 ; Device CLOSE +CMD_FIXED_MEDIA equ 15 ; Removeable Media Check +CMD_GENERIC_IOCTL equ 19 ; Generic IOCTL +CMD_GET_DEVICE equ 23 ; Get the Logical Device +CMD_SET_DEVICE equ 24 ; Set the Logical Device + +; Request header definition + +RH_LEN equ byte ptr 0 +RH_UNIT equ byte ptr 1 +RH_CMD equ byte ptr 2 +RH_STATUS equ word ptr 3 + RHS_DONE equ 0100h + RHS_BUSY equ 0200h + RHS_RM equ 0800h + RHS_ERROR equ 8000h + +;****** +;* No longer safe to use - some device drivers trample on them.... +;* +;* RH_STRATEGY equ dword ptr 5[bx] ; Device Strategy Routine +;* RH_STRATOFF equ word ptr 5[bx] ; Strategy Offset +;* RH_STRATSEG equ word ptr 7[bx] ; Strategy Segment +;* RH_INTERRUPT equ dword ptr 9[bx] ; Device Interrupt Routine +;* RH_INTOFF equ word ptr 9[bx] ; Intterupt Offset +;* RH_INTSEG equ word ptr 11[bx] ; Interrupt Segment +;***** + +; Request header for media check + +RH1_MEDIA equ byte ptr 13 ; BDOS: current media byte +RH1_RETURN equ byte ptr 14 ; driver: return code (00, 01, FF) +RH1_VOLID equ dword ptr 15 ; driver: volume label address + + +; Request header for "build BPB" + +RH2_MEDIA equ byte ptr 13 ; BDOS or driver? +RH2_BUFFER equ dword ptr 14 ; BDOS: scratch buffer for driver use +RH2_BPB equ dword ptr 18 ; driver: address of new BPB + + +; Request header for input/output + +RH4_MEDIA equ byte ptr 13 ; BDOS: current media byte +RH4_BUFFER equ dword ptr 14 ; BDOS: disk transfer address +RH4_BUFOFF equ word ptr 14 +RH4_BUFSEG equ word ptr 16 +RH4_COUNT equ word ptr 18 ; BDOS: sector count +RH4_SECTOR equ word ptr 22 ; BDOS: starting sector +RH4_VOLID equ dword ptr 24 ; driver: volume if illegal disk change + +; Request Header for Non-Destructive Input + +RH5_CHAR equ byte ptr 13 ; Character Read from Device + +; Request header for generic IOCTL + +RH19_CATEGORY equ word ptr 13 ; BDOS: major/minor function number +RH19_GENPB equ word ptr 19 ; BDOS: extra parameters + +; Request header for get/set logical drive + +RH24_DRIVE equ byte ptr 13 ; Set logical drive + +; Request header lengths + +RH0_LEN equ 22 +RH1_LEN equ 15 +RH2_LEN equ 24 +if DOS5 +RH4_LEN equ 30 +else +RH4_LEN equ 22 ; or 24 for big sectors +endif +RH4_CDEV_LEN equ 22 +RH5_LEN equ 14 +RH12_LEN equ 22 +RH13_LEN equ 13 +RH14_LEN equ 13 +RH15_LEN equ 13 +RH19_LEN equ 23 +RH24_LEN equ 21 + diff --git a/IBMDOS/SUPPORT.A86 b/IBMDOS/SUPPORT.A86 new file mode 100644 index 0000000..e4a9b7a --- /dev/null +++ b/IBMDOS/SUPPORT.A86 @@ -0,0 +1,258 @@ +; File : $SUPPORT.A86$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; SUPPORT.A86 1.11 93/11/29 13:39:28 +; Don't rely on DS when return_ called +; ENDLOG +; +; The following Support routines are provided for both the +; handle and FCB functions which require critical error handler +; support. +; +; 15 Jun 88 Modify the SYSDAT and SUPERVISOR variables to enable +; the relocation of the BDOS into high memory +; 5 Jan 89 Only set PCKBD mode if we own the default console +; 9 Mar 89 Support a split PCMODE and SYSDAT Segments +; 22 Sep 89 LDT support routine added +; 29 Jan 90 Int 2A critical section support added to dpbdos_entry +; 7 Mar 90 Convert to register preserved function calls +; 4 May 90 DRDOS int3x handlers removed (they are pointed to IRET +; in PCMODE_DATA by INIT.PCM) +; 12 Dec 90 keep error server number inverted so local = 0, more compatible + +; + include pcmode.equ + include fdos.def + include i:mserror.equ + include i:doshndl.def + +eject +PCM_CODE CSEG BYTE + extrn error_exit:near ; Standard Error Exit Routine + extrn fcberror_exit:near ; Special FCB function Error Exit + extrn fdos_entry:near + extrn get_dseg:near + +eject +; +; STRLEN determines the length of the string passed in DS:SI +; and returns the byte length in CX. +; + Public strlen +strlen: + push es ! push di + push ds ! pop es + mov di,si + mov cx,0FFFFh + sub al,al + repnz scasb + pop di ! pop es + not cx + dec cx + ret + +eject +; +; This routine sets the address to be returned to by the +; FDOS when an error has occured and the RETRY request has been +; made. The set_retry routine should be used as follows:- +; +; mov al,Valid Error Responses +; call set_retry +; Init All FDOS Parameters +; call fdos_crit +; +; NB. For register model return with AX = dos_AL extended to 16 bit + + Public set_retry_RF +set_retry_RF: + mov al,OK_RF ; Valid to RETRY or FAIL +; jmp set_retry ; (the most common case) + + Public set_retry +set_retry: + mov valid_flg,al ; Save Valid Error Reponses + pop retry_off ; Save the Routine Address + mov retry_sp,sp ; and the Stack Pointer + mov al,ah ; get function number + xor ah,ah ; make it a word + mov FD_FUNC,ax ; save it for the FDOS + push ds + push bx + lds bx,int21regs_ptr ; point to users registers + and reg_FLAGS[bx],not CARRY_FLAG + mov al,reg_AL[bx] ; clear CY assuming we will succeed + pop bx ; and reload AL with entry value + pop ds + jmp retry_off + +; +; The FDOS routine executes the CCP/M FDOS function using the +; static FDOS parameter block defined in the Data Segment. +; + Public fdos_crit +fdos_crit: + call fdos_nocrit + cmp ax,ED_LASTERROR ; Compare against last error code + jnb fdos_error ; if NOT below then is ERROR CODE + or ax,ax ; Reset the Carry Flag and Return + ret + + Public fdos_ax_crit +fdos_ax_crit: + call fdos_nocrit + cmp ax,ED_LASTERROR ; Compare against last error code + jnb fdos_error ; if NOT below then is ERROR CODE + or ax,ax ; Reset the Carry Flag and Return +; jmp return_AX_CLC ; Save the Return Code + + Public return_AX_CLC +return_AX_CLC: +;------------- +; On Entry: +; AX to be returned to caller in AX +; On Exit: +; ES:DI trashed +; + push ds ! push di + lds di,ss:int21regs_ptr + mov reg_AX[di],ax ; return AX to caller + and reg_FLAGS[di],not CARRY_FLAG + pop di ! pop ds + ret + + +fdos_error: ; Process the Error + cmp sp,retry_sp ; Is the user expecting use to + jnz fdos_e10 ; return or use the default handler + jmp error_exit ; If CALLed then return with the error +fdos_e10: ; to the calling routine. + stc + ret + + Public fcbfdos_crit +fcbfdos_crit: + call fdos_nocrit + cmp ax,ED_LASTERROR ; Compare against last error code + jnb fcbfdos_error ; if NOT below then is ERROR CODE + or ax,ax ; Reset the Carry Flag and Return + ret + +fcbfdos_error: ; Process the Error + cmp sp,retry_sp ; Is the user expecting use to + jnz fcbfdos_e10 ; return or use the default handler + jmp fcberror_exit ; If CALLed then return with the error +fcbfdos_e10: ; to the calling routine. + stc + ret + + Public fdos_nocrit +fdos_nocrit: + mov dx,offset fdos_data ; point to fdos parameter block + push ds ! push es + push si ! push di ! push bp + call fdos_entry ; BDOS module entry point + or ax,ax ; Set the Flags + pop bp ! pop di ! pop si + pop es ! pop ds + ret + + + Public reload_ES +reload_ES: +; On Entry: +; None +; On Exit: +; ES = callers ES +; All regs preserved +; + push bx + les bx,ss:int21regs_ptr + mov es,es:reg_ES[bx] ; reload with callers ES + pop bx + ret + + + Public return_BX +return_BX: +;--------- +; On Entry: +; BX to be returned to caller in BX +; On Exit: +; All regs preserved +; + push ds ! push bx + lds si,ss:int21regs_ptr + mov reg_BX[si],bx ; return BX to caller + pop bx ! pop ds + ret + + Public return_CX +return_CX: +;--------- +; On Entry: +; CX to be returned to caller in CX +; On Exit: +; All regs preserved +; + push ds ! push bx + lds bx,ss:int21regs_ptr + mov reg_CX[bx],cx ; return CX to caller + pop bx ! pop ds + ret + + Public return_DX +return_DX: +;--------- +; On Entry: +; DX to be returned to caller in DX +; On Exit: +; All regs preserved +; + push ds ! push bx + lds bx,ss:int21regs_ptr + mov reg_DX[bx],dx ; return DX to caller + pop bx ! pop ds + ret + +PCMODE_DATA DSEG WORD + + + extrn current_psp:word + extrn DBCS_tbl:word ; double byte character set table + extrn int21regs_ptr:dword + extrn retry_off:word + extrn retry_sp:word + extrn valid_flg:byte + + + end + diff --git a/IBMDOS/UTILS.FDO b/IBMDOS/UTILS.FDO new file mode 100644 index 0000000..b0ff10e --- /dev/null +++ b/IBMDOS/UTILS.FDO @@ -0,0 +1,2528 @@ +; File : $UTILS.FDO$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; UTILS.FDO 1.39 94/11/30 13:39:18 +; added share_delay function +; UTILS.FDO 1.37 94/07/13 15:42:01 +; Change to rename/delete of file open in compatibility modes +; UTILS.FDO 1.36 94/06/28 11:10:10 +; Limit ddsc allocation to 1st 255 +; UTILS.FDO 1.34 94/04/25 19:33:04 +; Reject blank names (ie. all spaces) when parsing path +; We used to die in rebuild_ldt_curdir (GATEWAY problem) +; UTILS.FDO 1.33 93/12/16 13:57:06 +; Fix path_prep bug when dir in path doesn't exist +; UTILS.FDO 1.32 93/12/09 23:56:10 +; Move non-inherited bit to correct place in file handle +; UTILS.FDO 1.31 93/12/08 03:30:03 +; Add extra check to offer_join: consider JOIN B: \FRED, SUBST L: \FRED\FRED +; A CD L:\ would see FRED at the root of B: and change into it, so we +; would end up at \FRED, so we only check if ROOTLEN=2 +; UTILS.FDO 1.27 93/11/19 17:45:14 +; Fix for SERVER print queue viewing problem +; UTILS.FDO 1.26 93/11/08 16:30:12 +; Get dat/time on device handle returns current date/time +; UTILS.FDO 1.25 93/09/14 20:03:42 +; Trust LFLG_PHYSICAL +; UTILS.FDO 1.23 93/09/03 20:26:09 +; Add "no critical errors" support (int 21/6C) +; UTILS.FDO 1.22 93/07/26 18:11:00 +; re-arrange DHNDL_DCNTHI for the benefit of Geoworks +; UTILS.FDO 1.21 93/07/20 22:43:48 +; Even fewer checks on int 25/26 +; ENDLOG +; General utility include module for FDOS.A86 + +select_pb2: +;---------- + call get_pb2_drive ; get drive from parameter block +; jmp select_unique ; select drive, make HDS unique + +select_unique: +;------------- +; entry: AL = drive to select (0-15) + + mov byte ptr path_drive,al ; save logical drive + jmp select_logical_drv ; select the drive + + +logical2physical: +;---------------- +; On Entry: +; AL = drive to select +; On Exit: +; AL = appropriate physical drive to select +; +; This routine is called by low level routines (func_ddio, func_getdpb) +; and bypasses the checks for networked/joined drives together with the +; normal media change checks. It does however handle SUBST'd drives. +; + call get_ldt_raw ; ES:BX -> LDT for our drive + jc logical2physical10 ; if we don't have one must be physical + test es:LDT_FLAGS[bx],LFLG_JOINED + jnz logical2physical10 ; joined drive - treat as physical + test es:LDT_FLAGS[bx],LFLG_SUBST + jz logical2physical10 ; as long as we aren't SUBST'd it OK + mov al,es:LDT_NAME[bx] ; get the drive from the ascii name + and al,1fh ; as the drive may require rebuilding + dec ax ; make it zero based +logical2physical10: + ret + + + Public dbcs_lead + +dbcs_lead: +;--------- +; Return true if given byte is the first of a double byte character. +; Entry +; al = byte to be tested +; Exit +; Z Flag = 1 - byte is a DBCS lead +; 0 - byte is not a DBCS lead +; Lost +; no registers changed + +if KANJI + push si + push bx + push ax + +; First get a pointer to the double byte lead table in the COUNTRY info. + mov si, offset DBCS_tbl+2 ; ds:si -> double byte table + +; Examine each entry in the table to see if it defines a range that includes +; the given character. + mov bl, al ; bl = byte to be tested +dbcs_loop: + lods ss:ax ; al/ah = start/end of range + test ax, ax ; end of table? + jz dbcs_no ; yes - exit (not in table) + cmp al, bl ; start <= bl? + ja dbcs_loop ; no - try next range + cmp ah, bl ; bl <= end? + jb dbcs_loop ; no - try next range + + cmp al, al ; return with Z flag set + jmp dbcs_exit + +dbcs_no: + cmp al, 1 ; return with Z flag reset + +dbcs_exit: + pop ax + pop bx + pop si + ret +else + test al, al ; force non-0 condition + ret +endif + + +kanji_eos: +;--------- +; entry: ES:DI -> string to find the end of +; exit: ES:DI -> character before NUL byte + + mov dx,di ; in case string is empty +kanji_eos1: + mov al,es:[di] ; get next character + test al,al ; is it the final NUL byte + jz kanji_eos9 ; return if NUL found + mov dx,di + inc di ; move to next character +if KANJI + call dbcs_lead ; is this first half of 16-bit char? + jne kanji_eos1 ; skip if normal character + inc di ; else skip 2nd half (should really check) +endif + jmps kanji_eos1 ; loop back for next character + +kanji_eos9: + mov di,dx ; ES:DI -> last character + ret ; end of string found + + +path_chop: +;--------- +; entry: ES:DI -> path = "d:\level1\level2\" +; exit: path = "d:\level1\" + + mov al,es:[di] ; get next character + test al,al ; end of string? + jz path_chop2 ; yes, string scanned + inc di ; next character +if KANJI + call dbcs_lead ; lead-in of 16-bit character? + jne path_chop1 ; no, normal 8-bit + inc di ; skip hi-byte (should really check) + jmps path_chop ; try again +path_chop1: +endif + call check_slash ; is this a path character + jne path_chop ; loop back if not path character + mov dx,cx ; last but one '/' = last '/' + mov cx,di ; last '/' = current '/' + jmps path_chop ; repeat +path_chop2: + mov di,dx ; ES:DI -> last but one slash + 1 + sub ax,ax ; get a NUL byte + stosb ; chop off the last level + ret + + Public rebuild_ldt_root + +rebuild_ldt_root: +;---------------- +; On Entry: +; ES:BX -> LDT_ to rebuild +; fdos_hds = physical root for this drive +; On Exit: +; ES:BX preserved +; LDT_ROOT rebuilt from ASCII LDT_NAME +; + push ds + push es ! pop ds ; DS:BX -> LDT_ + push ss ! pop es + mov di,offset temp_ldt ; ES:DI -> temp LDT_ + lea si,LDT_NAME+3[bx] ; point to start of pathname + mov cx,LDT_ROOTLEN[bx] ; CX = end of root portion + xor ax,ax ; assume we want root block + sub cx,3 ; skip the 'D:\' + jbe rebuild_ldt_root10 ; nothing to do unless SUBST'd + rep movsb ; copy the root portion of the name + call select_dir ; select this directory + jnc rebuild_ldt_root10 + xor ax,ax + mov LDT_ROOTLEN[bx],2 ; force ourselves into the root + mov LDT_NAME+3[bx],al ; as the media has changed +rebuild_ldt_root10: + push ds ! pop es ; ES:BX -> LDT_ + pop ds + mov ax,fdos_hds_blk + mov es:LDT_ROOT[bx],ax ; update our root block +if JOIN + mov al,fdos_hds_drv ; and the physical drive + mov es:LDT_DRV[bx],al +endif + ret + + +rebuild_ldt_curdir: +;------------------ +; On Entry: +; ES:BX -> LDT_ to rebuild +; fdos_hds = logical root of this drive +; On Exit: +; ES:BX preserved +; LDT_DRV and LDT_BLK rebuilt from ASCII LDT_NAME +; + push ds + push es ! pop ds ; DS:BX -> LDT_ + push ss ! pop es + mov di,offset temp_ldt ; ES:DI -> temp LDT_ + mov si,LDT_ROOTLEN[bx] ; SI = end of root portion + lea si,LDT_NAME[bx+si] ; point to subdir entry + lodsb ; get 1st char + call check_slash ; is it a leading '\' ? + je rebuild_ldt_curdir10 ; yes, discard it + dec si ; else leave it alone +rebuild_ldt_curdir10: + test al,al ; anything to do? + jz rebuild_ldt_curdir40 ; no, we are already there +rebuild_ldt_curdir20: + lodsb ! stosb ; copy the string + test al,al ; until we hit the terminating NUL + jnz rebuild_ldt_curdir20 + dec di + call select_dir ; select this directory + jnc rebuild_ldt_curdir40 + mov si,LDT_ROOTLEN[bx] ; SI = end of root portion + cmp si,3 ; is root real root or a subdir ? + ja rebuild_ldt_curdir30 + mov si,3 ; real root, leave '\' alone +rebuild_ldt_curdir30: + mov LDT_NAME[bx+si],0 ; move ASCII to root +rebuild_ldt_curdir40: + push ds ! pop es ; ES:BX -> LDT_ + pop ds + mov ax,fdos_hds_blk + mov es:LDT_BLK[bx],ax ; update our curdir block +if JOIN + mov al,fdos_hds_drv ; and the physical drive + mov es:LDT_DRV[bx],al +endif + ret + +select_dir: +;---------- +; On Entry: +; DS:BX -> LDT +; ES:DI -> end of ASCII path +; temp_ldt contains dir to select +; On Exit: +; DS:BX preserved +; CY set on error, root of original drive reselected +; + mov ax,'.\' ; append a "\." in case it's the root + stosw ; (and so a NULL path) + xor ax,ax + stosb + push ds ! push bx ; make sure LDT survives + push ss ! pop ds ; DS back to SYSDAT + mov si,offset temp_ldt ; ES:SI -> directory to select + call path_prep_next ; try to move into it +if JOIN + call offer_join ; are we opening a JOIN'd drive ? + jnc select_dir20 +endif + call finddfcbf ; find the directory entry + jz select_dir10 ; stop if we can't + test DATTS[bx],DA_DIR ; check if directory + jz select_dir10 ; fail if this is a file + push ds ! pop es + lea di,DNAME[bx] ; ES:DI -> ASCII name to open + mov cx,8+3 + mov al,' ' + repe scasb ; is it all spaces ? + je select_dir10 ; if so reject it + call open_dir + jnc select_dir20 +select_dir10: + mov ax,fdos_hds_root ; move to the virtual root + mov fdos_hds_blk,ax + stc ; return error +select_dir20: + pop bx ! pop ds + ret + + +eject +; Run down the path and parse final name +; exit: ds:dx -> info_fcb parsed at path end +; cf = 1, and al = code on any error + +path_prep: + les di,dword ptr fdos_pb+2 ; es:di -> path name + +path_prep_ptr: + call path_prep_check ; try to prepare path + jnc path_prep_good ; skip if success + jmp fdos_error ; return error to application + +path_prep_drive_error: +; stc ; return CY set + mov ax,ED_DRIVE ; with correct error code +path_prep_good: + ret + +path_prep_check: + call get_path_drive ; from asciiz or default + jc path_prep_drive_error ; continue if drive A: - Z: +path_prep_cont: + push di ; DX = drive code (0-15) + push es ; save string address + push ds ! pop es ; ES = SYSDAT + call select_unique ; select the drive and + pop es + pop si ; es:si -> past drive + + lods es:al ; get first character + call check_slash ; if '\' or '/' then start at root + jne path_prep_curdir ; else select current directory + push es + call path_prep_root ; fake a '.' entry for the root + pop es + lods es:al ; get next char + dec si ; forget we looked + test al,al ; if just a '\' stop now + jz path_prep_done + call check_slash + jne path_prep_next ; otherwise start processing from root + mov ax,ED_ACCESS ; get correct error code + stc ; and return if \\ + ret + +path_prep_curdir: +; We need to select the current directory as a start for our operations + dec si ; forget about char we looked at + push es ! push si ; and save position in name + mov al,logical_drv ; get the current logical drive + call get_ldt ; and hence the LDT structures + jc path_prep_curdir30 ; no LDT, leave at physical root +if JOIN + mov al,fdos_hds_drv ; are we on a known drive ? + sub al,es:LDT_DRV[bx] ; (we may be on joined drive) + jne path_prep_curdir10 ; if not better rebuild + cbw ! dec ax ; AX = FFFF +else + mov ax,0FFFFh +endif + cmp ax,es:LDT_BLK[bx] ; do we need to do a rebuild + jne path_prep_curdir20 ; or can we trust the media ? +path_prep_curdir10: + call rebuild_ldt_curdir ; better reselect current dir +path_prep_curdir20: + mov ax,es:LDT_BLK[bx] ; move to current directory block + mov fdos_hds_blk,ax +path_prep_curdir30: + pop si ! pop es ; ES:SI -> name again + +path_prep_next: +;-------------- +; Called by disk change code to rebuild an HDS_ for a drive after +; media change detected. +; On Entry: +; ES:SI -> pathname to rebuild +; fdos_hds = HDS_ to rebuild +; On Exit: +; CY set if problem (AX=error code) +; ES=DS +; + cmp es:byte ptr [si],0 ; can't have trailing '/' or '\' + je path_prep_error ; return this as an error + + mov ax,path_drive + inc ax ; al = drive (one based) + call parse_path ; set up the info_fcb + jc path_prep_error ; skip on any parse error + + test al,al ; AL = delimiter + jz path_prep_done ; are we at the end ? + + cmp word ptr info_fcb+1,' .' + je path_prep_next ; CHDIR (".") => stay where we are + + call check_no_wild ; no wilds cards in path's + je path_prep_error ; skip if wild cards found + +if JOIN + push es + push si + call offer_join ; are we opening a JOIN'd drive ? + pop si + pop es + jnc path_prep_next ; if so move on to next stage +endif + push es + push si ; save string address + push ds ! pop es ; ES = local segment + call finddfcbf ; locate the directory entry + pop si + pop es ; restore string address + jz path_prep_error ; no, missing directory in path + + test DATTS[bx],DA_DIR ; check if directory + jz path_prep_error ; fail if this is a file + + push es ! push si ; save string address + push ds ! pop es ; ES = local segment +if PASSWORD + call check_pwd_any ; check if PW req'd & supplied +endif + call open_dir ; go down one level + pop si ! pop es ; restore string address + jnc path_prep_next ; if open is good, repeat +path_prep_error: + mov ax,ED_PATH ; return code in case of error + stc ; indicate error to caller + ret + + +path_prep_done: + cmp info_fcb+1,'.' ; is it '.' or '..' ? + jne path_prep_exit ; if so get its full name +if JOIN + call offer_join ; are we opening a JOIN'd drive ? + jnc path_prep_root ; if so move into the dir +endif + call finddfcbf ; find the directory entry + jz path_prep_exit ; stop if we can't + call open_dir ; move into the directory + jc path_prep_error ; stop if we can't + mov cx,DBLOCK1[bx] ; are we destined for the root ? + jcxz path_prep_root ; yes, stop - we won't find anything + push fdos_hds_root + mov fdos_hds_root,0 ; don't stop at virtual root + call find_parent ; find the parental entry + pop fdos_hds_root + jz path_prep_error ; (shouldn't happen) + mov ax,DPWD[bx] ; get password hash code from entry + mov local_password,ax ; ensure we can get back down + lea si,DNAME[bx] ; point to it's name + mov cx,11 + push ds ! pop es + mov di,offset info_fcb+1 + rep movsb ; copy parental name to info_fcb +path_prep_exit: + push ds ! pop es ; restore ES to local segment + clc + ret + + +path_prep_root: + push ds ! pop es ; ES = local segment + mov al,info_fcb ; preserve drive setting + call clear_info_fcb + mov info_fcb+1,'.' ; fake a '.' directory + ret + + +clear_info_fcb: +;-------------- +; Sets up a clean info_fcb for later use +; On Entry: +; AL = drive +; On Exit: +; All regs preserved +; + push di ! push cx ! push ax + mov di,offset info_fcb + stosb ; set the drive code + + mov cx,11 + mov al,' ' + rep stosb ; fill name with blanks +if PASSWORD + mov cx,8 + mov di,offset password_buffer + rep stosb ; blank password buffer + mov es:local_password,cx ; zero out local password +endif + pop ax ! pop cx ! pop di + clc + ret + + +eject +; Get drive from path name, or if none, use default drive +; On Entry: +; es:di -> path name +; On Exit: +; AL = path_drive = sepcified or default drive +; es:di -> past drive name +; cf = 1 if illegal drive name + +get_path_drive: + cmp es:byte ptr [di],0 ; check if string is empty + je get_path_error ; which isn't O.K. at all + cmp es:byte ptr 1[di],':' ; if the second char is ':', + jz get_path_explicit ; then drive is in pathname + call current_dsk2al + jmps get_path_ok ; common code from here + +get_path_explicit: + mov al,es:[di] ; grab the drive designator + call toupper ; make sure it is upper case + sub al,'A' ; correct offset. if too + jb get_path_error ; small, return error + cmp al,ss:last_drv + jae get_path_error + inc di + inc di ; it's ok, bump the pointer +get_path_ok: + xor ah,ah ; zero ah and clc + mov path_drive,ax ; save for other functions + ret + +get_path_error: + stc ; flag the error + ret + +eject +asciiz_dev_offer: +;---------------- +; On Entry: +; PB+2 -> pathname +; On Exit: +; Only come back if not a device +; +; See if the filename is that of a simple device +; eg. 'CON', 'A:CON', 'CON.EXT' +; We should also accept '\DEV' format +; eg. '\DEV\CON', "A:\DEV\CON' +; More complicated forms should be ignored - they will be handled +; after the pathname is parsed. +; eg. 'A:\CON', '\CON', 'SUBDIR\CON.EXT' +; + push ds + mov si,2[bp] ; SI -> parameter block + lds si,ds:2[si] ; DS:SI -> file specification + cmp ds:byte ptr 0[si],0 ; NUL names are stupid, but + je asciiz_dev_offer30 ; you do get them.... + cmp ds:byte ptr 1[si],':' ; is a drive specified + jne asciiz_dev_offer10 + inc si ! inc si ; skip that, but no more +asciiz_dev_offer10: + push ss ! pop es ; ES:DI -> scratch FCB in build + mov di,offset name_buf ; name in pcmode data buffer + mov al,' ' + mov cx,8+3 + rep stosb ; start by clearing name + + mov al,[si] ; beware of '\DEV\name' format.. + call check_slash ; if not slash carry on + jne asciiz_dev_offer15 + lodsb ; possible, lets look at rest + lodsb + call toupper + cmp al,'D' ; is '\D'possible ? + jne asciiz_dev_offer30 + lodsb + call toupper + cmp al,'E' ; is '\DE' on ? + jne asciiz_dev_offer30 + lodsb + call toupper + cmp al,'V' ; is '\DEV' on ? + jne asciiz_dev_offer30 + lodsb ; finally how about trailing '\' + call check_slash + jne asciiz_dev_offer30 + mov al,[si] ; check for delimiter +asciiz_dev_offer15: + call check_delim ; if first char = delimiter + jz asciiz_dev_offer30 ; then it can't be a device + + mov di,offset name_buf ; build name in scratch FCB + mov cx,8 ; length of name field + call parse_one ; parse just the name + cmp al,'.' + jnz asciiz_dev_offer20 ; do we have to parse an extention ? + mov di,offset name_buf+8 ; di -> fcb ext field + mov cx,3 ; length of ext field + call parse_one ; parse just extension +asciiz_dev_offer20: + test al,al ; if not a NUL by now forget it + jnz asciiz_dev_offer30 + push ss ! pop ds + mov si,offset name_buf ; DS:SI -> name + call check_device_common ; try to find the name + jnc asciiz_dev_accept ; if we can handle it here +asciiz_dev_offer30: + pop ds ; DS back to normal + push ss ! pop es ; ditto with ES + ret ; not a device - proceed + +asciiz_dev_accept: +;---------------- +; We have found a match in the device at ES:BX +; + mov ss:word ptr current_device,bx + mov ss:word ptr current_device+WORD,es + pop ds ; DS = SYSDAT again + pop ax ; discard return address + call local_disk ; we need the MX + les bx,ss:current_device ; ES:BX -> device header + cmp fdos_pb,FD_EXPAND + je asciiz_dev_accept20 + cmp fdos_pb,4Eh ; is it FD_FFIRST ? + je asciiz_dev_accept10 + jmp open_dev ; open the device locally +asciiz_dev_accept10: + jmp first_dev ; 'find' the device locally +asciiz_dev_accept20: + jmp expand_dev ; 'expand' the device locally + +eject +chk_no_dev: ; check file is not a character device +;---------- +; On Entry: +; info_fcb contains parsed filename +; On Exit: +; Don't return if it's a character device +; + call check_device ; is this a device ? + jnc chk_not_dev10 + push ds ! pop es ; ES points to data again + ret +chk_not_dev10: + jmp fdos_ED_ACCESS ; blow caller away + +check_device: +;------------ +; On Entry: +; info_fcb contains parsed filename +; On Exit: +; CY set if not found +; else +; CY clear if found +; ES:BX -> device header +; + mov si,offset info_fcb+1 ; DS:SI -> name to check +; jmp check_device_common + +check_device_common: +;------------------- +; On Entry: +; DS:SI -> 8 byte buffer to check +; On Exit: +; CY set if not found +; else +; CY clear if found +; ES:BX -> device header +; + push ss ! pop es ; Get the PCMODE Data Segment + mov bx,offset dev_root ; hence the Device List + mov ax,si ; keep copy of start in AX +check_device10: + test es:DH_ATTRIB[bx],DA_CHARDEV + jz check_device20 ; skip unless it's a character device + lea di,DH_NAME[bx] ; ES:DI -> device name + mov cx,8/2 ; compare file name w/o extension + repe cmpsw ; compare until CX == 0 or mismatch + je check_device30 +check_device20: + mov si,ax ; restore starting address + les bx,es:DH_NEXT[bx] ; get next device driver + cmp bx,0FFFFh ; end of the chain ? + jne check_device10 + stc ; indicate character device not found +check_device30: + ret + +eject + +no_dir_vol: +;---------- + test DATTS[bx],DA_DIR+DA_VOLUME + jnz dir_vol_err ; return error if label or directory + ret ; else it's O.K. +dir_vol_err: + jmp fdos_ED_ACCESS ; return "access denied" + +eject + + +get_pb2_drive: +;------------- + mov al,byte ptr fdos_pb+2 ; get requested drive code + dec al ; Get the default drive if + jns get_pb2_drv1 ; the requested drive is 00 + call current_dsk2al ; AL = default drive +get_pb2_drv1: + ret + +eject + +mkdir_init: +;---------- + push ax ; Init 1st block of the directory + call zeroblk ; zero the block + pop ax ! push ax ; get the block number + xor bx,bx ; seek to beginning of cluster + call fill_dirbuf ; DI -> directory entry + pop dx ! push dx ; get our own block # + mov ax,' .' ; this is the "." directory + call init_dot ; set name, attrib, time, date, block1 + call flush_dirbuf ; copy '.' entry to sector buffer + pop ax ; get the block number + mov bx,1 ; do 2nd entry + call fill_dirbuf ; DI -> directory entry + call hdsblk + xchg ax,dx ; DX = parent directory + mov ax,'..' ; this is the ".." directory +; call init_dot ; fall into INIT_DOT +; ret + +init_dot: + mov dirp,di ; save directory entry for SETPCD + push di + mov DBLOCK1[di],dx ; our own block # + stosw ; store "." or ".." + mov al,' ' + mov cx,11-2 + rep stosb ; pad the name with spaces + mov al,DA_DIR + stosb ; attribute = directory + call GetTOD ; get time/date of creation + pop bx + jmp stamp_date_and_time ; set date DX and time AX in dir BX + +eject + +; Utility functions for RMDIR and UNLINK + +rmdir_ok: ; make sure directory not in use +;-------- +; + + mov bx,dirp ; get the directory entry + mov ax,DBLOCK1[bx] ; block number of directory + xor bx,bx ; start at beginning +rmdir_ok1: + push ax ! push bx ; save block, offset + call fill_dirbuf ; locate directory entry + pop bx ! pop ax ; restore offset, block + cmp DNAME[di],0 ; is it virgin entry? + je rmdir_ok4 ; yes, no entries above here + cmp DNAME[di],0E5h ; is it deleted entry? + je rmdir_ok3 ; yes, no problems yet... + cmp DNAME[di],'.' ; is it "." or ".."? + je rmdir_ok3 +if DELWATCH +; We have found a dir entry - better check if it is a pending delete +; and that delwatch is installed. Then we can ignore it. + test DATTS[di],DA_VOLUME ; is the volume label bit set + jz rmdir_not_empty ; no, can't be pending delete + xor dx,dx ; (also sets DH = DELW_RDMASK) +; cmp dx,DBLOCK1[di] ; is it really a pending delete ? +; jz rmdir_not_empty ; yes, fall thru to delwatch check + xchg ax,dx ; AH = DELW_RDMASK, DX = dir cluster + mov si,di ; -> directory buffer (for DELWATCH) + callf ss:fdos_stub ; is the delwatch TSR installed + xchg ax,dx ; AX = dir cluster + jnc rmdir_ok3 ; delwatch will handle pending deletes +rmdir_not_empty: +endif + mov ax,ED_ACCESS ; return "access denied" if not empty + +rmdir_inuse: ; directory not empty or in use: + jmp fdos_error ; return the error + +rmdir_ok3: ; else this entry O.K. + inc bx ; check next directory entry + cmp bx,dirperclu ; cluster completed? + jb rmdir_ok1 ; loop back if more to come + call getnblk ; get next block in directory + sub bx,bx ; start at beginning of block + cmp ax,lastcl ; end of cluster chain? + jb rmdir_ok1 ; loop back if not done yet +rmdir_ok4: ; directory is empty + mov al,adrive + call hshdscrd ; discard the hash values + clc ; "go ahead with RMDIR..." + ret ; return, ready for the evil deed... + + +chkcds: ; check if any process uses directory to delete +;------ +; On Entry: +; dirp -> directory entry of DIR to check +; On Exit: +; CY clear if DIR is in use +; + mov bx,dirp + mov cx,DBLOCK1[bx] ; block number of directory to delete + mov dl,physical_drv ; get the drive the subdir is in + mov al,-1 ; start with drive A: +chkcds10: + inc ax ; next drive + call get_ldt_raw ; ES:BX -> LDT for drive + jc chkcds20 ; bail if if bad drive + test es:byte ptr LDT_FLAGS+1[bx],(LFLG_NETWRKD+LFLG_PHYSICAL)/100h + js chkcds10 ; it can't be a network drive + jz chkcds10 ; it must be a physical drive + cmp dl,es:LDT_DRV[bx] ; does the drive match? + jne chkcds10 ; no, don't bother then + cmp es:LDT_BLK[bx],0ffffh ; is it valid + jne chkcds19 + push ax + push cx + push dx + call select_logical_drv ; select with media change check + call rebuild_ldt_curdir ; rebuild LDT_ + pop dx + pop cx + pop ax +chkcds19: +if 0 +; This didn't make the beta, so leave until the next release +; We really need to make sure we relog all SUBST's drives before +; we can be sure this is valid and fail the rmdir + cmp cx,es:LDT_ROOT[bx] ; is this our root block ? + je chkcds20 ; (ie. a SUBST'd drive) +endif + cmp cx,es:LDT_BLK[bx] ; does the block match + jne chkcds10 ; no, try next drive +chkcds20: + ret + + +eject +; +; Go down one level in directory +; On Entry: +; DIRP -> directory to open +; PATH_DRIVE = drive to use +; On Exit: +; AX = fdos_hds_blk (the current directory block) +; CY clear on success +; CY set on error +; + +open_dir: + mov bx,dirp + test DATTS[bx],DA_DIR ; check if directory + stc + jz open_dir20 ; fail if this is a file + cmp word ptr info_fcb+1,'..' + jne open_dir10 ; watch out if going up a level + mov ax,fdos_hds_blk ; get current block + cmp ax,fdos_hds_root ; check if at logical root already + jne open_dir10 ; and if not carry on + cmp ax,DBLOCK1[bx] ; if we are already at the virtual root + stc ; and want to stay there that's OK + jne open_dir20 ; otherwise return an error +open_dir10: + mov al,physical_drv ; remember the drive + mov fdos_hds_drv,al + mov ax,DBLOCK1[bx] ; remember this directory block + mov fdos_hds_blk,ax + clc ; success +open_dir20: + ret + + + Public hdsblk + +;====== +hdsblk: ;/* check if we are in subdirectory */ +;====== +; +; exit: AX = directory block number +; ZF = set if at root +; regs: others preserved + + mov ax,fdos_hds_blk ; get current directory block + test ax,ax ; set ZF + ret + + + +parent2save_area: +;----------------- +; On Entry: +; AX = cluster number of parent to find +; On Exit: +; save_area contains parental name (DX = length of name) +; + call find_parent ; locate parent directory + jz path_error ; stop in case we're in a mess + lea si,DNAME[bx] ; get parent directory name + mov di,offset save_area ; ES:DI -> scratch area +; jmp unparse ; make it ASCIIZ file name + +; build ASCIIZ string from directory entry +; entry: BX -> directory buffer +; ES:DI -> output buffer +; exit: ES:DI -> next byte in buffer + +unparse: +;------- + push di ; save base of name + mov cx,8 ; remainder of up to 7 characters + lea si,DNAME[bx] ; SI -> directory name + call unparse_field ; copy name, strip trailing blanks + mov al,'.' + stosb ; add the dot for start of extension + push di ; remember where extention starts + mov cx,3 ; copy 3-char extension + lea si,DNAME+8[bx] ; SI -> directory extention + call unparse_field ; copy extension, strip trailing blanks + pop ax ; recover start of extension + cmp ax,di ; did we generate extension? + jne unparse1 ; skip if we did + dec di ; else eat the '.' +unparse1: + xor ax,ax + stosb ; NUL-terminate the name + pop bx ; ES:BX -> base of name + cmp es:byte ptr [bx],05h + jne unparse2 ; if not mapped E5 (deleted entry/Kanji) + mov es:byte ptr [bx],0E5h ; else map back to E5 for Kanji support +unparse2: + ret + +unparse_field: +;------------- +; entry: DS:SI -> disk buffer +; ES:DI -> ASCIIZ name to build +; CX = field length +; On Exit: +; ES:DI -> end of name +; BX preserved + + push si ; save start of field + add si,cx ; SI -> end of field + inc cx ; one extra for LOOPE dec +unprsf10: + dec si ; lets look at the previous char + cmp ds:byte ptr [si],' ' ; trailing space ? + loope unprsf10 + pop si ; SI = start of field + rep movsb + ret + + +path_error: + jmp fdos_ED_PATH ; return "invalid path" error + +mkspace_parent: +;-------------- +; save_area contains the parental name, DX bytes long. We wish to insert it +; into an ASCIIZ string so make DX bytes of space at ES:DI. +; On Entry: +; ES:DI -> ASCIIZ, DX = byte count +; On Exit: +; DS:SI -> parents name, CX = length of parent (DX on entry) +; + mov al,0 ; find end of name + mov cx,128 ; max. path length + repne scasb ; scan for end of path + neg cx + add cx,128 ; CX = string length including NUL + mov ax,cx + add ax,dx + cmp ax,64 + ja path_error + dec di ; ES:DI -> '\0' + mov si,di ; SI -> source of copy + add di,dx ; point to beyond insertion + push ds + push es ! pop ds ; move string backwards to make space + std ! rep movsb ! cld ; for directory name + pop ds + mov cx,dx ; CX = length of new directory name + mov si,offset save_area ; SI -> unparsed name + ret + +; find parent directory starting with cluster AX +; entry: AX = cluster of parent to find +; exit: ZF = 1 if not found (shouldn't happen) +; -or- +; ZF = 0 if found, BX=DIRP -> dir entry + +find_parent: + mov blk,ax ; save the block number + push ds ! pop es + mov di,offset info_fcb+1 + mov ax,'..' ! stosw ; file name is '..' + mov al,' ' ; pad with spaces + mov cx,9 ! rep stosb + call finddfcbf ; find pointer to parent + jz fndpar2 ; shouldn't happen... + call open_dir ; go up one level + jc fndpar3 ; screwed up by security... + call setenddir ; search from beginning +fndpar1: + sub cx,cx + call getdir ; find next directory entry + jz fndpar2 ; end of directory + mov al,DNAME[bx] ; check if deleted file + cmp al,0E5h + je fndpar1 ; skip empty slots + cmp al,0 + je fndpar2 ; end of directory + test DATTS[bx],DA_DIR ; try to find directory + jz fndpar1 ; skip plain files + mov ax,DBLOCK1[bx] ; get starting cluster + cmp ax,blk + jne fndpar1 +fndpar3: + or ax,0FFFFh ; force non-zero condition +fndpar2: + ret ; ZF = 0 if found + +eject +path_prep_chk: +;------------- +; Run down the path and parse final name +; exit: ds:dx -> info_fcb parsed at path end + + call path_prep ; prepare the path + call chk_no_dev ; devices not allowed +chk_no_dot_or_wild: +;------------------ + call chk_no_dot ; no subdirs entries either +; jmp chk_no_wild ; wild cards not allowed + +eject +chk_no_wild: ; make sure path doesn't contain wild cards +;----------- ; (or is all spaces) + call check_no_wild ; error if any wildcards + jne check_no_wild_ret ; or if all spaces + jmp fdos_ED_FILE ; return "invalid filename" + +check_no_wild: ; make sure path doesn't contain wild cards +;------------- ; (or is all spaces) ZF set on problem + push es + push ds ! pop es ; ES -> SYSDAT + mov di,offset info_fcb+1 + mov cx,11 + mov al,'?' ; scan for wild cards + repne scasb + je check_no_wild_exit ; skip if wild cards found + mov di,offset info_fcb+1 + mov cx,11 + mov al,' ' ; scan for all spaces + repe scasb ; ZF set if a problem +check_no_wild_exit: + pop es +check_no_wild_ret: + ret + + +chk_for_root: +;------------ +; On Entry: +; info_fcb -> name of failed search +; fdos_hds -> dir we searched in +; On Exit: +; ZF set if a search for root (or '.' in root) +; + cmp fdos_hds_blk,0 ; are we in the root ? + jne chk_for_root10 ; no, no further checks required + push ds ! pop es + mov di,offset info_fcb+1 + mov al,'.' ; check for root + scasb ; is it a '.' entry ? + jne chk_for_root10 + mov cx,8+3-1 + mov al,' ' + repe scasb ; is it all spaces ? +chk_for_root10: + ret + + +; Parse a pathname into an info_fcb +; entry: es:si -> asciiz string +; AX = drive code +; exit: es:si -> next asciiz name in path +; dx -> fcb +; CY clear, AL = 0 if end of string +; CY set, AX = error code + +parse_path: +;---------- + push ds ! push es + pop ds ! pop es + + call clear_info_fcb ; initialise to blanks and drive AL + + mov dx,offset info_fcb ; use a scratch fcb + mov di,dx ; dx saves initial di + inc di + + mov ax,[si] ; check first two chars + cmp al,'.' ; special case: if name = '.' + jne parse_path20 ; then we parse it differently + movsb ; copy the '.' + cmp ah,'.' ; special case: if name = '..' + jne parse_path10 ; then we parse it differently + movsb ; copy '..' +parse_path10: + lodsb ; get next char + cmp al,' ' ; skip all spaces + je parse_path10 + jmps parse_path30 ; now exit as normal + +parse_path20: + call check_delim ; if first char = delimeter + je parse_path30 ; then only allow '\' + +; filename begins with a legal char, parse it normally + + mov di,dx + inc di ; di -> fcb name field + mov cx,8 ; length of name field + call parse_one ; parse just the name + mov di,dx ; DI -> FCB + cmp es:byte ptr 1[di],0E5h ; is first character E5? + jne parse_path30 ; skip if not + mov es:byte ptr 1[di],05h ; else make it internal synonym +parse_path30: + cmp al,'.' + jne parse_path40 ; skip if no extension + add di,9 ; di -> fcb ext field + mov cx,3 ; length of ext field + call parse_one ; parse just extension +parse_path40: +if PASSWORD + cmp al,';' ; check if password specified + jne parse_path50 ; skip if no password + mov di,offset password_buffer + mov cx,8 ; length of password field + call parse_one ; parse just password + push ax + push ds ! push si + push ss ! pop ds ; DS:SI -> ASCII password + mov si,offset password_buffer + call hash_pwd ; AX = encrypted password + mov local_password,ax ; remember it in case we need it + pop si ! pop ds + pop ax +endif +parse_path50: + test al,al ; a NUL is OK + jz parse_path90 + call check_slash ; if terminator != '\' or '/', + stc ; assume an error + jne parse_path80 ; report it if so +parse_path60: + lodsb ; get next character + call check_delim ; we expect a normal character + jne parse_path80 ; here - exit if we've got one + call check_slash ; swallow '\'s at this point and leave + je parse_path60 ; other delimiters for next time + cmp al,'.' ; trailing '\.' ? + jne parse_path75 + mov cx,si ; remember position of '.' +parse_path70: + lodsb ; now discard trailing spaces + cmp al,' ' + je parse_path70 ; keep going until we lose all spaces + test al,al ; stop at a NUL + jz parse_path50 + call check_slash ; if it's a '\' try again + je parse_path50 + mov si,cx ; retract to the '.' +parse_path75: + mov al,'\' ; return '\' as the delimiter + clc ; and exit with no problems +parse_path80: + dec si ; retract a byte (CY unaffected) +parse_path90: + push ds ! push es + pop ds ! pop es + ret + + + + Public parse_one + +; Parse a single name or extension +; On Entry: +; DS:SI -> asciiz name +; ES:DI -> start of fcb field +; CX = field size +; On Exit: +; AL = last char parsed +; +; nb. make no assumptions about DS and ES +; + +parse_one: + lodsb ; grab asciiz char + cmp al,'*' ; if char = *, then fill + jz parse_one_wild ; rest of field with '?' + call check_delim ; if char is not delimiter, + jnz parse_one_char ; then move it to fcb + ret ; if delimiter, return + +parse_one_wild: + mov al,'?' + rep stosb ; after filling + jmps parse_one_ignore ; skip until a delimiter + +parse_one_char: +if KANJI + call dbcs_lead ; is it 1st byte of Kanji pair? + jnz parse_one_skip ; skip if straight 8-bit + inc si ; assume both chars discarded + dec cx ; we will copy 2 bytes + jcxz parse_one_ignore ; ignore both if only room for one + stosb ; thats the first byte + dec si ; point at 2nd again + lodsb ; get the 2nd byte +parse_one_skip: +endif + stosb ; send char to fcb + loop parse_one ; get another character from ASCIIZ string +parse_one_ignore: + lodsb + call check_delim ; ignore up to next delimiter + jnz parse_one_ignore + ret + +; +; +; Check for a path name delimiter +; entry: AL = ASCIIZ char +; exit: all registers preserved +; ZF = 1 if char is a delimeter +; ZF = 0 if char is legal in file names + + Public check_delim + +check_delim: +;----------- + cmp al,' ' ; if any printable char, + jae check_delim_char ; then skip + cmp al,al ; set zf + ret + +check_delim_char: +if KANJI + call dbcs_lead ; if it's 1st of kanji pair + jne check_delim10 ; DON'T upper case it + test al,al ; clear zf + ret ; (should really check the 2nd byte) +check_delim10: +endif + call toupper ; make it upper case + push es ! push di ! push cx + push cs ! pop es + lea di,delim_string ; es:di -> delimeters + mov cx,length delim_string + cld + repnz scasb ; match al against the list + pop cx ! pop di ! pop es + clc ; never return cf set + ret ; with zf set by scasb + +delim_string db ':.;,=+\<>|/"[]' ; DOS delimeters + + +; Check AX for '\\' + + Public check_dslash + +check_dslash: + xchg al,ah + call check_slash + xchg al,ah + jne check_slash_done +; jmp check_slash + +; Check delimeter character for '\' or '/' +; entry: al = char +; exit: zf = 1 if either slash + +check_slash: + cmp al,'\' ; if first char is a backslash + jz check_slash_done ; or a frontslash, then + cmp al,'/' ; return with zf set +check_slash_done: + clc ; never return cf set + ret + +; Convert character to upper case +; WARNING - may be called with DS <> SYSDAT + +toupper: +;------- + test al,al + js toupper_intl + cmp al,'a' + jb isupper + cmp al,'z' + ja isupper + sub al,'a'-'A' +isupper: + ret + +toupper_intl: + callf ss:intl_xlat ; call international upper case vector + ret + +eject +kill_file: ; release clusters for file/dir and delete entry +;--------- + mov bx,dirp ; get pointer to directory entry +if DELWATCH + call hdsblk ; AX = directory root cluster + xchg ax,dx ; DX = dir cluster + mov cx,dcnt ; CX = directory index for entry + mov ah,DELW_DELETE ; we are about to delete this dir + mov al,physical_drv ; directory entry so give delwatch + callf ss:fdos_stub ; a chance to make it pending delete + jnc kill_file10 ; delwatch took it - just update dir +endif + mov al,0E5h ; deleted file mark + xchg al,DNAME[bx] ; delete the directory entry + mov DUNDEL[bx],al ; save 1st letter for UNDEL command + mov ax,DBLOCK1[bx] ; get starting block # + call delfat ; release all clusters +kill_file10: + jmp flush_dirbuf ; update the directory + ; done it! (DIR/FAT still dirty) +eject + +mustbe_nolbl: +;------------ +; On Entry: +; None +; On Exit: +; Only returns if no label exists +; forces us to root of drive +; + push ds ! pop es ; ES = DS for string ops + mov si,offset info_fcb+1 + mov di,offset save_area ; SI->search name, DI->save area + mov cx,11 + push di ; save save_area + push si ; save info_fcb+1 + push cx ; save length + rep movsb ; copy search name into save area + pop cx ; CX = length (11) + pop di ; DI = info_fcb+1 + push di + push cx + mov al,'?' ; now fill info_fcb with wildcards + rep stosb + call find_labelf ; look for a volume label + pop cx ; CX = length (11) + pop di ; DI = info_fcb+1 + pop si ; SI = save_area + push ds ! pop es ; ES = DS for string ops + rep movsb ; restore info_fcb + jnz mustbe_nolbl10 ; if we found a label bail out + ret +mustbe_nolbl10: + jmp fdos_ED_ACCESS ; return access denied + +find_labelf: ; find label only +;----------- ; forces us to root +; On Entry: +; None +; On Exit: +; ZF clear if volume label found +; dirp/dcnt tell where label is +; + call setenddir ; start from beginning +; jmp find_label + +find_label: ; find label only +;---------- ; forces us to root +; On Entry: +; dcnt -> location to search from +; On Exit: +; ZF clear if volume label found +; dirp/dcnt tell where label is +; + mov chdblk,0 ; don't assume sequential access + mov fdos_hds_blk,0 ; look for labels in the root + mov finddfcb_mask,000ffh ; return VOL labels, not pending dels +find_label30: + call finddfcb ; find matching file name + jz find_label40 ; skip if not found + test DATTS[bx],DA_VOLUME + jz find_label30 ; try again if not a volume label +find_label40: + mov finddfcb_mask,DA_VOLUME*256 + ret ; back to no VOL labels or pending dels + +if UNDELETE +find_pending_delete: ; find pending delete only +;------------------- +; On Entry: +; dcnt -> location to search from +; On Exit: +; ZF clear if pending delete entry found +; dirp/dcnt tell where entry is +; + mov finddfcb_mask,0h ; return pending delete entries +find_pending_delete10: + mov al,05h ; replace 1st char with 05h + xchg al,info_fcb+1 ; saving char we really want + push ax + call finddfcb ; find matching file name + pop ax + mov info_fcb+1,al ; restore original 1st letter + jz find_pending_delete30 ; skip if not found + test DATTS[bx],DA_VOLUME ; Is it a pending delete entry + jz find_pending_delete10 ; No, try again if not a volume label + cmp word ptr DBLOCK1[bx],0 ; Is this a pending delete entry + jz find_pending_delete10 ; No, try again if not correct + cmp al,'?' ; wildcard is OK + je find_pending_delete20 + cmp al,DUNDEL[bx] ; does saved char match what we want? + jne find_pending_delete10 +find_pending_delete20: + and DATTS[bx],not DA_VOLUME ; mask out volume bit + mov al,DUNDEL[bx] ; move deleted character to normal + mov DNAME[bx],al ; position for return + or al,al ; clear the zero flag (assumes al!=0) +find_pending_delete30: + mov finddfcb_mask,DA_VOLUME*256 + ret ; back to no VOL labels or pending dels + +endif + +eject +find_xfn: ; find spare external file number +;-------- +; exit: DI = new handle + + + push es ; save ES while we play + xor di,di ; return handle 0 if don't have PSP + call get_xftptr + jc fndxfn2 + mov bx,di ; save the offset + mov al,0FFh ; look for unused slot + repne scasb ; loop while CX != 0 and *ES:DI != 0FFh + jne fndxfn3 ; ZF = 1 if match, else none found + dec di ; DI = matching offset + sub di,bx ; DI = handle index +fndxfn2: + pop es + clc ; indicate no error + ret + +fndxfn3: + pop es + stc ; indicate an error + ret + + Public alloc_dhndl + +alloc_dhndl: +;----------- +; provisionally allocate a spare DHNDL_, do not return without one +; On Entry: +; None +; On Exit: +; AX = IFN of handle +; ES:BX -> DHNDL_ structure +; (All other regs preserved) + call find_dhndl ; try to find a spare DHNDL_ + jc fdos_ED_HANDLE ; bail out if we can't + ret + +mustbe_free_handle: +;------------------ +; return an error to user if either an XFN or an IFN is unavailable +; On Entry: +; None +; On Exit: +; None +; + call alloc_dhndl ; make sure we can allocate a DHNDL + mov es:DHNDL_COUNT[bx],0 ; free it in case open/creat fails + ; (we are protected by local_disk) +; jmp alloc_xfn ; make sure an XFN is also free + + Public alloc_xfn + +alloc_xfn: ; find spare external file number +;-------- +; exit: DI = new handle + + call find_xfn ; try to find spare slot in XFT + jc fdos_ED_HANDLE ; "out of handles" if no luck + mov fdos_ret,di ; else save the resulting handle + ret + + +fdos_ED_HANDLE: + mov ax,ED_HANDLE ; out of user file #s, all 20 in use + jmp fdos_error + + +; Allocate & initialize file handle: +; entry: AX = open mode +; DIRP -> directory entry +; exit: ES:BX = CURRENT_DHNDL = file handle +; AX = fdos_ret = IFN +; -or- +; System call fails with ED_HANDLE + +open_handle: +;----------- + mov bx,dirp ; else get directory entry + test DATTS[bx],DA_RO ; check if file is r/o - if so + jz creat_handle ; make handle r/o too + and ax,not DHM_RWMSK +creat_handle: +;------------ +; entry point for create file - when you create a read-only file +; you still get a handle you can write with ! + push ax ; save open mode + xchg ax,si ; SI = open mode + mov di,S_OM_COMPAT ; check if open/sharing modes are compatible + call check_with_share ; does SHARE approve ? + call alloc_dhndl ; allocate a DHNDL_ structure + mov fdos_ret,ax ; remember IFN in case it's FCB + pop dx ! push dx ; DX = open mode + push es ! push bx ; save DHNDL_ pointer + test dh,DHM_FCB/100h ; FCB call? + jne creat_handle10 ; skip XFN allocation if FCB + push ax ; save IFN + call alloc_xfn ; allocate spare XFN + pop ax ; recover IFN + mov bx,di ; BX = XFN + call get_xftptr ; ES:DI -> user file table + jc creat_handle10 ; skip if we don't have one + mov es:[di+bx],al ; set IFN in PSP +creat_handle10: + pop bx ! pop es + lea di,DHNDL_COUNT[bx] ; point at open count + mov ax,1 + stosw ; open by one + pop ax ; recover open mode + mov cx,DHAT_TIMEOK+DHAT_CLEAN + test al,DHM_LOCAL ; is it private ? + jz creat_handle20 + or ch,DHAT_LOCAL/256 ; rememmber it's local + and al,not DHM_LOCAL ; clear inherit bit +creat_handle20: +; lea di,DHNDL_MODE[bx] ; update the mode + stosw + mov si,dirp + mov al,DATTS[si] ; get file attribute byte + lea di,DHNDL_DATRB[bx] ; now copy file attribute + stosb ; to DHNDL_ + xchg ax,cx ; AX = attributes + or al,physical_drv ; get physical drive +; lea di,DHNDL_WATTR[bx] ; make as clean disk file + stosw +; lea di,DHNDL_DEVOFF[bx] ; ES:DI -> dd entry in DHNDL_ + mov ax,ss:word ptr current_ddsc + stosw ; point to DDSC_ + mov ax,ss:word ptr current_ddsc+WORD + stosw + mov ax,DBLOCK1[si] ; get starting cluster of file +; lea di,DHNDL_BLK1[bx] + stosw + lea si,DTIME[si] +; lea di,DHNDL_TIME[bx] + movsw ; copy the time +; lea di,DHNDL_DATE[bx] + movsw ; and the date + lodsw ; skip 1st cluster (already done) +; lea di,DHNDL_SIZE[bx] + movsw ! movsw ; copy the file size +; lea di,DHNDL_POS[bx] + xor ax,ax ; zero current position + stosw ! stosw +; lea di,DHNDL_IDX[bx] + stosw ; zero block index +if DOS5 + call hdsblk ; get directory block +; lea di,DHNDL_DBLK[bx] + stosw + xor ax,ax + stosw +else +; lea di,DHNDL_BLK[bx] + stosw ; and current block + call hdsblk ; get directory block +; lea di,DHNDL_DBLK[bx] + stosw +endif + mov ax,dcnt ; set DCNT of file +; lea di,DHNDL_DCNTLO[bx] + stosb ; store low byte of DCNT + mov es:DHNDL_DCNTHI[bx],ah ; and hi byte +; lea di,DHNDL_NAME[bx] ; copy name from dir entry + mov si,dirp + mov cx,11 + rep movsb + xor ax,ax + stosw ; zero DWORD + stosw + lea di,DHNDL_SHARE[bx] ; zero sharing record + stosw +if DOS5 + stosw ! stosw ! stosw ; zero DHNDL_BLK + IFS +endif + callf ss:share_stub+S_OPEN ; we have opened this handle + ; ask SHARE to register it + jc create_handle30 + mov ax,fdos_ret ; AX = handle to return + ret +create_handle30: ; free the handle again + push ax + mov ax,fdos_ret + call release_handle2 + pop ax + jmp fdos_error + + + + Public verify_handle + +verify_handle: +;------------- +; On Exit: +; ES:BX = DHNDL_ +; CY set if bad file handle (nb. device handle is bad) +; + call check_handle ; make sure we can access it + jc vfy_hnd9 ; return if character device + +select_handle: ; select directory of current handle +;------------- +; On Entry: +; ES:BX -> DHNDL_ +; On Exit: +; ES:BX preserved +; + mov al,es:DHNDL_ATTR[bx] ; get physical drive + and al,DHAT_DRVMSK ; from attrib field + push es ! push bx + call select_physical_drv ; select the drive + pop bx ! pop es + mov ax,es:DHNDL_DBLK[bx] + mov fdos_hds_blk,ax ; copy HDS_BLK + clc ; handle is OK file +vfy_hnd9: + ret ; good handle + + +; Checks if parameter is a legal file handle: +; Entry: CURRENT_DHNDL = handle to verify +; Exit: ES:BX = DHNDL_ if O.K. +; CY clear if local disk file +; CY set if device/network handle +; Note: doesn't return on error + +check_handle: +;------------ + les bx,current_dhndl + test es:DHNDL_WATTR[bx],DHAT_REMOTE+DHAT_DEV + stc ; assume device/network file + jnz chkhnd10 ; return with CY = 0 if disk file + callf ss:share_stub+S_UPDATE ; make sure DHNDL_ info valid + jc chkhnd20 ; if not close it down +chkhnd10: + ret + +chkhnd20: + call get_xftptr ; ES:BX -> XFT + jc fdos_ED_H_MATCH ; skip if not handle + mov bx,fdos_pb+2 ; get XFN so we can poke + mov es:byte ptr [di+bx],0ffh + ; PSP handle to closed +; jmp fdos_ED_H_MATCH ; return "invalid handle" + +fdos_ED_H_MATCH: + mov ax,ED_H_MATCH ; "invalid handle" + jmp fdos_error ; return an error + + public vfy_dhndl_ptr + +vfy_dhndl_ptr: +;============= +; Verifies file handles at FDOS_xxxx calling level +; before MXdisk is locked. +; On Entry: +; SS:BP -> func #, parm off, parm seg +; stack holds two ret addresses + above values +; On Exit: +; ES:BX -> DHNDL_ + + mov si,2[bp] ; SI -> parameter block + mov ax,2[si] ; get file handle from parameter block + test ss:byte ptr remote_call+1,DHM_FCB/100h; if we are doing an FCB operation + jnz vfy_dhndl10 ; deal only with IFN, forget PSP + mov es,ss:current_psp + cmp ax,PSP_XFNMAX ; CX = # entries in table + jae vfy_dhndl_err + les di,PSP_XFTPTR ; ES:DI -> user file table + mov bx,ax ; get user file number (0-19) + mov al,es:[bx+di] ; get IFN for this handle +vfy_dhndl10: + cmp al,0ffh ; invalid handle? + je vfy_dhndl_err ; 00h-FEh only + les bx,ss:file_ptr ; get the address of the first entry +vfy_dhndl20: + cmp ax,es:DCNTRL_COUNT[bx] ; handle in this block? + jae vfy_dhndl50 ; skip to try next block if not + mov ah,DHNDL_LEN + mul ah + add ax,DCNTRL_LEN ; skip the header + add bx,ax ; add to start of structure + mov cx,es:DHNDL_COUNT[bx] ; fail if the handle is not in use + jcxz vfy_dhndl_err + inc cx ; FFFF = pre-allocated is also failed + jz vfy_dhndl_err + cmp ss:WindowsHandleCheck,26h + ; have we been patched + jne vfy_dhndl30 ; yes, don't check owner + mov ax,ss:machine_id ; get current process + cmp ax,es:DHNDL_UID[bx] ; are we the owning process + jne vfy_dhndl_err ; no, return an error +vfy_dhndl30: + mov ss:word ptr current_dhndl,bx + mov ss:word ptr current_dhndl+WORD,es + test es:DHNDL_MODE[bx],DHM_NOCRIT + jnz vfy_dhndl40 ; are critical errors allowed ? + ret + +vfy_dhndl40: + or valid_flg,NO_CRIT_ERRORS + ret ; remember no critical errors possible + +vfy_dhndl50: + sub ax,es:DCNTRL_COUNT[bx] ; update the internal file number + les bx,es:DCNTRL_DSADD[bx] ; get the next entry and check + cmp bx,0FFFFh ; for the end of the list + jnz vfy_dhndl20 +vfy_dhndl_err: + add sp,WORD ; pop return addr - return to caller + mov bx,ED_H_MATCH ; with "invalid handle" error + ret + + + + +; On Entry: +; FDOS_PB+2 = external file handle to release +; On Exit: +; ES:BX -> DHNDL_ + +release_handle: +;-------------- + mov ax,fdos_pb+2 ; get user file number (0-19) +release_handle2: +;--------------- + call get_xftptr ; ES:DI -> XFN table + jc release_ifn ; IFN = XFN if no PSP + cmp ax,cx ; more than in handle table? + jae rlshnd_err ; return error if too large + xchg ax,bx ; BX = external file number + mov al,0FFh ; get old IFN, release XFN + xchg al,es:[bx+di] ; get IFN for this handle + cmp al,0FFh + je rlshnd_err +release_ifn: + call ifn2dhndl ; ES:BX -> DHNDL_ + jnc check_no_dir_ret ; return if no error + +rlshnd_err: ; else bad handle + jmp fdos_ED_H_MATCH ; return the error + + +eject +check_no_dir: ; check if entry is directory +;-------- +; entry: BX -> directory entry + + test DATTS[bx],DA_DIR ; test if directory + jnz chk_ro_err ; skip if a directory +check_no_dir_ret: + ret ; else return to caller + +check_ro: ; check if file write protected +;-------- +; entry: BX -> directory entry + + test DATTS[bx],DA_RO ; test if file r/o + jnz chk_ro_err ; skip if file r/o + ret ; else return to caller +chk_ro_err: + jmp fdos_ED_ACCESS ; return "access denied" if r/o + + + +discard_files: ; discard all handles on adrive +;------------- + mov al,adrive + callf ss:share_stub+S_DISCARD ; tell share to forget about files + ret + + + +; Close file if it's us in compatibility modes + +close_if_same_psp: +;----------------- +; Note: We first check if the file is open by anyone other +; than the same UID and PSP, or is open in shared mode. +; In either case we deny the operation. +; Otherwise we fall through and close the file. +; We could do it in one with a new share, but this way means +; less changes. +; + mov di,S_DENY_IF_OPEN ; check if file already open + call check_with_share ; and stop if it is +; jmp close_if_open + +; Make sure our file is not open + +close_if_open: +;------------- +; entry: HDSADR->BLK = block # of directory +; HDSADR->DRV = drive number +; DCNT = directory position +; Note: If the file is open by any other process, +; error ED_SHAREFAIL is returned from the system call +; If open by us (same UID, any PSP) in compatibility mode, +; close it and allow us to proceed. + + mov di,S_CLOSE_IF_OPEN ; check if file already open +; jmps check_with_share + +check_with_share: +;---------------- +; On Entry: +; DI = S_ share query +; On Exit: +; Come back if share says it's OK. +; + call hdsblk ; get directory block in AX + xchg ax,dx ; directory block + mov cx,dcnt ; get the directory count in CX + mov al,physical_drv ; get physical drive in AL + callf ss:share_stub[di] ; ask SHARE if it knows of anyone open + jc check_with_share10 + ret ; must be OK. + +check_with_share10: + jmp fdos_error ; bail out with an error + + +eject + +eject +; +; Return a pointer to the DOS Handle corresponding to the internal +; handle number passed in AX +; +; On Entry: +; AL = IFN +; +; On Exit: +; ES:BX -> DOS handle (All other Regs preserved) +; CY set if no corresponding valid DHNDL_ +; + Public ifn2dhndl +ifn2dhndl: + push ax + xor ah,ah ; make IFN a word + les bx,ss:file_ptr ; get the address of the first entry + +ifn2dh10: + cmp ax,es:DCNTRL_COUNT[bx] ; handle in this block? + jae ifn2dh20 ; skip if not + mov ah,DHNDL_LEN ; calculate offset of the DOS Handle + mul ah + add bx,ax ; add structure offset (should be 0) + add bx,DCNTRL_LEN ; and then skip the header + pop ax + clc + ret ; ES:BX -> valid DHDNL_ + +ifn2dh20: + sub ax,es:DCNTRL_COUNT[bx] ; update the internal file number + les bx,es:DCNTRL_DSADD[bx] ; get the next entry and check + cmp bx,0FFFFh ; for the end of the list + jnz ifn2dh10 +ifn2dh15: + pop ax + stc + ret ; invalid file handle number + + + +; +; Allocate a DHNDL_ structure +; +; On Entry: +; None +; +; On Exit: +; CY clear if handle allocated +; AX = IFN of handle +; ES:BX -> DOS handle +; (All other Regs preserved) +; + Public find_dhndl +find_dhndl: + push cx ! push dx ! push di ! push si + mov ax,ss:machine_id ; get current process + mov dx,ss:owning_psp ; DX = owining PSP + xor si,si ; SI = IFN + les di,ss:file_ptr ; get the address of the first entry +find_dh10: + mov cx,es:DCNTRL_COUNT[di] ; get # handles in this block + jcxz find_dh40 ; skip if none + lea bx,DCNTRL_LEN[di] ; ES:BX -> 1st DHNDL_ +find_dh20: + push cx + cli ; be alone while looking at handles + mov cx,es:DHNDL_COUNT[bx] + jcxz find_dh50 ; if handle free grab it + inc cx ; FFFF = allocated but unused + jnz find_dh30 + cmp ax,es:DHNDL_UID[bx] ; was it allocated to us + jne find_dh30 + cmp dx,es:DHNDL_PSP[bx] ; if so use it again + je find_dh60 +find_dh30: + sti ; finished with this handle + pop cx + inc si ; onto next IFN + cmp si,0FFh ; only handles 00-FE are valid + jae find_dh45 ; so bail if out of range + add bx,DHNDL_LEN ; onto next handle in the block + loop find_dh20 +find_dh40: + les di,es:DCNTRL_DSADD[di] ; get the next entry and check + cmp di,0FFFFh ; it's valid + jne find_dh10 +find_dh45: + stc ; no more handles, + jmps find_dh70 ; exit in failure.. + +find_dh50: + mov es:DHNDL_COUNT[bx],0FFFFh + mov es:DHNDL_UID[bx],ax ; allocate it to us + mov es:DHNDL_PSP[bx],dx +find_dh60: + sti ; safe again + pop cx ; discard handle count + xchg ax,si ; AX = IFN + mov ss:word ptr current_dhndl,bx + mov ss:word ptr current_dhndl+WORD,es + mov ss:current_ifn,ax + clc ; we have found and allocated a handle +find_dh70: + pop di ! pop si ! pop dx ! pop cx + ret + + + Public get_xftptr + +get_xftptr: +;---------- +; On Entry: +; None +; On Exit: +; ES:DI -> PSP_XFTPTR for current_psp +; CX = # entries in it +; CY set if not PSP operation (eg. FCB's) +; (all other regs preserved) +; + + test ss:byte ptr remote_call+1,DHM_FCB/100h; if we are doing an FCB operation + jnz get_xftptr_err ; deal only with IFN, forget PSP + mov es,ss:current_psp + mov cx,PSP_XFNMAX ; CX = # entries in table + les di,PSP_XFTPTR ; ES:DI -> user file table + ret + +get_xftptr_err: + stc ; forget about XFN's + ret + + + Public current_dsk2al + +current_dsk2al: +;-------------- +; AL = current default drive + mov al,ss:current_dsk + ret + + Public lds_si_dmaptr + +lds_si_dmaptr: +;------------- +; On Entry: +; None +; On Exit: +; DS:SI -> current DMA address +; (All other regs preserved) + lds si,ss:dword ptr dma_offset + ret + + + public les_di_dmaptr + +les_di_dmaptr: +;------------- +; On Entry: +; None +; On Exit: +; ES:DI -> current DMA address +; (All other regs preserved) + les di,ss:dword ptr dma_offset + ret + + Public copy_asciiz + +copy_asciiz: +;---------- +; Copy an ASCIIZ string from DS:SI to ES:DI + lodsb ! stosb + test al,al + jnz copy_asciiz + ret + +if JOIN + +check_join: +;---------- +; On Entry: +; fdos_hds -> HDS we wish to check +; On Exit: +; AH = drive (zero based) from fdos_hds_drv +; AL = drive (zero based) of the JOIN root +; if JOINed drive +; ZF clear +; else +; ZF set +; (All other regs presrved) +; + push es ! push bx + mov al,fdos_hds_drv ; get drive from HDS_ + mov ah,al ; save HDS_DRV in AH + cmp join_drv,0 ; need we do anything ? + je check_join30 ; not if we haven't JOIN'd + cmp fdos_hds_root,0 ; is virtual root the physical one ? + jne check_join10 ; if not we can't be JOIN'd + call get_ldt ; ES:BX -> LDT for this drive + jc check_join10 ; bad LDT - we can't be joined + test es:LDT_FLAGS[bx],LFLG_JOINED + jz check_join30 + mov al,es:LDT_NAME[bx] ; get drive letter + sub al,'A' ; make drive letter zero based + mov bl,byte ptr path_drive ; get the logical drive we are on + push ax + mov al,bl ; AL = logical drive we are using + call get_ldt ; ES:BX -> LDT for this drive + pop ax + jc check_join10 ; no valid LDT.. + cmp es:LDT_NAME+2[bx],'\' ; are we at the root ? + jne check_join10 ; no, it can't be match + mov bl,es:LDT_NAME[bx] ; get the root drive for this drive + sub bl,'A' ; make drive letter zero based + cmp al,bl ; are we on the JOIN'd drive ? + mov bl,0ffh ; assume we are + je check_join20 ; were we ? +check_join10: + mov al,ah ; restore HDS_DRV + xor bl,bl ; return with ZF clear +check_join20: + test bl,bl ; set ZF appropriately +check_join30: + pop bx ! pop es + ret + +offer_join: ; are we opening a JOIN'd drive ? +;---------- +; If we are at the root of a JOIN'd drive moving up ("..") fiddle HDS +; onto parental JOIN drive root. +; If we are at the root of a non-JOIN'd drive see if we are searching for +; a JOIN'd drive directory +; On Entry: +; info_fcb = entry we are searching for +; On Exit: +; CY set if not a JOIN'd drive +; + + cmp join_drv,0 ; need we do anything ? + jne oj_dochecks ; not, if we haven't JOIN'd +oj_rejected: + stc ; not a JOIN drive + ret + +oj_dochecks: +;----------- +; Before we do anything else we must be at the physical root of a drive +; with a valid LDT. We then check for two cases +; 1) Doing a '..' from a JOIN'd drive to it's parental root +; 2) Opening a directory correpsonding to a JOIN'd drive +; + mov al,info_fcb ; AL -> drive we are looking for + call get_ldt ; ES:BX -> LDT for this drive + jc oj_rejected ; bad LDT - we can't be joined + cmp es:LDT_ROOTLEN[bx],2 ; is root at top level ? + ja oj_rejected ; no, skip the rest + cmp fdos_hds_blk,0 ; are we at the root ? + jne oj_rejected ; if not we needn't do anything + +; We have validated HDS_, so now check for case 1) + call check_join ; is it a joined drive ? + jz oj_dir ; if not skip to case 2) + cmp word ptr info_fcb+1,'..'; else is it a '..' in JOIN'd root? + jne oj_rejected ; if not we needn't do anything + call mvhds_drvroot ; do '..' from root -> real root + clc ; we handled it it ! + ret + +oj_dir: +;------ +; We are in the physical root of a non-joined drive. We now need to see if +; the dir we are searching for corresponds with a joined drive +; + push si ! push di + call build_match_name ; join_name = what we are looking for + call look_for_match ; see if we can find it + jc oj_dir10 + call mvhds_drvroot ; we have a match - move into it + clc ; say we handled it +oj_dir10: + pop di ! pop si + ret + + +look_for_match: +;-------------- +; Compare join_name against available JOIN drives. +; Return with CY clear if we found it, ES:BX -> LDT, AL the drive + xor ch,ch + mov cl,join_drv ; search this many drives + xor ax,ax ; start with drive A: + mov ah,last_drv + call get_ldt ; ES:BX -> LDT for this drive + jnc lfm20 + ret ; no LDT's... +lfm10: + inc al ; next drive + cmp al,ah ; paranioa - check if we have reached + jae lfm50 ; last_drv and exit if so + add bx,LDT_LEN ; next LDT +lfm20: + test es:LDT_FLAGS[bx],LFLG_JOINED + jz lfm10 ; if not JOIN'd try next candidate + + lea di,LDT_NAME[bx] ; ES:DI -> JOIN info + mov si,offset join_name ; lets see if it matches the + push ax +lfm30: + lodsb ; get a byte + scasb ; does it match ? + jne lfm40 ; no, forget it + test al,al ; end of the string yet ? + jnz lfm30 ; no, keep trying +lfm40: + pop ax + je lfm60 ; did we match ? + loop lfm10 ; no, if any JOIN's left try them +lfm50: + stc ; we didn't find it +lfm60: + ret + +build_match_name: +;---------------- +; Fill join_name with the "C:\JOIN" we want to find +; + mov al,info_fcb ; AL -> drive we are looking for + dec al ; make it zero based + call get_ldt ; ES:BX -> LDT for this drive + mov al,es:LDT_NAME[bx] ; get the drive "D" + push ds ! pop es ; ES -> SYSDAT + mov di,offset join_name ; construct the target name + stosb ; plant the drive letter + mov ax,'\:' + stosw ; now we have "d:\" + mov bx,offset info_fcb+1 ; DS:SI -> name we are looking for + jmp unparse ; unparse the name + +BDOS_DATA dseg word + +join_name db 'd:\filename.ext',0 + +BDOS_CODE cseg + + Public mv_join_root + +mv_join_root: +;------------ +; Poke the fdos_hds to be the root. If it's the physical root we then +; see if it is a JOIN'd drive. If it is we poke the drive and reselect +; the disk so we are at the real root of the drive. +; + push bx ! push si ! push di ; save index registers + mov ax,fdos_hds_root + mov fdos_hds_blk,ax ; move us to virtual root + test ax,ax ; is it the real root ? + jnz mvj_root10 ; if not forget about JOIN'd drives + call check_join ; are we joined ? + jz mvj_root10 ; no, we've done enough + call mvhds_drvroot ; make it real root +mvj_root10: + pop di ! pop si ! pop bx ; restore index registers + ret + + +mvhds_drvroot: +;------------- +; On Entry: +; AL = Drive (0 based physical) +; On Exit: +; None +; +; Poke the HDS to be at the root of drive AL and select that drive +; + mov fdos_hds_drv,al ; change to joined drive + xor dx,dx + mov fdos_hds_blk,dx ; put us back to the root again + mov fdos_hds_root,dx + cmp al,physical_drv ; already there ? + je mvhds_drvroot10 ; then skip the selection + call select_physical_drv ; select the drive +mvhds_drvroot10: + jmp path_prep_root ; info_fcb = '.' +; ret + +endif ;JOIN + +eject +stamp_dir_entry: +;--------------- +; On Entry: +; DIRP -> None +; On Exit: +; None +; +; Apply current date/time stamp to a directory, along with any other +; security information required. +; +if PASSWORD + mov cx,local_password ; were we given a password ? + jcxz stamp_dir_entry10 ; if so apply it + mov bx,dirp + mov DPWM[bx],PWM_ANY ; deny all for compatibility + or DATTS[bx],DA_HIDDEN ; make dir entry hidden + mov DPWD[bx],cx ; with this password +stamp_dir_entry10: +endif + call ReadTOD ; get current time/dat + mov bx,dirp +; jmp stamp_date_and_time +stamp_date_and_time: +; On Entry: +; BX -> directory entry +; AX = time +; DX = date +; On Exit: +; None +; stamp a directory entry with a given date and time + mov DDATE[bx],dx + mov DTIME[bx],ax + mov ah,PASSWD_CREAT ; call out to SECURITY TSR + callf ss:fdos_stub + jc stamp_date_and_time10 + jmp fdos_error ; return an error if required +stamp_date_and_time10: + ret + + + public ReadTOD + +ReadTOD: +;------- +; On Entry: +; None +; On Exit: +; DX = internal date format +; AX = internal time format +; + call ReadTimeAndDate ; get current time/date from BIOS +; jmp GetTOD + +GetTOD: +;------- +; On Entry: +; None +; On Exit: +; DX = internal date format +; AX = internal time format +; + mov ax,yearsSince1980 ; year is bits 9-15 + mov cl,4 + shl ax,cl + add al,month ; month is bits 4-8 + mov cl,5 + shl ax,cl + add al,dayOfMonth ; day is bits 0-3 + xchg ax,dx ; DX = date + + mov al,hour ; hour is bits 11-15 + mov cl,6 + shl ax,cl + add al,minute ; minute is bits 5-10 + mov cl,5 + shl ax,cl + mov cl,second ; second/2 is bits 0-4 + shr cl,1 ; + add al,cl + ret + + + +select_from_DTA: +;---------------- +; called by search next/undelete/purge to select a disk and prepare for +; a directory search based upon DTA contents. +; + push ds + call lds_si_dmaptr ; DS:SI -> DMA address + lodsb ; get search drive + pop ds + dec ax ; (stored 1-relative) + mov path_drive,ax ; restore path drive + call select_physical_drv ; select the drive in AL + push ds + push ds ! pop es ; ES = local segment + call lds_si_dmaptr ; DS:SI -> DMA address + inc si ; skip the drive # + mov di,offset info_fcb+1 ; copy FCB back to INFO_FCB + mov cx,11 + rep movsb + + lodsb ; get search attribute + mov es:attributes,al + + lodsw ; get directory count + mov es:dcnt,ax + + lodsw ; get the directory block + pop ds ; restore data segment + mov fdos_hds_blk,ax + ret + +if PASSWORD + +check_pwd_d: ; check if PW protected in any mode +;----------- + mov ax,PWM_D + jmps check_pwd + +check_pwd_any: ; check if PW protected in any mode +;------------- + mov ax,PWM_ANY +; jmps check_pwd + +check_pwd: ; check for password mismatch +;--------- +; entry: AX = password mode to be checked +; DIRP -> directory entry for file +; exit: BX, SI preserved + + push ax + push bx + mov bx,dirp ; BX -> file to be opened/deleted/etc. + xchg ax,cx ; password mode in CX + mov ah,PASSWD_CHECK ; call out to SECURITY TSR + callf ss:fdos_stub + jnc check_pwd20 + + mov ax,DPWD[bx] ; get password hash code from entry + jcxz check_pwd10 ; exit if no password + cmp ax,global_password ; compare with default password + je check_pwd10 ; yes, go ahead + cmp ax,local_password ; is it one we've just parsed ? + je check_pwd10 ; yes, go ahead + ; else we've got a password mismatch + + test cx,DPWM[bx] ; test if password mode affects us + jz check_pwd10 ; skip if attempted access O.K. + mov ax,ED_PASSWORD ; return password error +check_pwd20: + jmp fdos_error + +check_pwd10: + pop bx + pop ax + ret + + Public hash_pwd + +hash_pwd: ; compute 16-bit hash code for 1st COMMON_DMA password +;-------- +; On Entry: +; DS:SI -> 8 character password +; On Exit: +; AX = password hash code or 0000 if none (ZF set) +; SI corrupted, all other regs preserved +; + + push cx + push bp + mov cx,8 ; ch = 0, cl = 8 + mov bp,sp ; reverse and upper-case the name + sub sp,cx ; using temp buffer on the stack + xor ax,ax ; zero null password flag + +hash_pwd1: + lodsb ; get next ASCII character + call toupper ; international upper case + dec bp + mov ss:[bp],al ; copy password char to encrypted buff + or al,al ; is password char zero? + jz hash_pwd2 ; yes + cmp al,' ' ; is password char blank? + je hash_pwd2 ; yes + inc ah ; password is not null +hash_pwd2: + add ch,al ; add password char to encrypt CRC + dec cl + jnz hash_pwd1 + + mov al,ch ; AL = password CRC + mov cx,8 ; encrypt 8 characters + or ah,al ; if CRC = 0 and all 00 or ' ' + jz hash_pwd6 ; then there is no password + +hash_pwd3: + xor ss:[bp],al ; encrypt password on stack + inc bp + loop hash_pwd3 + + xor bp,bp ; initialize hash code + mov cx,4 ; 8 bytes = 4 words +hash_pwd4: + pop ax ; get two encrypted characters + rol ax,cl ; juggle them about a bit + xor bp,ax ; "add" them into hash code + loop hash_pwd4 ; repeat for whole password + jnz hash_pwd5 ; skip if result is non-zero + inc bp ; else force it to be non-zero +hash_pwd5: + xchg ax,bp ; return hash code in AX +hash_pwd6: + add sp,cx ; tidy up stack if buffer not poped + test ax,ax ; set ZF flag appropriately + pop bp + pop cx + ret + +endif + + + public share_delay + +; waste time before retrying operation that failed due to SHARE intervention +share_delay: + cmp ss:byte ptr remote_call,0 + jne share_delay_30 + push cx + mov cx,ss:net_delay + jcxz share_delay_20 +share_delay_10: + push cx + xor cx,cx + loop $ + pop cx + loop share_delay_10 +share_delay_20: + pop cx +share_delay_30: + ret diff --git a/IBMDOS/VECTORS.DEF b/IBMDOS/VECTORS.DEF new file mode 100644 index 0000000..3728a43 --- /dev/null +++ b/IBMDOS/VECTORS.DEF @@ -0,0 +1,213 @@ +; File : $VECTORS.DEF$ +; +; Description : +; +; Original Author : DIGITAL RESEARCH +; +; Last Edited By : $CALDERA$ +; +;-----------------------------------------------------------------------; +; Copyright Work of Caldera, Inc. All Rights Reserved. +; +; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, +; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. +; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES +; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF +; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO +; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE +; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE +; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, +; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, +; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, +; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF +; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT +; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND +; CIVIL LIABILITY. +;-----------------------------------------------------------------------; +; +; *** Current Edit History *** +; *** End of Current Edit History *** +; +; $Log$ +; +; ENDLOG + +INT08_OFFSET equ 0020h +INT08_SEGMENT equ INT08_OFFSET + 2 + +INT09_OFFSET equ 0024h +INT09_SEGMENT equ INT09_OFFSET + 2 + +INT10_OFFSET equ 0040h +INT10_SEGMENT equ INT10_OFFSET + 2 + +INT11_OFFSET equ 0044h +INT11_SEGMENT equ INT11_OFFSET + 2 + +INT12_OFFSET equ 0048h +INT12_SEGMENT equ INT12_OFFSET + 2 + +INT13_OFFSET equ 004Ch +INT13_SEGMENT equ INT13_OFFSET + 2 + +INT14_OFFSET equ 0050h +INT14_SEGMENT equ INT14_OFFSET + 2 + +INT15_OFFSET equ 0054h +INT15_SEGMENT equ INT15_OFFSET + 2 + +INT16_OFFSET equ 0058h +INT16_SEGMENT equ INT16_OFFSET + 2 + +INT17_OFFSET equ 005Ch +INT17_SEGMENT equ INT17_OFFSET + 2 + +INT18_OFFSET equ 0060h +INT18_SEGMENT equ INT18_OFFSET + 2 + +INT19_OFFSET equ 0064h +INT19_SEGMENT equ INT19_OFFSET + 2 + +INT1A_OFFSET equ 0068h +INT1A_SEGMENT equ INT1A_OFFSET + 2 + +INT1B_OFFSET equ 006Ch +INT1B_SEGMENT equ INT1B_OFFSET + 2 + +INT1C_OFFSET equ 0070h +INT1C_SEGMENT equ INT1C_OFFSET + 2 + +INT1D_OFFSET equ 0074h +INT1D_SEGMENT equ INT1D_OFFSET + 2 + +INT1E_OFFSET equ 0078h +INT1E_SEGMENT equ INT1E_OFFSET + 2 + +INT1F_OFFSET equ 007Ch +INT1F_SEGMENT equ INT1F_OFFSET + 2 + +INT20_OFFSET equ 0080h +INT20_SEGMENT equ INT20_OFFSET + 2 + +INT21_OFFSET equ 0084h +INT21_SEGMENT equ INT21_OFFSET + 2 + +INT22_OFFSET equ 0088h +INT22_SEGMENT equ INT22_OFFSET + 2 + +INT23_OFFSET equ 008Ch +INT23_SEGMENT equ INT23_OFFSET + 2 + +INT24_OFFSET equ 0090h +INT24_SEGMENT equ INT24_OFFSET + 2 + +INT25_OFFSET equ 0094h +INT25_SEGMENT equ INT25_OFFSET + 2 + +INT26_OFFSET equ 0098h +INT26_SEGMENT equ INT26_OFFSET + 2 + +INT27_OFFSET equ 009Ch +INT27_SEGMENT equ INT27_OFFSET + 2 + +INT28_OFFSET equ 00A0h +INT28_SEGMENT equ INT28_OFFSET + 2 + +INT29_OFFSET equ 00A4h +INT29_SEGMENT equ INT29_OFFSET + 2 + +INT2A_OFFSET equ 00A8h +INT2A_SEGMENT equ INT2A_OFFSET + 2 + +INT2B_OFFSET equ 00ACh +INT2B_SEGMENT equ INT2B_OFFSET + 2 + +INT2C_OFFSET equ 00B0h +INT2C_SEGMENT equ INT2C_OFFSET + 2 + +INT2D_OFFSET equ 00B4h +INT2D_SEGMENT equ INT2D_OFFSET + 2 + +INT2E_OFFSET equ 00B8h +INT2E_SEGMENT equ INT2E_OFFSET + 2 + +INT2F_OFFSET equ 00BCh +INT2F_SEGMENT equ INT2F_OFFSET + 2 + +INT30_OFFSET equ 00C0h +INT30_SEGMENT equ INT30_OFFSET + 2 + +INT31_OFFSET equ 00C4h +INT31_SEGMENT equ INT31_OFFSET + 2 + +INT32_OFFSET equ 00C8h +INT32_SEGMENT equ INT32_OFFSET + 2 + +INT33_OFFSET equ 00CCh +INT33_SEGMENT equ INT33_OFFSET + 2 + +INT34_OFFSET equ 00D0h +INT34_SEGMENT equ INT34_OFFSET + 2 + +INT35_OFFSET equ 00D4h +INT35_SEGMENT equ INT35_OFFSET + 2 + +INT36_OFFSET equ 00D8h +INT36_SEGMENT equ INT36_OFFSET + 2 + +INT37_OFFSET equ 00DCh +INT37_SEGMENT equ INT37_OFFSET + 2 + +INT38_OFFSET equ 00E0h +INT38_SEGMENT equ INT38_OFFSET + 2 + +INT39_OFFSET equ 00E4h +INT39_SEGMENT equ INT39_OFFSET + 2 + +INT3A_OFFSET equ 00E8h +INT3A_SEGMENT equ INT3A_OFFSET + 2 + +INT3B_OFFSET equ 00ECh +INT3B_SEGMENT equ INT3B_OFFSET + 2 + +INT3C_OFFSET equ 00F0h +INT3C_SEGMENT equ INT3C_OFFSET + 2 + +INT3D_OFFSET equ 00F4h +INT3D_SEGMENT equ INT3D_OFFSET + 2 + +INT3E_OFFSET equ 00F8h +INT3E_SEGMENT equ INT3E_OFFSET + 2 + +INT3F_OFFSET equ 00FCh +INT3F_SEGMENT equ INT3F_OFFSET + 2 + +INT5B_OFFSET equ 016Ch +INT5B_SEGMENT equ INT5B_OFFSET + 2 + +INT5C_OFFSET equ 0170h +INT5C_SEGMENT equ INT5C_OFFSET + 2 + +INTE0_OFFSET equ 0380h ; Concurrent DOS Vector +INTE0_SEGMENT equ INTE0_OFFSET + 2 + +INTEF_OFFSET equ 03BCh ; GEM Interrupt Vector +INTEF_SEGMENT equ INTEF_OFFSET + 2 + +; +; The following equates determine the vectors that will be saved +; during a DISPATCH. A core of vectors is always saved these are +; specified by the VEC_LOWCORE and VEC_HIGHCORE equates. Then the +; absolute FIRST and LAST vectors that will ever be preserved are +; specified by VEC_MINSAVE and VEC_MAXSAVE. +; +; The VEC_DEFAULT equate specifies the default range of equates +; that will be saved if this value is not over-ridden. +; +VEC_MINSAVE equ 05h ; Concurrent Saves 0 to 4 +VEC_MAXSAVE equ 0FFh ; Brief 2.01 Uses vectors > F0h +VEC_LOWCORE equ 05h +VEC_HIGHCORE equ 32h +VEC_LOWSPECIAL equ 70h ; 70h-77h are hardware vectors on PC +VEC_HIGHSPECIAL equ 77h ; and so are specially saved/restored +VEC_DEFAULT equ (VEC_HIGHCORE * 0100h) + VEC_LOWCORE diff --git a/LICENSE.TXT b/LICENSE.TXT new file mode 100644 index 0000000..9108d41 --- /dev/null +++ b/LICENSE.TXT @@ -0,0 +1,282 @@ +CALDERA'S OPENDOS END-USER LICENSE AGREEMENT. + +CALDERA OPENDOS IS AVAILABLE FOR INSTALLATION FROM THIS FILE SET. +IF YOU CHOOSE TO INSTALL THIS SOFTWARE YOU ARE CONSENTING TO BE +BOUND BY TERMS OF THIS AGREEMENT. IF YOU DO NOT AGREE TO ALL OF +THE TERMS OF THIS AGREEMENT, DO NOT CONTINUE WITH THE INSTALLATION +AND/OR RETURN THE COMPLETE PACKAGE TO CALDERA FOR A FULL REFUND. + +THIS DOWNLOAD, CDROM OR OTHER SUPPLIED MEDIA/DISTRIBUTION IS PROVIDED +WITHOUT TECHNICAL SUPPORT. + +This Agreement has 4 parts. At least two parts will apply to you. +Part I applies if you have not purchased a license to the accompanying +software (the "Software"). Part II applies if you have purchased a +license to the Software. Part III applies to binary license grants +to the Software within the categories of Part I or Part II. Part IV +applies to source code license grants to the Software within said +primary categories. If you initially acquired a copy of the Software +without purchasing a license and you wish to purchase a license, +contact Caldera, Inc. ("Caldera") on the Internet at +http:/www.caldera.com or call +1-800-850-7779. + +PART I -- TERMS APPLICABLE WHEN LICENSE FEES NOT (YET) PAID TO +CALDERA (LIMITED LICENSE FOR EVALUATION, EDUCATIONAL AND NON-PROFIT +USE) ONLY. + +Caldera grants you a non-exclusive license to use the Software in +source or binary form free of charge if (a) you are a student, +faculty member or staff member of an educational institution +(K-12, junior college, college or library), a staff member of +a religious organization, or an employee of an organization which +meets Caldera's criteria for a charitable non-profit organization; +or (b) your use of the Software is for the purpose of evaluating +whether to purchase an ongoing license to the Software. The evaluation +period for use by or on behalf of a commercial entity is limited +to 90 days; evaluation use by others is not subject to this 90 day +limit but is still limited to a reasonable period. Government +agencies (other than public libraries) are not considered educational, +religious, or charitable non-profit organizations for purposes of this +Agreement. If you are using the Software free of charge, you are not +entitled to support or telephone assistance. If you fit within the +description of a non-commercial use license, you may use the Software +in the manner described in Parts III and IV below under "Scope of Grant." + +DISCLAIMER OF WARRANTY FOR NON-COMMERCIAL USE. + +Software obtained free of charge, wether in source and binary forms, +are provided on an "AS IS" basis, without warranty of any kind, +including without limitation the warranties of merchantability, fitness +for a particular purpose and non-infringement. The entire risk as to +the quality and performance of the Software is born by you. Should +the Software prove defective, you and not Caldera assume the entire +cost of any service and repair you may desire. In addition, the +security mechanisms implemented by Caldera software have inherent +limitations, and you must determine that the Software sufficiently +meets your requirements. This disclaimer of warranty constitutes an +essential part of the agreement. SOME JURISDICTIONS DO NOT ALLOW +EXCLUSIONS OF AN IMPLIED WARRANTY, SO THIS DISCLAIMER MAY NOT APPLY +TO YOU AND YOU MAY HAVE OTHER LEGAL RIGHTS THAT VARY BY JURISDICTION. + +PART II -- TERMS APPLICABLE WHEN LICENSE FEES PAID + +GRANT. Subject to payment of applicable license fees, Caldera grants +to you a non-exclusive license to use the Software in binary and source +form and accompanying online documentation ("Documentation") in the +manner described in Parts III and IV below under "Scope of Grant." + +LIMITED WARRANTY FOR COMMERCIAL USE. + +Caldera warrants that for a period of ninety (90) days from the date +of acquisition, the Software, if operated as directed, will substantially +achieve the functionality described in the Documentation. Caldera does +not warrant, however, that your use of the Software will be uninterrupted +or that the operation of the Software will be error-free or secure. In +addition, the security mechanisms implemented by Caldera software have +inherent limitations, and you must determine that the Software +sufficiently meets your requirements. Caldera also warrants that +the media containing the Software, if provided by Caldera, is free +from defects in material and workmanship and will so remain for ninety +(90) days from the date you acquired the Software. Caldera's sole +liability for any breach of this warranty shall be, in Caldera's sole +discretion: + +(i) to replace your defective media; or (ii) to advise you how to achieve +substantially the same functionality with the Software as described in +the Documentation through a procedure different from that set forth in +the Documentation; or (iii) if the above remedies are demonstrated to +be impracticable, to refund the license fee you paid for the Software. +Repaired, corrected, or replaced Software and Documentation shall be +covered by this limited warranty for the period remaining under the +warranty that covered the original Software, or if longer, for thirty +(30) days after the date (a) of shipment to you of the repaired or +replaced Software, or (b) Caldera advised you how to operate the +Software so as to achieve the functionality described in the +Documentation. Only if you inform Caldera in writing of your problem +with the Software during the applicable warranty period and provide +evidence of the date you purchased a license to the Software will +Caldera be obligated to honor this warranty. Caldera will use reasonable +commercial efforts to repair, replace, advise or, for individual +consumers, refund pursuant to the foregoing warranty within 30 days +of being so notified. + +THIS IS A LIMITED WARRANTY AND IT IS THE ONLY WARRANTY MADE BY CALDERA. +CALDERA MAKES NO OTHER EXPRESS WARRANTY AND NO WARRANTY OF NON-INFRINGEMENT +OF THIRD PARTIES' RIGHTS. THE DURATION OF IMPLIED WARRANTIES, INCLUDING +WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY AND OF FITNESS FOR +A PARTICULAR PURPOSE, IS LIMITED TO THE ABOVE LIMITED WARRANTY PERIOD; +SOME JURISDICTIONS DO NOT ALLOW LIMITATIONS ON HOW LONG AN IMPLIED +WARRANTY LASTS, SO LIMITATIONS MAY NOT APPLY TO YOU. NO CALDERA DEALER, +AGENT, OR EMPLOYEE IS AUTHORIZED TO MAKE ANY MODIFICATIONS, EXTENSIONS, +OR ADDITIONS TO THIS WARRANTY. If any modifications are made to the +Software by you during the warranty period; if the media is subjected +to accident, abuse, or improper use; or if you violate the terms of this +Agreement, then this warranty shall immediately be terminated. This +warranty shall not apply if the Software is used on or in conjunction +with hardware or software other than the unmodified version of hardware +and software with which the software was designed to be used as described +in the Documentation. THIS WARRANTY GIVES YOU SPECIFIC LEGAL RIGHTS, +AND YOU MAY HAVE OTHER LEGAL RIGHTS THAT VARY BY JURISDICTION. + +PART III -- TERMS APPLICABLE TO BINARY LICENSE GRANTS + +SCOPE OF GRANT. + +For the binary license grants listed above, you may: +* use the Software on any single computer; +* use the Software on a network, provided that each person accessing + the Software through the network must have a copy licensed to that person; +* use the Software on a second computer so long as only one copy is used + at a time; +* copy the Software for archival purposes, provided any copy must contain + all of the original Software's proprietary notices and license terms; + or +* if you have purchased multiple licenses (as in a 10 Pack or a 50 Pack, + for instance) you may make any number of copies of the Software (but not + the documentation) up to the number licensed (10 or 50, in the example), + provided any copy must contain all of the original Software's proprietary + notices, marks and licenses. The number of copies is the total number + of copies that may be made for all platforms. Additional copies of + Documentation may be purchased. +* REDISTRIBUTION OF THE SOFTWARE IS PERMITTED FOR NON-COMMERCIAL + PURPOSES provided that the copyright notices, marks and these terms + and conditions in this document are duplicated in all such forms and + that the documentaiton, advertising materials, and other materials + related to such distribution and use acknowledge that the software was + developed by Caldera, Inc. Caldera's name may not be used to endorse + or promote products derived from this Software without specific prior + written permission. You may not: + +* permit concurrent use of the Software without proper licenses; +* copy the Software other than as specified above; +* rent, lease, grant a security interest in, or otherwise transfer + rights to the Software; or +* remove any proprietary notices, licenses or labels on the Software. + +PART IV -- TERMS APPLICABLE TO SOURCE CODE GRANT + +GRANT. Caldera grants you a non-exclusive license to use the Software +in source code form free of charge for personal, non-commercial use. +The Software in source code form may also be used for commercial +development purposes, provided a license is obtained from Caldera +before any products or derivative works are shipped for commercial gain +that utilize the Software , its components or derivative works. + +For the source code license grant, you may: +* use the Software on any single computer; +* use the Software on a network, provided that each person accessing + the Software through the network agrees to the terms and conditions + of this license +* use the Software on as many computers as needed provided that each + person accessing the Software agrees to the terms and conditions of + this license; +* redistribute the Software for non-commerical purposes, provided any + copy must contain all of the original Software's proprietary notices, + marks and license terms. (Note: redistibution of derivative products + for commercial gain is permitted, provided a license is obtained + before the derivative products are exchanged for commercial gain) +* copy the Software for archival purposes, provided any copy must + contain all of the original Software's proprietary notices, marks + and license terms. +* modify, translate, compile, disassemble, or create derivative works + based on the Software provided that such modifications are for + non-commercial use and that such modifications are provided back to + Caldera except for those who have obtained the right from Caldera + in writing to retain such modifications; any modification, translation, + compilation, disassembly or derivative work used for commercial gain + requires a seperate license from Caldera; + + You may not: + +* permit other individuals to use the Software except under the terms + listed above; +* copy the Software other than as specified above; +* rent, lease, grant a security interest in, or otherwise transfer + rights to the Software; or +* remove any proprietary notices , licenses or labels on the Software. + +TITLE. + +Title, ownership rights, and intellectual property rights in the Software +and all derivative works wether in binary and source forms shall remain +in Caldera and/or its suppliers unless otherwise specificed in a +seperate agreement with Caldera. The Software is protected by the +copyright laws and treaties. Title and related rights in the content +accessed through the Software is the property of the applicable content +owner and may also be protected by applicable law. This License gives you +no rights to such content. + +TERMINATION. + +The license will terminate automatically if you fail to comply with the +limitations described herein. On termination, you must destroy all copies +of the Software and Documentation. + +EXPORT CONTROLS. + +None of the Software or underlying information or technology may be +exported or reexported (i) into (or to a national or resident of) Cuba, +Iraq, Libya, North Korea, Iran, Syria or any other country to which the +U.S. has embargoed goods; or (ii) to anyone on the U.S. Treasury +Department's list of Specially Designated Nationals or the U.S. +Commerce Department's Table of Denial Orders. By downloading or using +the Software, you are agreeing to the foregoing and you are representing +and warranting that you are not located in, under the control of, or +a national or resident of any such country or on any such list. + +LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL +THEORY, TORT, CONTRACT, OR OTHERWISE, SHALL CALDERA OR ITS +SUPPLIERS OR RESELLERS BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY +INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY +CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF +GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND +ALL OTHER COMMERCIAL DAMAGES OR LOSSES. IN NO EENT WILL CALDERA +BE LIABLE FOR ANY DAMAGES IN EXCESS OF THE AMOUNT CALDERA +RECEIVED FROM YOU FOR A LICENSE TO THE SOFTWARE, EVEN IF CALDERA +SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR +ANY CLAIM BY ANY OTHER PARTY. THIS LIMITATION OF LIABILITY SHALL NOT +APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY TO THE EXTENT +APPLICABLE LAW PROHIBITS SUCH LIMITATION. FURTHERMORE, SOME +JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL +OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION AND EXCLUSION MAY NOT +APPLY TO YOU. + +HIGH RISK ACTIVITIES. + +The Software is not fault-tolerant and is not designed, manufactured or +intended for use or resale as on-line control equipment in hazardous +environments requiring fail-safe performance, such as in the operation +of nuclear facilities, aircraft navigation or communication systems, air +traffic control, direct life support machines, or weapons systems, in +which the failure of the Software could lead directly to death, +personal injury, or severe physical or environmental damage ("High +Risk Activities"). Caldera and its suppliers specifically disclaim +any express or implied warranty of fitness for High Risk Activities. + +MISCELLANEOUS. + +If the copy of the Software you received was accompanied by a printed or +other form of "hard-copy" End User License Agreement whose terms vary from +this Agreement, then the hard-copy End User License Agreement governs your +use of the Software. This Agreement represents the complete agreement +concerning this license and may amended only by a writing executed by +both parties. + +THE ACCEPTANCE OF ANY PURCHASE ORDER PLACED BY YOU IS EXPRESSLY MADE +CONDITIONAL ON YOUR ASSENT TO THE TERMS SET FORTH HEREIN, AND NOT +THOSE IN YOUR PURCHASE ORDER. If any provision of this Agreement is held +to be unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. This Agreement shall be governed by +Utah law (except for conflict of law provisions). The application the +United Nations Conventio of Contracts for the International Sale of +Goods is expressly excluded. + +U.S. GOVERNMENT RESTRICTED RIGHTS. Use, duplication or disclosure by +the Government is subject to restrictions set forth in subparagraphs +(a) through (d) of the Commercial Computer-Restricted Rights clause +at FAR 52.227-19 when applicable, or in subparagraph (c)(1)(ii) +of the Rights in Technical Data and Computer Software clause at +DFARS 252.227-7013, or at 252.211-7015, or to Caldera's standard +commercial license, as applicable, and in similar clauses in the +NASA FAR Supplement. Contractor/manufacturer is Caldera, Inc. 633 South +550 East, Provo, UT 84606, U.S.A. \ No newline at end of file diff --git a/LTOOLS/BIN2ASC.EXE b/LTOOLS/BIN2ASC.EXE new file mode 100644 index 0000000000000000000000000000000000000000..a6c4eed0ea72241d1af6f5d596eda149cdb608de GIT binary patch literal 22067 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 literal 0 HcmV?d00001 diff --git a/LTOOLS/COMPBDOS.EXE b/LTOOLS/COMPBDOS.EXE new file mode 100644 index 0000000000000000000000000000000000000000..0f5781399f60de91d44fed1ea7c78b6fa62fc1dd GIT binary patch literal 6379 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 literal 0 HcmV?d00001 diff --git a/LTOOLS/COMPBIOS.EXE b/LTOOLS/COMPBIOS.EXE new file mode 100644 index 0000000000000000000000000000000000000000..8b63fb0c3119ec627bcdad458fb90bd35f8d54c0 GIT binary patch literal 6610 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 literal 0 HcmV?d00001 diff --git a/LTOOLS/EXE2BIN.EXE b/LTOOLS/EXE2BIN.EXE new file mode 100644 index 0000000000000000000000000000000000000000..80dbd533a37c33633fc611143494b8e0bdb9be9b GIT binary patch literal 9700 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 voAg<M+*uPDJ_JY$?PQB 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 literal 0 HcmV?d00001 diff --git a/LTOOLS/LINKCMD.EXE b/LTOOLS/LINKCMD.EXE new file mode 100644 index 0000000000000000000000000000000000000000..67ff41bc31f76be78adb5ac0a031a1fbac0ebfe3 GIT binary patch literal 46592 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 aw8y-oUeoJ(sW<1H_QW(Z{n2Fqx$p}>eA*EJ literal 0 HcmV?d00001 diff --git a/LTOOLS/RASM86.EXE b/LTOOLS/RASM86.EXE new file mode 100644 index 0000000000000000000000000000000000000000..684c8490fbe1cea9a223cff91c89954572a7c025 GIT binary patch literal 49152 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 literal 0 HcmV?d00001 diff --git a/LTOOLS/RASM_SH.EXE b/LTOOLS/RASM_SH.EXE new file mode 100644 index 0000000000000000000000000000000000000000..49f840a789905cbdda7c085274e6993173057e5c GIT binary patch literal 12845 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