CSTART.ASM
上传用户:xiaogehua
上传日期:2007-01-08
资源大小:1183k
文件大小:100k
源码类别:

操作系统开发

开发平台:

Asm

  1. ;    File              : $Workfile: CSTART.ASM$
  2. ;
  3. ;    Description       :
  4. ;
  5. ;    Original Author   : DIGITAL RESEARCH
  6. ;
  7. ;    Last Edited By    : $CALDERA$
  8. ;
  9. ;-----------------------------------------------------------------------;
  10. ;    Copyright Work of Caldera, Inc. All Rights Reserved.
  11. ;      
  12. ;    THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
  13. ;    PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
  14. ;    ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
  15. ;    WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
  16. ;    THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
  17. ;    HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
  18. ;    AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
  19. ;    AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
  20. ;    COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
  21. ;    CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
  22. ;    TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
  23. ;    CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
  24. ;    AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
  25. ;    CIVIL LIABILITY.
  26. ;-----------------------------------------------------------------------;
  27. ;
  28. ;    *** Current Edit History ***
  29. ;    *** End of Current Edit History ***
  30. ;
  31. ;    $Log$
  32. ;    CSTART.ASM 1.2 97/03/21 15:01:01
  33. ;    Added /n option to disable critical error handler
  34. ;    CSTART.ASM 1.38 94/12/21 10:45:05 
  35. ;    Reduced Heap size to 860h just to be sure.
  36. ;    CSTART.ASM 1.34 94/03/29 16:10:05 
  37. ;    _docmd_int2f returns 1 or 0 depending on whether or not the command
  38. ;    is accepted.
  39. ;    CSTART.ASM 1.31 93/11/18 18:50:18
  40. ;    Fix HMA registration problem
  41. ;    CSTART.ASM 1.30 93/11/09 00:00:14
  42. ;    Shorten _ge_config_env
  43. ;    CSTART.ASM 1.28 93/11/05 00:54:25
  44. ;    move HMA registration code to where it's actually executed
  45. ;    CSTART.ASM 1.27 93/11/04 23:39:11
  46. ;    Fix problem with resident data relocation code
  47. ;    CSTART.ASM 1.26 93/11/04 20:06:09
  48. ;    int2E_far_entry now does CLI and STI the correct way round when loading
  49. ;    SS and SP.
  50. ;    CSTART.ASM 1.25 93/10/24 13:13:34
  51. ;    Added strategy 'best fit upper mem'' & link upper mem'
  52. ;    put_resident_high()    
  53. ;    CSTART.ASM 1.24 93/09/10 15:56:46
  54. ;    CLS checks for ANSI using Int 2F/1A00
  55. ;    CSTART.ASM 1.23 93/08/26 09:40:50
  56. ;    Now use PSP for stack during func 4b exec. There's some debug
  57. ;    code in case things screw up.
  58. ;    CSTART.ASM 1.21 93/08/03 10:04:18
  59. ;    Stopped using memory above A000 for transient portion because the 
  60. ;    stack was disappearing when MEMMAX -V executed.
  61. ;    CSTART.ASM 1.20 93/07/05 08:35:00
  62. ;    Now switch to a stack located at the top of conventional memory before
  63. ;    calling INT 21 ah=4B.
  64. ;    CSTART.ASM 1.19 93/05/24 11:38:22
  65. ;    alloc_com_memory now allocates copy buffer by allocating largest possible
  66. ;    block then shrinking it to the correct size. This prevents the buffer
  67. ;    being located in upper memory after a HILOAD.
  68. ;    CSTART.ASM 1.16 93/02/24 17:42:01
  69. ;    int10_cls() no longer checks position of INT 29 vector.
  70. ;    CSTART.ASM 1.12 92/11/17 14:26:40 
  71. ;    Change to set_reload_file to allow switches on COMSPEC line.
  72. ;    CSTART.ASM 1.10 92/09/17 11:31:43 
  73. ;    INT 2e DS=SI=0 now works when we are relocated.
  74. ;    CSTART.ASM 1.9 92/09/11 10:45:36
  75. ;    our_cmd_int2f altered so we can support multi-line macros in DOSKEY.
  76. ;    CSTART.ASM 1.8 92/08/06 09:55:22
  77. ;    Correctly support INT 2F AH=AEh for EDOS. See _cmd_line_int2f.
  78. ;    Int 2E DS=SI=0 causes batch processing to halt.
  79. ;    CSTART.ASM 1.7 92/07/20 17:13:44
  80. ;    Added the following maintanence source code changes:
  81. ;    29 Apr 92 Now sets Novell error mode to 00 on entry, and restores
  82. ;    ; original mode on exit.
  83. ;    18 May 92 Added routine get_original_envsize, to use as default if
  84. ;    ; /E option not used
  85. ;    ENDLOG
  86.     page 62,132
  87. title COMMAND.COM Startup Routines and Resident Section
  88. ;
  89. ;  7 Nov 87 Force the initial PATH specification to the root of the
  90. ; boot drive. Also add a new variable TEMPDRV which is 
  91. ; Concurrents Temporary Drive.
  92. ;
  93. ; 10 Dec 87 If DRNET has been loaded then add the DRNET=x.x string to
  94. ; the initial environment.
  95. ; 25 Feb 88 Run the 2nd Phase RSP's before spawning the remaining TMPs
  96. ;  1 Mar 88 Initialize the AUTOLOGON and NODE variables for diskless
  97. ; workstation support. Support the NODE environment variable
  98. ; 21 Mar 88 Allow for all registers to be corrupted on return from the 
  99. ; DOS EXEC function call.
  100. ;  5 Apr 88 Correctly handle incorrect command line length passed by
  101. ; FrameWork Install Program
  102. ; 13 Apr 88 Move Memory allocation code to DOSIF and initialise the
  103. ; default console in PD for SunRiver.
  104. ; 10 May 88 Clean-Up the segment grouping and force the CGROUP to be
  105. ; linked after the data for everything but the TMP. Add the
  106. ; INT10_CLS function for DOSPLUS
  107. ; 12 May 88 Cater for DesqView passing an environment segment of 0000
  108. ; 13 May 88 Alter FCB build to giver F & RED when /FRED typed in For FS.COM
  109. ; 19 May 88 Prevent CODE being moved to high memory if loaded as an .EXE
  110. ; or no initial environment is supplied
  111. ; 20 May 88 Move reload messages into the MESSAGE.C file.
  112. ; 24 May 88 Use the internal Critical Error handler and check for ABORT
  113. ; codes while in the Command Processor Code.
  114. ;  6 Jun 88 Move Command ReadLine down to resident code - so SK+ can
  115. ; overwrite the hi-mem portion.
  116. ; 16 Jun 88 VC_DATA now returns the Physical Console Number as well.
  117. ; 21 Jun 88 Add FARPTR routine which determines the correct segment to
  118. ; return to PRINTF based on the offset of a message.
  119. ; 22 Jun 88  remove environment & PSP setup & RSP spawning code
  120. ; for banked RSP support. Kludgey CDOS_EXEC code for banking
  121. ; 29 Jun 88 Modify MASTER_ENV so it can be called from C and change the
  122. ; exec code to use the internal FCB parsing.
  123. ; 30 Jun 88 Set the default PRINTER and AUX using the information in the
  124. ; INT17 and INT14 mapping arrays.
  125. ; 20 Jul 88 Increase HEAP Size to 0A00h for the TMP
  126. ;  9 Aug 88 Terminate the command line after a CR or LF for 
  127. ; BitStream Fontware.
  128. ; 31 Aug 88 Make the READLINE function call from high memory so PolyTron
  129. ; PolyWindows can be invoked from the command line.
  130. ; 22 Sep 88 Always use INT_BREAK routine for Control Break Handling
  131. ; 03 Oct 88 Invalidate the Old Environment for Novell under CDOS.
  132. ; 09 Nov 88 Select the correct DR-DOS history Buffer.
  133. ; 15 Nov 88 Re-initilaise Interrupt handlers after an EXEC for Novell
  134. ; 21 Nov 88 Install Command Processor Backdoor but just terminate caller
  135. ; 13 Dec 88 Generate the FCBs for a DOS exec internally for compatibility
  136. ; with Novell Netware.
  137. ; 15 Dec 88 Force the default INT 22, 23, 24 and 2E handlers to be set 
  138. ; relative to the PSP. Update PSP copies of interrupt 22, 23, 24
  139. ; if this is the root DOS process.
  140. ; 25 Jan 89 If new DRDOS internal data layout get the PD a new way
  141. ; 27 Feb 89 fix MAKE_FCB, use SI from F_PARSE if possible
  142. ; 15 Apr 89 INT2E handler
  143. ; 17 Apr 89 int10_cls: don't return to 25 lines if in 43 or 50 line mode 
  144. ; 31 May 89 DRDOS get PD using new f4458 backdoor
  145. ;  6 Jun 89 int2e: amend our copy of command, not users command
  146. ; 19 Jun 89 Remove "Alternative" methods of getting PD address
  147. ; 14 Jul 89 SideKick Plus checksum only done if STDERR is to CON
  148. ; (so when LAPLINK does CTTY COM1 it goes quicker)
  149. ;  6 Sep 89 Call INT21/5D09,5D08 in readline
  150. ; 30 Oct 89 Throw away startup code (put it in STACK segment)
  151. ; 13 Nov 89 Relocate DRDOS resident code over command line/fcbs in PSP
  152. ; 30 Jan 90 in_exec is now incremented and decremented to allow
  153. ; novell menu program to exit successfully.
  154. ; 30 Jan 90 Added batch_seg_ptr before first occurance of string
  155. ; 'A:COMMAND.COM' (reload_file). Novell uses it during
  156. ; remote boot.
  157. ; 31 Jan 90 restore_term_addr puts back old Int22/23/24 ready for
  158. ; an EXIT command (DESQview bug)
  159. ; If no environment make reload_file in root of default drive
  160. ;  7 Feb 90 Turn off HILOAD on DRDOS
  161. ; Add d2cgroupptr support routine (see COM.C)
  162. ; 27 Mar 90 turn history buffers to command when in readline, so COPY CON
  163. ; etc will use application buffers
  164. ; 30 Mar 90  Stop cleanly when we can't reload transient portion rather
  165. ; than overwriting other peoples memory and crashing
  166. ;  4 Apr 90 dbcs_init moved from DOSIF, use system table,
  167. ; throw away init code
  168. ; 12 Apr 90 changed for no inherited environment
  169. ; 18 Apr 90 add JW's changes to int10_cls to support JW's new VGA card
  170. ;  9 May 90 Int2E doesn't trash Int24, returns with CY clear
  171. ; 17 May 90 CLI/STI round stack swap in INT2E exit routine.
  172. ;  5 Jun 90 Int21/4458 checks CY before fetching PD, so if running on DOS
  173. ; we carry on into the C code which gives version error
  174. ; 12 Jun 90 master_env now leaves MS_M_STARTEGY alone, because Novell
  175. ; gets confused if it ends up high
  176. ;  3/Jul/90 DLS data into R_TEXT for Watcom C v7.0 (again - I originally
  177. ; did this on 20/Apr/90, but someone screwed up with the
  178. ; archive version managment).
  179. ;  2-Aug-90 RG-00- define LOGIN procedures for Stellar security
  180. ;  1-Sep-90 _msgfarptr added for DLS
  181. ; 13-Sep-90 COMSPEC=A:COMMAND.COM even when CDOS.COM
  182. ; 21-Sep-90 Increase TMP heap size so we can save initial state for
  183. ; subsequent login's.
  184. ; 26-Sep-90 We now switch to our own psp during an INT 2Eh.
  185. ;  This fixes bug experienced with NOVELL MENU.EXE on top of
  186. ; DR DOS 5.0.
  187. ; 11-Oct-90 CDOSTMP exec stashes unlinked MD in PSP for TSR auto-load
  188. ; 03-Dec-90 Stop corruption of DMD chain when allocating high memory for
  189. ; transient portion of command processor 
  190. ; 11 dec 90 CDOS.COM switches to TMP history buffer
  191. ; 13 dec 90 save ES around TMP P_EXEC (DRNET sometimes trashes it)
  192. ; 17 dec 90 exec of CMD call io_pckbd with cl=40h (must be 24 line)
  193. ; 26/Feb/91 Increased _rld_msgs maximum text size from 100 to 120.
  194. ; 11/Mar/91 Added show_help function. COMMAND.COM is now really
  195. ;       an EXE file with the help messages tagged onto the end.
  196. ; 25/Apr/91 Most of the resident code/data is now relocatable to high
  197. ; memory. Some Novell critical data is left in low memory.
  198. ; 15/May/91 Added dummy code to force at least one relocation item in
  199. ; .exe header so loader doesn't think file is EXEPACKed.
  200. ; 12/Jun/91 Added dummy code to allow Software Carousel to run.
  201. ; See int22_entry.
  202. ; 19 jun 91 disable control break until handler initialised
  203. ; 24/Jun/91 Changed memory allocation procedure on return from func 4B to
  204. ; allow Novell Remote Boot to work.
  205. ;  2 jul 91 our_cmd_int2f only has single parameter
  206. ; 26 jul 91 Novell dummy pipe filenames zero terminated
  207. ; 29 jul 91 A 1K far buffer is now allocated by alloc_com_memory. It is
  208. ; used by type, batch_read, and printf.
  209. ;  5 Aug 91 Call Get Extended Error (int 21 ah=59) after exec.
  210. ; 14 Aug 91 Put pointers to _batch, _batchflg, and _echoflg in low memory
  211. ; stub. This is primarily for Software Carousel.
  212. ;  4 Dec 91 Fixed problem with full environment trashing next DMD.
  213. ; 29 Apr 92 Rearranged DGROUP so that constant code and data appear after
  214. ; the stack - So that Multitasker need not save it.
  215. ; 10 Jun 92 show_help function now copes with doubled % characters.
  216. ;
  217. ;------------------------------------------------------------------------------
  218. .xlist
  219. include msdos.equ          
  220. include mserror.equ
  221. include char.def
  222. .list
  223. ; This is the offset in segment FFFF to which we will relocate.
  224. ; It is set to E0 to allow for a PCNFS bug
  225. HISEG_OFF equ 0E0h
  226. FALSE equ 0h
  227. TRUE equ not FALSE
  228. ThreeCOM equ TRUE
  229. Copy_Buffer_Size equ 0C80h ; 50k of buffer space in paras
  230. ; matches MAX_COPYBUF in COMCPY.C
  231. RLSTACK_SIZE equ 256+256 ; Reserve for ReadLine stack
  232. ; We need 260 bytes for possible
  233. ; buffer, plus a little stack
  234. ; If the stack overflows it isn't
  235. ; a disaster - we will just re-load
  236.             ; COMMAND.COM
  237. ifdef CDOSTMP
  238. C_HEAP_SIZE equ 1200h ; C routine Heap Size - TMP has
  239. else ;  extra to save ENV in
  240. ;C_HEAP_SIZE equ 0800h ; C routine Heap Size
  241. ;endif ; (observed sizes 500h-600h - IJ)
  242. C_HEAP_SIZE equ 0860h ; C routine Heap Size
  243. ; For safety increased that value as UNC filenames require 128 byte buffers
  244. ; allocated dynamically on tha stack. With respect to the observed sizes
  245. ; above it might be dangerous to leave that value at 0800h. I would have
  246. ; increased the value to 0A00 but then it does no longer fit into HMA. (JBM)
  247. endif
  248. ifdef DOSPLUS
  249. include f52data.def
  250. else
  251. .xlist
  252. include system.def
  253. include pd.def
  254. .list
  255. XIOS_HISTBUF equ 44 ; Get the History Buffer Address
  256. XIOS_PCKBD equ 32 ; Set keyboard/screen modes
  257. NETMOD_BIT equ 040h ; Network Module in MODULE_MAP
  258. ; Concurrent DOS System Data Page Format
  259. XIOS_ENTRY equ ds:dword ptr 0028h ; XIOS function Entry
  260. CCPMSEG equ es:word ptr 0040h ; OS Starting Paragraph
  261. MODULE_MAP equ es:byte ptr 0046h ; Concurrent Module Map
  262. NVCNS equ es:byte ptr 0047h ; Number of Virtual Consoles
  263. MFL equ es:word ptr 005Ah ; Memory Free List
  264. RLR equ es:word ptr 0068h ; Ready List Root
  265. VERSION equ es:word ptr 0078h ; OS Version String Offset
  266. MWDR equ es:word ptr 0098h ; Memory Window Decriptor
  267. BOOTDRV equ es:byte ptr 009Dh ; System Boot Drive
  268. ENVSIZE  equ es:word ptr 00B8h ; Environment Size Bytes
  269. DRNET_NODE equ es:byte ptr 00BAh ; DR-NET Node Number
  270. DRNET_FLAG equ es:byte ptr 00BB ; DR-NET Flags
  271. V386_PTR equ es:word ptr 00C8h ; 386 Data pointer
  272. CCBLIST equ es:word ptr 0C3Eh ; XIOS CCB$LIST
  273. INT17_PTR equ es:word ptr 0C46h ; XIOS INT 17 Mapping Array
  274. INT14_PTR equ es:word ptr 0C48h ; XIOS INT 14 Mapping Array
  275. CCB_OWNER equ es:word ptr 0 ; CCB Owning Process
  276. CCB_PCNS equ es:byte ptr 10 ; CCB Physical Console Number
  277. CCB_VCNS equ es:byte ptr 11 ; CCB Virtual Console Number
  278. MF_CODE equ 0004h ; MD flag bit
  279. endif
  280. ;
  281. ; Standard definitions for PSP variable
  282. ;
  283. PSP_TERM_IP equ es:word ptr 000Ah
  284. PSP_PARENT equ es:word ptr 0016h
  285. PSP_ENVIRON equ es:word ptr 002ch
  286. ifndef DOSPLUS
  287. ; The following Macro takes one parameter which is the Concurrent DOS
  288. ; function number.
  289. bdos MACRO func
  290. ifnb <func>
  291. mov cl,func
  292. endif
  293. int 224
  294. ENDM
  295. .xlist
  296. include ccpm.equ
  297. .list
  298. endif
  299. swap MACRO reg1, reg2
  300. push reg1
  301. push reg2
  302. pop reg1
  303. pop reg2
  304. ENDM
  305. page
  306. ifdef CDOSTMP
  307. ;
  308. ; For the Concurrent DOS TMP the CGROUP segments are defined
  309. ; first so that the CGROUP appears first in the .EXE file and
  310. ; can be converted to a .COM by "RELOC" or "EXE2BIN". This .COM
  311. ; file is then converted to a .CMD by the COM2CMD utility which
  312. ; uses the data embeded at the start of the code to generate the
  313. ; right groups.
  314. ;
  315. HGROUP GROUP HEADER
  316. HEADER SEGMENT para public 'HEADER'
  317. HEADER ENDS
  318. DGROUP GROUP RSP_SEG,PD_SEG,UDA_SEG,NULL,EXEC_CODE,_DATA,DATA,CONST,FIXED,_BSS,HEAP,c_common,STACK,DYNAMIC
  319. RSP_SEG SEGMENT para public 'CDOS_DATA'
  320. RSP_SEG ENDS
  321. PD_SEG SEGMENT para public 'CDOS_DATA'
  322. PD_SEG ENDS
  323. UDA_SEG SEGMENT para public 'CDOS_DATA'
  324. UDA_SEG ENDS
  325. NULL SEGMENT para public 'BEGDATA'
  326. NULL ENDS
  327. EXEC_CODE SEGMENT byte public 'DATA'
  328. EXEC_CODE ENDS
  329. _DATA SEGMENT byte public 'DATA'
  330. _DATA ENDS
  331. DATA SEGMENT byte public 'DATA'
  332. DATA ENDS
  333. CONST SEGMENT byte public 'CONST'
  334. CONST ENDS
  335. FIXED SEGMENT para public 'FDATA'
  336. FIXED ENDS
  337. _BSS SEGMENT word public 'BSS'
  338. _BSS ENDS
  339. HEAP SEGMENT word public 'BSS'
  340. HEAP ENDS
  341. c_common SEGMENT byte public 'BSS'
  342. c_common ENDS
  343. STACK SEGMENT para public 'BSS'
  344. STACK ENDS
  345. DYNAMIC SEGMENT para public 'DDATA'
  346. DYNAMIC ENDS
  347. endif
  348. ifndef CDOSTMP
  349. ; The following declarations declare the presence and order of
  350. ; various data segments within the DATA Group of the command
  351. ; processor.
  352. ;
  353. DGROUP GROUP R_TEXT, ED_TEXT, NULL, _DATA, DATA, CONST, FIXED, _BSS, HEAP, c_common, STACK, DYNAMIC
  354. R_TEXT SEGMENT para public 'CDOS_DATA'
  355. R_TEXT ENDS
  356. NULL SEGMENT byte public 'BEGDATA'
  357. NULL ENDS
  358. _DATA SEGMENT byte public 'DATA'
  359. _DATA ENDS
  360. DATA SEGMENT byte public 'DATA'
  361. DATA ENDS
  362. CONST SEGMENT byte public 'CONST'
  363. CONST ENDS
  364. FIXED SEGMENT byte public 'FDATA'
  365. FIXED ENDS
  366. _BSS SEGMENT byte public 'BSS'
  367. _BSS ENDS
  368. HEAP SEGMENT byte public 'BSS'
  369. HEAP ENDS
  370. c_common SEGMENT byte public 'BSS'
  371. c_common ENDS
  372. STACK SEGMENT word public 'STACK'
  373. STACK ENDS
  374. ED_TEXT SEGMENT para public 'CDATA'
  375. Public ed_text_start
  376. ed_text_start label byte
  377. ED_TEXT ENDS
  378. DYNAMIC SEGMENT para public 'DDATA'
  379. DYNAMIC ENDS
  380. endif
  381. CGROUP GROUP _TEXT, _MSG, _TEXTEND
  382. _TEXT SEGMENT para public 'CODE'
  383. ifdef DLS
  384. extrn _my_dls_init:far
  385. endif
  386. _TEXT ENDS
  387. _MSG SEGMENT byte public 'CODE'
  388. _MSG ENDS
  389. _TEXTEND SEGMENT para public 'CODE'
  390. _TEXTEND ENDS
  391. CEND GROUP ETEXT, ETEXTEND
  392. ETEXT SEGMENT para public 'XEND'
  393. ETEXT ENDS
  394. ETEXTEND SEGMENT para public 'XEND'
  395. ETEXTEND ENDS
  396. codeOFFSET equ offset CGROUP:
  397. dataOFFSET equ offset DGROUP:
  398. endOFFSET equ offset CEND:
  399. code_length equ codeOFFSET rlstack  ; Total Code Length
  400. real_code equ code_length - RLSTACK_SIZE
  401. static_length equ dataOFFSET FIXED  ; Static Data Length
  402. dynamic_length equ dataOFFSET ed_text_start
  403. total_length equ dataOFFSET DYNAMIC  ; Total Data Length
  404. cgroup_length equ codeOFFSET _TEXTEND
  405. cend_length equ endOFFSET ETEXTEND
  406. ; help_length is an APPROXIMATE value, but it must be LARGER than the correct
  407. ; length of the help segment.
  408. ifdef DLS
  409. help_length equ 0A000h  
  410. else
  411. help_length equ 05000h
  412. endif
  413. page
  414. public __acrtused ; trick to force in startup
  415. __acrtused = 9876h ; funny value not easily matched in SYMDEB
  416. ifdef CDOSTMP
  417. HEADER SEGMENT public 'HEADER'
  418. dw 0EDCh ; Header Signature
  419. dw offset HGROUP:CGROUP ; Code Group
  420. dw real_code ; Real Code Size
  421. dw offset HGROUP:DGROUP
  422. dw total_length
  423. dw static_length
  424. HEADER ENDS
  425. ; These Segments are forced into the correct order for a CDOS 
  426. ; Resident System Process. First the RSP header which contains
  427. ; the regeneration information required by GENSYS.
  428. ;
  429. RSP_SEG SEGMENT
  430. sysdatseg dw 0 ; system data segment
  431. sdatvar dw 0047h ; # of system consoles
  432. defconsole db 0,0 ; console # | copy #
  433. dw 0,0
  434. dw RSF_DYNAMIC+RSF_SPECIAL+RSF_ENVIRON
  435. dw 0
  436. dw 0
  437. RSP_SEG ENDS
  438. _DATA SEGMENT byte public 'DATA'
  439. extrn _gp_far_buff:word
  440. _DATA ENDS
  441. else
  442. R_TEXT SEGMENT
  443. assume cs:DGROUP, ds:nothing, es:nothing, ss:nothing
  444. ifdef WATCOMC
  445. Public _small_code_ ; Watcom C requires this label to
  446. _small_code_ label near ; be declared in the start-up module
  447. else
  448. ifdef MWC
  449. Public _mwINIT ; MetaWare requires this label
  450. _mwINIT label near ; to be declared in the start-up
  451. ; module
  452. else
  453.     Public  __cstart       
  454. __cstart label near ; to be declared in the start-up
  455. ; module
  456. endif
  457. endif
  458. extrn _gp_far_buff:word
  459. ifdef DOSPLUS
  460. extrn com_criterr:near
  461. endif
  462. cstart: ; start address of all "C" programs
  463. call near ptr getIP ; Push the IP register and Skip the
  464. retIP: ; version control messages.
  465. dw 0EDCh ; Digital Research Marker
  466. dw code_length ; Length of the Code Group
  467. ;dw static_length ; Length of the Fixed Data Group
  468. ifdef DLS
  469. dw total_length
  470. else
  471. dw dynamic_length ; length of dynamic data
  472. endif
  473. dw total_length ; Minimum Length of the Runtime
  474. ; Data Group
  475. reloc_off dw 0 ; offset of relocated resident code/data 
  476. reloc_seg dw 0 ; segment of relocated resident code/data
  477. reloc_size dw 0 ; size of relocated resident code/data
  478. public _batchptr_off
  479. public _batchflg_off
  480. public _echoflg_off
  481. _batchptr_off dw 0 ; offset of _batch variable
  482. _batchflg_off dw 0 ; offset of _batchflg variable
  483. _echoflg_off dw 0 ; offset of _echoflg variable
  484. ; These are the entry points for INT 23 and INT 24. They will have JMPF
  485. ; instructions poked into them.
  486. control_break_entry db 5 dup(90h)
  487. crit_error_entry db 5 dup(90h)
  488. ; The call to MS_X_EXEC must be made from the same segment as the PSP.
  489. ; msdos_exec does a far jump to here and then we far jump back.
  490. psp_dofunc4b:
  491. mov ax,(MS_X_EXEC*256)
  492. int DOS_INT
  493. jmp   i22_entry
  494. ; Software Carousel Version 5.0 looks for the following three instructions
  495. ; and assumes it is an entry point to int 22 code.
  496. mov bx,0ffffh
  497. mov ah,48h
  498. int 21h
  499. clc
  500. i22_entry:
  501. int22_entry db 0eah
  502. dw dataOFFSET func4b_return
  503. func4b_seg dw 0
  504. int2E_entry db 0eah
  505. dw dataOFFSET int2E_far_entry
  506. int2E_seg dw 0
  507. ; IMPORTANT - batch_seg_ptr MUST be just before reload_file. - EJH
  508. ;
  509. ; ***** Do Not change the order of the following variables *****
  510. ;
  511. batch_seg_ptr dw 0ffffh ; file filename. For novell remote
  512. ; boot support.
  513. ifdef DOSPLUS
  514. reload_file db 'A:COMMAND.COM',0
  515. else
  516. ifdef NETWARE
  517. reload_file db 'A:NETWARE.COM',0
  518. else
  519. reload_file db 'A:CDOS.COM',0
  520. endif
  521. endif
  522. db (80-15) dup ('n') ; Expanded LoadPath
  523. ;cmdline db 128 dup ('c') ; Local Copy of Initial Command Line
  524. ; dummy pipe filenames for NOVELL
  525. out_pipe  db '_:/' , 0 , '_______.___',0
  526. in_pipe db '_:/' , 0 , '_______.___',0
  527. ;
  528. ; ***** Do Not change the order of the preceeding variables *****
  529. ;
  530. ; This next bit forces hi_seg_start to be on a paragraph boundary 
  531. org HISEG_OFF
  532. hi_seg_start label byte
  533. ; Himem Registration chain entry
  534. himem_link_next dw 0
  535. himem_link_size dw 0
  536. db 5
  537. public __psp
  538. __psp dw 0
  539. Public _batch_seg_ptr
  540. _batch_seg_ptr dw dataOFFSET batch_seg_ptr
  541. dw 0 ; segment will be set to low_seg
  542. Public _cbreak_ok
  543. _cbreak_ok db 0 ; set when ctrl-break handler initialised
  544. ; The following causes there to be at least one relocation item
  545. ; in the .exe header so the loader does not think the file is
  546. ; EXEPACKed.
  547. mov ax,seg _batch_seg_ptr
  548. R_TEXT ENDS
  549. endif
  550. _TEXT SEGMENT
  551. ifdef  CDOSTMP
  552. assume cs:CGROUP, ds:DGROUP, ss:DGROUP
  553. ;
  554. ; This entry point is used when the startup is executed as an
  555. ; RSP. CS is CGROUP and DS is DGROUP. From here on we initialise
  556. ; internal data structures etc. 
  557. ;
  558. ifdef WATCOMC
  559. Public _small_code_ ; Watcom C requires this label to
  560. _small_code_ label near ; be declared in the start-up module
  561. else
  562. ifdef MWC
  563. Public _mwINIT ; MetaWare requires this label
  564. _mwINIT label near ; to be declared in the start-up
  565. ; module
  566. else
  567.     Public  __cstart       
  568. __cstart label near ; to be declared in the start-up
  569. ; module
  570. endif
  571. endif
  572. cstart:
  573. call RSP_start ; Push the IP register and Skip the
  574. retIP: ; version control messages.
  575. dw 0EDCh ; Digital Research Marker
  576. dw code_length ; Length of the Code Group
  577. dw static_length ; Length of the Fixed Data Group
  578. dw total_length ; Minimum Length of the Runtime
  579. ; Data Group
  580. else
  581.   extrn _int2e_handler:far
  582. endif
  583. extrn __main:far ; C main program
  584. _TEXT ENDS
  585. _DATA SEGMENT
  586. ;
  587. ; Data held in this segment remains in the resident portion of 
  588. ; the program image is is not overlayed by transient programs
  589. ; loaded by COMMAND.COM. The variables here are private to the
  590. ; startup module.
  591. ;
  592. psp_save_area dw 6 dup (?)
  593. ifndef DOSPLUS
  594. extrn _pd:dword ; Concurrent Process Descriptor
  595. extrn _sysdat_seg:word ; Concurrent System Data Page
  596. endif
  597. extrn _n_option:word
  598. ;
  599. ; The following is the offset and segment of the C routine MAIN
  600. ; which is moved up in memory in order to accomodate the
  601. ; Environment variables and Resident Data area.
  602. ;
  603. C_code_entry label dword
  604. Public code_seg,low_seg
  605. code_off dw codeOFFSET __main ; Offset of MAIN
  606. code_seg dw ? ; Segment of MAIN
  607. data_seg dw ? ; DGROUP segment
  608. alloc_seg dw ? ; the start of hi mem allocated
  609. low_seg dw ? ; segment of low memory stub.
  610. ifdef CDOSTMP
  611. Public __psp
  612. __psp dw 0
  613. cmd_histbuf dw 0 ; Command Processor History Buffer
  614. prog_histbuf dw 0 ; Program History Buffer
  615. mpb label word
  616. mpb_start dw ?
  617. mpb_min dw ?
  618. mpb_max dw ?
  619. mpb_pdadr dw ?
  620. mpb_flags dw ?
  621. sysdat dw ? ; Concurrent System Data Page
  622. uda dw ? ; Concurrent User Data Area
  623. ;
  624. ; The following buffer is used by the P_EXEC function. Used
  625. ; by CDOS_EXEC to load DOS and CP/M programs.
  626. ;
  627. exec_block label byte
  628. exec_pathoff dw ? ; Offset of ASCIIZ Load file
  629. exec_pathseg dw ? ; Segment of ASCIIZ Load File
  630. exec_filetype db ? ; File Type Index
  631. exec_loadtype db ? ; EXEC or CHAIN to application
  632. exec_clineoff dw ? ; ASCIIZ Command line Offset
  633. exec_clineseg dw ? ; ASCIIZ Command Line Segment
  634. exec label dword ; FAR pointer to EXEC routine
  635. dw dataOFFSET cdos_exec
  636. exec_seg dw ?
  637. cmdline db 0 ; Blank Command Line
  638. EXEC_CODE SEGMENT
  639. Assume CS:DGROUP, DS:DGROUP, SS:DGROUP
  640. err_tbl db 0 ; 00 Success
  641. db -101 ; 01 System Call Not Implemented
  642. db -102 ; 02 Illegal System Call
  643. db ED_MEMORY ; 03 Cannot Find Memory
  644. db -104 ; 04 Illegal Flag Number
  645. db -105 ; 05 Flag Overrun
  646. db -106 ; 06 Flag Underrun
  647. db -107 ; 07 No Unused Queue Descriptors
  648. db -108 ; 08 No free Queue Buffer
  649. db -109 ; 09 Cannot find Queue
  650. db -110 ; 10 Queue in Use
  651. db -111 ; 11
  652. db -112 ; 12 No Free Process Descriptors
  653. db -113 ; 13 No Queue Access
  654. db -114 ; 14 Empty Queue
  655. db -115 ; 15 Full Queue
  656. db -116 ; 16 CLI Queue missing
  657. db -117 ; 17 No 8087 in system
  658. db ED_DMD ; 18 No Unused Memory Descriptors
  659. db -119 ; 19 Illegal Console Number
  660. db -120 ; 20 No Process Descriptor Match
  661. db -121 ; 21 No Console Match
  662. db -122 ; 22 No CLI Process ??
  663. db -123 ; 23 Illegal Disk Number
  664. db -124 ; 24 Illegal FileName
  665. db -125 ; 25 Illegal FileType 
  666. db -126 ; 26 Character Not Ready
  667. db ED_BLOCK ; 27 Illegal Memory Descriptor
  668. db -128 ; 28 Bad Return from BDOS load
  669. db ED_FAIL ; 29 Bad Return from BDOS read
  670. db ED_ACCESS ; 30 Bad Return from BDOS Open
  671. db -131 ; 31 Null Command
  672. db ED_ENVIRON ; 32 Not owner of resource
  673. db -133 ; 33 No Cseg in Load File
  674. db -134 ; 34 PD exists on Thread Root
  675. db -135 ; 35 Could Not Terminate Process
  676. db -136 ; 36 Cannot ATTACH to Process
  677. db -137 ; 37 Illegal List Device Number
  678. db ED_PASSWORD ; 38 Illegal Password
  679. db -139 ; 39
  680. db -140 ; 40 External Termination
  681. db -141 ; 41 Fixup Error on Load
  682. db -142 ; 42 Flag Set Ignored
  683. db -143 ; 43 Illegal Aux Device Number
  684. cdos2dos PROC NEAR
  685. cmp ax,0000 ; Check for Success
  686. jz c2d10 ; and skip lookup
  687. lea bx,err_tbl ; xlat the error code in AL
  688. xlat err_tbl ; into a Negated DOS compatible
  689. mov ah,0FFH ; error code
  690. c2d10:
  691. ret
  692. cdos2dos ENDP
  693. ; WORD FAR CDECL cdos_exec(BYTE *path, UWORD type, BYTE *line, BOOLEAN back);
  694. ;
  695. ; On Entry:
  696. ; back 10[bp]
  697. ; line 08[bp]
  698. ; type 06[bp]
  699. ; path 04[bp]
  700. ;
  701. ; ES = SYSDAT
  702. ;
  703. ; On Exit:
  704. ; AX = exit error code
  705. ;
  706. cdos_exec PROC FAR
  707. lea si,P_MEM[bx] ; SI -> root of MD's
  708. ce_10: ; find our code segment
  709. mov si,es:[si] ; get next memory descriptor
  710. test si,si ; end of list?
  711.  jz ce_40 ; yes, we don't own any separate code
  712. test es:word ptr 6[si],MF_CODE
  713.  jz ce_10 ; loop back if not code segment
  714. mov si,es:8[si] ; get MPAD for code segment
  715. lea di,P_MPAR[bx] ; get MPAD root
  716. ce_20:
  717. cmp si,es:[di] ; is this the predecessor?
  718.  je ce_30
  719. mov di,es:[di] ; else check next MPAD
  720. jmp short ce_20
  721. ce_30: ; SI -> our MPAD, DI -> previous MPAD
  722. xor ax,ax
  723. xchg ax,es:[si] ; get next MPAD
  724. mov es:[di],ax ; unlink our MPAD from list
  725. ce_40:
  726. push di
  727. push si ; SI = 0 if no separate code alloc
  728. push ds
  729. mov ds,es:P_PSP[bx] ; point to our PSP
  730. mov ds:word ptr [5eh],si ; stash TMP mpad away in here
  731. pop ds
  732. mov dx,198 ; Raise the priority of the TMP
  733. bdos P_PRIORITY ; while we wait for the child
  734. mov dx,dataOFFSET exec_block
  735. push es ; do a P_EXEC but save /restore
  736. bdos P_EXEC ; ES around it since DRNET trashes
  737. pop es ; it sometimes.
  738. mov ax,cx ; Get the Concurrent Error Code
  739. call cdos2dos ; and convert to a standard DOS
  740. push ax
  741. ; Error Code for COMMAND.RSP
  742. test ax,ax ; If any errors occured during the 
  743.  jnz ce_60 ; exec or the child process is not
  744. cmp word ptr 10[bp],0 ; inheriting the console the do not
  745.  jnz ce_60 ; execute a Console Attach function
  746. bdos C_ATTACH ; process to terminate
  747. ce_60:
  748. mov dx,200 ; Return to the normal priority
  749. bdos P_PRIORITY ; now that we have the console back
  750. pop ax
  751. pop si
  752. pop di
  753. test si,si ; separate code allocation?
  754.  jz ce_50 ; no, don't have to un-kludge!
  755. push ax
  756. mov ax,es:[di] ; get link of previous MPAD
  757. mov es:[si],ax ; link it to our MPAD
  758. mov es:[di],si ; link our MPAD to previous MPAD
  759. mov dx,1 ; make sure code gets banked in
  760. bdos P_DELAY ; this gets us off/on RLR
  761. pop ax
  762. ce_50:
  763. ret
  764. cdos_exec ENDP
  765. EXEC_CODE ENDS
  766. _TEXT SEGMENT
  767. assume cs:CGROUP, ds:DGROUP, es:nothing, ss:nothing
  768. public _exec ; EXEC routine
  769. ;
  770. ; WORD CDECL exec(BYTE *path, UWORD type, BYTE *line, BOOLEAN back);
  771. ;
  772. ; On Entry:
  773. ; back 10[bp] ; This value is ignored for MSDOS_EXEC
  774. ; line 08[bp]
  775. ; type 06[bp]
  776. ; path 04[bp]
  777. ;
  778. ; On Exit:
  779. ; AX = exit error code
  780. ;
  781. _exec:
  782. ;-----
  783. push bp
  784. mov bp,sp
  785. push si
  786. push di
  787. mov ax,04[bp] ; Get the Full Command Name
  788. mov exec_pathoff,ax
  789. mov exec_pathseg,ds
  790. mov ax,08[bp] ; and the Command Line
  791. mov exec_clineoff,ax
  792. mov exec_clineseg,ds
  793. mov ax,06[bp] ; Get the Command Type (.CMD etc)
  794. mov exec_filetype,al ; Save the Command type
  795. mov exec_loadtype, 0 ; The default is to load the command
  796. cmp word ptr 10[bp],0 ; and for the child to inherit the
  797.  jz exec_10 ; console
  798. mov exec_loadtype,2
  799. exec_10:
  800. test al,al ; is command type a CMD
  801.  jnz exec20 ; no, skip XIOS call
  802. mov ax,XIOS_PCKBD ; CMD's expect 24 lines
  803. mov cl,40h ; so tell XIOS thats what we must have
  804. mov dl,defconsole ; on this console
  805. call xios
  806. exec20:
  807. les bx,_pd ; Get the process Descriptor Address
  808. mov cx,prog_histbuf ; and force the system to use the
  809. mov es:P_SB_SEG[bx],cx ; Program Level History Buffer
  810. call exec ; do FAR call to cdos_exec
  811. les bx,_pd ; Get the process Descriptor Address
  812. mov cx,cmd_histbuf ; and force the system to use the
  813. mov es:P_SB_SEG[bx],cx ; Command Level History Buffer
  814. cmp exec_filetype,0 ; was it a CMD
  815.  jne exec30
  816. push ax
  817. mov ax,XIOS_PCKBD ; we are in must-be-24 line
  818. mov cl,0 ; mode, get back to default mode
  819. mov dl,defconsole ; for console number
  820. call xios
  821. pop ax
  822. exec30:
  823. pop di
  824. pop si
  825. pop bp
  826. ret
  827. _TEXT ENDS
  828. Assume CS:DGROUP, DS:DGROUP, SS:DGROUP
  829. else
  830. ;
  831. ; Novell 2.1 intercepts the DOSPLUS 4B00  return by updating the
  832. ; PSP USER_SS/SP and  when it returns ALL registers except CS:IP
  833. ; have been corrupted.
  834. ;
  835. extrn stack_min:word ; Minimum Stack Address
  836. extrn heap_top:word
  837. readline label dword ; FAR pointer to READLINE routine
  838. dw dataOFFSET msdos_readline
  839. readline_seg dw ?
  840. critical dd ? ; Critical Error Handler Address
  841. exec_sp dw ?
  842. exec_ss dw ?
  843. exec_block label byte
  844. exec_env dw ? ; Environment Segment
  845. exec_clineoff dw ? ; ASCIIZ Command line Offset
  846. exec_clineseg dw ? ; ASCIIZ Command Line Segment
  847. exec_fcb1off dw dataOFFSET fcb1 ; FCB1 Contents Offset
  848. exec_fcb1seg dw ? ; FCB1 Contents Segment
  849. exec_fcb2off dw dataOFFSET fcb2 ; FCB2 Contents Offset
  850. exec_fcb2seg dw ? ; FCB2 Contents Segment
  851. exec label dword ; FAR pointer to EXEC routine
  852. dw dataOFFSET msdos_exec
  853. exec_seg dw ?
  854. msdos_exec_ret label dword ; FAR pointer to exit EXEC routine
  855. dw codeOFFSET _exec_ret
  856. msdos_exec_ret_seg dw ?
  857. fcb1 db 16 dup (?) ; FCB1 Buffer
  858. fcb2 db 16 dup (?) ; FCB2 Buffer
  859. crc dw ? ; COMMAND.COM crc
  860. ; For Dual Language Support...
  861. ifdef DLS
  862. ;;ED_TEXT SEGMENT para public 'CDATA'
  863. Public _rld_msgs,_rld_text
  864. _rld_msgs dw 120 ;RELOAD_LEN ; size of this message buffer
  865. _reload_msgs dw 0 ; First part of Code reload prompt
  866. _reload_msgf dw 0 ; Second part of Code reload prompt
  867. _reload_msgm dw 0 ; Unlikely part of Code reload prompt
  868. dw 0 ; end of list
  869. _rld_text db 120 dup (?) ; message text is placed here
  870. RELOAD_LEN equ $-_reload_msgs
  871. ;;ED_TEXT ENDS
  872. else
  873. extrn _reload_msgs:byte ; First part of Code reload prompt
  874. extrn _reload_msgf:byte ; Second part of Code reload prompt
  875. extrn _reload_msgm:byte ; No memory available message
  876. endif
  877. reload_flag db 0 ; Reloading Command Processor
  878. in_exec     db  0       
  879. high_code dw TRUE ; Enable High Code
  880. exe_file dw FALSE ; True if COMMAND.COM is really an EXE
  881. return_code dw ? ; Exec return code
  882. net_error_mode  db ?
  883. ; int2E data
  884. i2e_lock dw 0 ; mutex flag
  885. i2e_user_ss dw 0 ; users ss, sp
  886. i2e_user_sp dw 0
  887. i2e_stack dw 0
  888. i2e_cmd dw 0 ; offset of local copy of command line
  889. i2e_c_entry label dword
  890. i2e_c_offs dw codeOFFSET _int2e_handler
  891. i2e_c_seg dw ?
  892. i2e_i23vec label dword
  893. i2e_i23off dw ?
  894. i2e_i23seg dw ?
  895. i2e_i24vec label dword
  896. i2e_i24off dw ?
  897. i2e_i24seg dw ?
  898. endif
  899. _DATA ENDS
  900. _BSS SEGMENT
  901. Public _edata
  902. _edata label BYTE ; end of data (start of bss)
  903. _BSS ENDS
  904. ETEXT SEGMENT
  905. ;
  906. ; The RLSTACK segment holds the stack used by the READLINE routine.
  907. ; This must be in High memory for the PolyTron PolyWindows product.
  908. ;
  909. ; "ETEXT" also forces the linker to pad the CGROUP to at least
  910. ; real_code bytes. Otherwise the file length can be upto 15 bytes 
  911. ; shorter then real_code + total_length. This obviously causes 
  912. ; problems with CALC_CRC and the file reloading.
  913. ;
  914. db RLSTACK_SIZE dup(0CCh)
  915. rlstack label word
  916. ETEXT ENDS
  917. ifdef CDOSTMP
  918. STACK SEGMENT
  919. Public _end
  920. _end label BYTE ; end of bss (start of starup/stack)
  921.   db (C_HEAP_SIZE - 6) dup (0DDh) ; C Heap Area
  922. stack_top label word
  923. stack_ip dw ? ; Initial Offset
  924. stack_cs dw ? ; Initial Code Segment (Unknown)
  925. stack_flags dw ? ; Initial Flags (Unknown)
  926. temp_buffer db 512 dup(0) ; temp far buffer for *gp_far_buff
  927. STACK ENDS
  928. else
  929. STACK SEGMENT
  930. stack_start:
  931. ; HEAP_TOP is initialised to _end so the _RELOAD_FILE and CMDLINE
  932. ; variables are allocated on the HEAP.
  933. ;
  934. Public _end
  935. _end label BYTE ; end of bss (start of startup/stack)
  936. db 255,'3771146-XXXX-654321'
  937. page
  938. ;
  939. ; The CS register is now adjusted so that this startup
  940. ; can be used in the form of an .EXE or .COM. Whatever the 
  941. ; execution format of this file DS still points at the PSP
  942. ; but must be careful when resizing the RAM.
  943. ;
  944. getIP PROC FAR
  945. cld ; be sure of DIR flag...
  946. pop di ; Get the Program Counter
  947. sub di,dataOFFSET retIP ; Correct for retIP
  948. mov cl,4 ; Convert Offset values to Segments
  949. mov ax,cs ; Get the current CS
  950. shr di,cl ; Convert Initial IP to Segment
  951. add ax,di ; add to CS and save for CALLF to MAIN
  952. push ax ; Save the New CS and the offset to
  953. mov ax,dataOFFSET gotCS ; the next instruction and then execute
  954. push ax
  955. ret ; a RETF instruction to correct CS.
  956. getIP ENDP
  957. ifdef DOSPLUS
  958. ; Most of the PSP (FCB's and command buffer) is unused - we reclaim this space
  959. ; by relocating the resident part of COMMAND.COM
  960. reloc_code:
  961. ;----------
  962. ; On Entry:
  963. ; CS = DGROUP, DS = PSP, ES = nothing
  964. ; On Exit:
  965. ; CS = relocated DGROUP
  966. ;
  967. ; We build a "REP MOVSB ! RETF 6" on the stack. We also fiddle the near return
  968. ; address into a FAR. We then setup our registers appropriately and execute
  969. ; this code.
  970. ;
  971. if 1
  972. ret
  973. else
  974. cmp ds:byte ptr 0080h,7fh ; discard garbage cmdline lengths
  975. jb reloc_code10
  976. ret
  977. reloc_code10:  
  978. pop bx ; recover return offset
  979. mov ax,0
  980. push ax ; 0 (part of RETF 6)
  981. mov ax,006cah
  982. push ax ; RETF 6 on stack
  983. mov ax,0a4f3h
  984. push ax ; REP MOVSB on stack
  985. mov al,ds:0080h ; Get the Command length
  986. xor ah,ah
  987. mov cl,4 ; convert AX to cmdline length
  988. shr ax,cl ; in rounded down para's
  989. add ax,9 ; keep at least this much
  990. mov si,ds
  991. add ax,si ; add in PSP
  992. mov es,ax
  993. mov cx,sp ; save address of code on stack
  994. push ax
  995. push bx ; new RETF address on stack
  996. push ss
  997. push cx ; address of CODE on stack
  998. push cs
  999. pop ds ; DS -> DGROUP
  1000. xor si,si ; setup DS:SI, ES:DI and CX
  1001. xor di,di ;  ready to do REP MOVSB
  1002. mov cx,total_length ; DGROUP length
  1003. add cx,real_code ;+CGROUP length
  1004. db 0cbh ; RETF to code on stack
  1005. endif
  1006. endif
  1007. gotCS:
  1008. ;out 0fdh,al ; for debug purposes
  1009. mov [__psp],ds ; Save our PSP in the local variable
  1010. ifdef DOSPLUS
  1011. mov ax,cs ; put our stack somewhere safe
  1012. mov ss,ax
  1013. mov sp,dataOFFSET rlstack
  1014. push ds
  1015. push di
  1016. call reloc_code ; relocate code over unused bit of PSP
  1017. pop di
  1018. pop ds
  1019. endif
  1020. ifdef DLS
  1021. call _my_dls_init
  1022. endif
  1023. mov [code_seg],cs ; Initialise the DATA segment address
  1024. mov [data_seg],cs ; and calculate the current address
  1025. mov [exec_seg],cs ; of the Code Segment
  1026. mov [readline_seg],cs ; use it to fixup some JMPFs
  1027. mov [_batch_seg_ptr+2],cs
  1028. mov [low_seg],cs     ; we may be relocated to upper or high
  1029.     ; memory so remember the current segment
  1030. mov bx,cs ; Path up the JMPF instructions
  1031. sub bx,[__psp] ; around the MSDOS EXEC code to
  1032. mov cl,4
  1033. shl bx,cl
  1034. add cs:[exec_psp-2],bx
  1035. mov cs:[func4b_seg],cs
  1036. mov cs:[int2E_seg],cs
  1037. mov cs:[exec_psp],ds
  1038. cmp di,0000h ; Disable Code Relocation if we have
  1039. jnz gotCS_10 ; been loaded as an .EXE file
  1040. ;;mov high_code,FALSE
  1041. mov exe_file,TRUE ; Remember we are an EXE
  1042. gotCS_10:
  1043. mov di,total_length
  1044. shr di,cl
  1045. add [code_seg],di
  1046. push ds ; Initialise the Checksum so we can
  1047. mov ds,[code_seg] ; check the integrity of the high
  1048. mov si,2  ; high copy of the command processor
  1049. call calc_crc ; code
  1050. pop ds
  1051. mov [crc],ax
  1052. mov ah,0ddh ; set Novell error mode
  1053. mov dl,0 ; to 00 - BAP
  1054. int 21h
  1055. mov net_error_mode,al ; save original error mode
  1056. call get_ds ; Get DGROUP value in AX
  1057. cli ; turn off interrupts
  1058. mov ss,ax ; SS = DGROUP
  1059. mov sp,dynamic_length ; Initialise SP
  1060. ;mov sp,total_length
  1061. sti ; turn interrupts back on
  1062. assume ss:DGROUP
  1063. push ax
  1064. call handler_init ; Initialise the Control Break and
  1065. pop ax ; Critical Error Interrupt Vectors
  1066. mov si,total_length ; Get the DGROUP length in bytes
  1067. add si,code_length ; Add in the Code Length
  1068. mov cl,4 ; and convert to a paragraphs
  1069. shr si,cl
  1070. mov bx,ax ; Get the Current DS
  1071. sub bx,__psp ; and calculate DS - PSP Seg
  1072. add bx,si ; DS + Data length in Para's
  1073. mov es,__psp
  1074. mov ah,MS_M_SETBLOCK
  1075. int DOS_INT
  1076. call exec_name ; Get our Load Path from the environment
  1077. cmp high_code,FALSE ; Skip Memory check if HIGH_CODE
  1078. jz cstart_10 ; support has been disabled
  1079. mov high_code,FALSE ; Assume Failure.
  1080. call alloc_com_memory ; Allocate high memory for command.com
  1081. jnc carry_on
  1082. mov ax,cs ; if no memory and CS is nearing
  1083. cmp ax,8000h ; transient part abort and go home.
  1084. jb cstart_10
  1085. mov ah,4ch
  1086. int 21h
  1087. carry_on:
  1088. mov high_code,TRUE ; Set HIGH_CODE flag TRUE
  1089. push es ; Relocate the command processor code
  1090. push ds ; into high memory
  1091. mov es,ax ; es-> destination segment
  1092. mov di,0
  1093. mov si,0
  1094. mov ds,code_seg ; ds-> code to be moved
  1095. mov cx,real_code ; convert bytes to words
  1096. shr cx,1
  1097. rep movsw ; Move code up to high memory
  1098. mov code_seg,es ; update code_seg
  1099. pop ds
  1100. pop es
  1101. ; Shrink memory containing low memory version of step aside code
  1102. mov si,total_length ; Get the DGROUP length in bytes
  1103. mov cl,4 ; and convert to a paragraphs
  1104. shr si,cl
  1105. call get_ds
  1106. mov bx,ax ; Get the Current DS
  1107. sub bx,__psp ; and calculate DS - PSP Seg
  1108. add bx,si ; DS + Data length in Para's
  1109. mov ah,MS_M_SETBLOCK
  1110. int DOS_INT
  1111. cstart_10:
  1112. ifdef DOSPLUS
  1113. mov ax,4457h ; terminate HILOAD operation
  1114. mov dx,200h
  1115. int DOS_INT
  1116. call dbcs_init ; initialise the DBCS support
  1117. endif
  1118. call get_cs
  1119. push ax
  1120. mov ax,codeOFFSET memory_init
  1121. push ax
  1122. db 0CBh ; a RETF instruction to correct CS.
  1123. page
  1124. ;
  1125. ; Build the full path and filename of this process using the
  1126. ; loadpath attached to the environment. If no filename exists
  1127. ; then prevent the Command Processor code from being located
  1128. ; in high memory.
  1129. ;
  1130. exec_name:
  1131. push es
  1132. mov es,__psp ; Get the PSP Segment Address
  1133. mov dx,PSP_ENVIRON ; Get the environment segment
  1134. cmp dx,0000 ; Have we got an environment ?
  1135. jz exec_n11 ; No prevent High Code Support
  1136. mov es,dx ; Scan through the environment and
  1137. mov di,0 ; determine the Environment size and
  1138. mov al,0 ; the Load file name
  1139. mov cx,7FFFh
  1140. exec_n05: ; Scan through the Environment
  1141. repne scasb ; searching for the 00 00 terminator
  1142. jcxz exec_n10 ; Terminate On CX == 0000
  1143. cmp es:byte ptr [di],al ; If the next byte is zero then this is
  1144. jnz exec_n05 ; then end of the environment
  1145. cmp es:word ptr 1[di],1 ; Are we pointing at the Control Word
  1146. jnz exec_n10 ; No then no Load Path exists
  1147. push ds
  1148. mov ds,dx  ; DS -> Environment Segment
  1149. ;call get_ds
  1150. ;mov es,ax  ; ES -> Command Processor Data Seg
  1151. mov es,[low_seg]
  1152. lea si,03[di]  ; Fully expand the filename so the
  1153. mov di,dataOFFSET reload_file ; user can SUBST drives
  1154. mov ah,60h
  1155. int DOS_INT
  1156. exec_n15:
  1157. if 0
  1158. mov di,dataOFFSET reload_file ; this ASCIIZ string is on the heap
  1159. xor ax,ax ;  so now we need to find out how
  1160. mov cx,-1 ;  much space it takes up and reserve
  1161. repne scasb ;  that amount of the heap
  1162. mov heap_top,di ; byte after the NUL is available
  1163. endif
  1164. pop ds
  1165. pop es
  1166. ret
  1167. exec_n10:
  1168. mov high_code,FALSE
  1169. exec_n11:
  1170. mov ah,MS_DRV_GET
  1171. int DOS_INT ; get default drive
  1172. mov es,[low_seg]
  1173. add es:reload_file,al ;  and use that for the comspec
  1174. push ds
  1175. ;call get_ds
  1176. ;mov es,ax  ; ES -> Command Processor Data Seg
  1177. jmp exec_n15
  1178. ifdef DOSPLUS
  1179. DI_BUF_PTR equ dword ptr -4 ; pointer to DBCS lead byte table
  1180. DI_BUF_ID equ byte ptr -5 ; buffer id
  1181. DI_BUF equ byte ptr -5 ; buffer
  1182. DI_LOCALS equ 5 ; No. bytes storage local to init_dbcs
  1183. _DATA SEGMENT byte public 'DATA'
  1184. Public dbcs_table_ptr
  1185. dbcs_table_ptr label dword
  1186. dbcs_table_off dw dataOFFSET dummy_dbcs_table
  1187. dbcs_table_seg dw 0
  1188. dummy_dbcs_table dw 0
  1189. _DATA ENDS
  1190. dbcs_init proc near
  1191. ;--------
  1192. ; To initialise the double byte character set (DBCS) lead byte table.
  1193. ; MUST be called before the first call to dbcs_lead() or dbcs_expected().
  1194. ; Entry
  1195. ; none
  1196. ; Exit
  1197. ; none (side effect: DBCS table initialised)
  1198. push bp
  1199. mov bp, sp
  1200. sub sp, DI_LOCALS ; allocate local variables
  1201. push ds
  1202. push es
  1203. push di
  1204. push si
  1205. mov dbcs_table_seg, ds ; assume DBCS call will fail
  1206. mov ax, 06507h ; Extended Country Info: get DBCS ptr
  1207. mov bx, 0FFFFh ; codepage number: -1 for global cp
  1208. mov cx, 00005h ; size of info. buffer
  1209. mov dx, 0FFFFh ; country code: -1 for current country
  1210. lea di, DI_BUF[bp]
  1211. push ss
  1212. pop es ; es:di -> DI_BUF
  1213. int 21h ; returns with DI_BUF filled in
  1214.  jc di_exit ; just exit if function fails
  1215. cmp DI_BUF_ID[bp], 7 ; is table for DBCS?
  1216.  jne di_exit ;  no - exit
  1217. les ax, DI_BUF_PTR[bp] ; es:ax -> system DBCS table
  1218. mov dbcs_table_off,ax
  1219. mov dbcs_table_seg,es ; fixup pointer to system DBCS table
  1220. di_exit:
  1221. pop si
  1222. pop di
  1223. pop es
  1224. pop ds
  1225. mov sp, bp
  1226. pop bp
  1227. ret
  1228. dbcs_init endp
  1229. endif
  1230. ; I want to do
  1231. ; db (C_HEAP_SIZE - 6 - ($ - stack_start)) dup (0DDh)
  1232. ; but MASM requires dup's be absolute, so instead
  1233. rept C_HEAP_SIZE
  1234. if (offset $ - offset stack_start) LT (C_HEAP_SIZE - 6)
  1235. db 0ddh
  1236. endif
  1237. endm
  1238. stack_top label word
  1239. stack_ip dw ? ; Initial Offset
  1240. stack_cs dw ? ; Initial Code Segment (Unknown)
  1241. stack_flags dw ? ; Initial Flags (Unknown)
  1242. STACK ENDS
  1243. ED_TEXT SEGMENT
  1244. ;
  1245. ; Return the CheckSum of All the C code and Static Data. DS:SI 
  1246. ; are initialised to point at the C_code_start. AX contains the
  1247. ; CheckSum on return.
  1248. ;
  1249. calc_crc:
  1250. mov cx,real_code ; Number of bytes to move is always
  1251. shr cx,1 ; even because of the segment def.
  1252. dec cx
  1253. mov bx,0EDCh ; Checksum Seed
  1254. cc_10: ; Sum the words of the image while
  1255. lodsw ; rotating the check value
  1256. add bx,ax
  1257. rol bx,1
  1258. loop cc_10
  1259. xchg ax,bx
  1260. ret
  1261. page
  1262. ;
  1263. ; Return the code segment of the C main routine.
  1264. ;
  1265. get_cs:
  1266. mov ax,cs:code_seg
  1267. ret
  1268. ;
  1269. ; Return the Data segment of the C data area
  1270. ;
  1271. get_ds:
  1272. mov ax,cs:data_seg
  1273. ret
  1274. ; Get remaining memory size, subtract code size and allocate high memory for
  1275. ; transient portion of command processor
  1276. ; Exit AX=Segment of high memory
  1277. ; CY set if none available
  1278. ; This used to allocate only just enough space for the code at the top of
  1279. ; memory and leave the reset free for use as copy buffers.
  1280. ; But then came SideKick Plus - this assumes COMMAND.COM only uses the top
  1281. ; 20K of it's hi-mem partion and overwrites the rest as it gets it's
  1282. ; overlays. As we are bigger the 20K the result is the system crashes when
  1283. ; you exit back to the command line.
  1284. ; In order to minimise this possibility we reserve some space (currently 50K)
  1285. ; for use as copy buffers and allocate all the rest to the hi-mem portion
  1286. ; of COMMAND.COM. Since SK starts overwriting from the bottom of memory it
  1287. ; doesn't usually reach the code.
  1288. ; The real solution is of course to make sure we are smaller than 20K too...
  1289. ; (Or transfer the ReadLine code into the resident portion and checksum the
  1290. ; hi-mem before returning to the hi-mem code ???).
  1291. ; --ij
  1292. public alloc_com_memory
  1293. alloc_com_memory:
  1294. push es
  1295. mov bx,0FFFFh ; Allocate more paras than there are
  1296. mov ah,MS_M_ALLOC ; to find out how many there are.
  1297. int  DOS_INT
  1298. mov ah,MS_M_ALLOC
  1299. int DOS_INT ; allocate it
  1300. mov si,code_length ; then convert the CODE_LENGTH to 
  1301. mov cl,4 ; paragraphs and check if enough memory
  1302. shr si,cl ; is available to copy the code high
  1303. add si,1  ; + para for a memory descriptor 
  1304. sub bx,si ; Is there enough for the code ?
  1305.  jc acm_10 ; if not exit with error
  1306. cmp bx,Copy_Buffer_Size ; allocate some memory for Copy Buffers
  1307.  jb acm_5
  1308. mov bx,Copy_Buffer_Size ; limit the maximum Copy Buffer size
  1309. acm_5:
  1310. mov es,ax
  1311. mov ah,MS_M_SETBLOCK
  1312. int DOS_INT ; shrink to fit
  1313. push es ; save buffer address
  1314. ; Now allocate remaining memory for step aside code
  1315. mov bx,0FFFFh ; allocate all memory
  1316. mov ah,MS_M_ALLOC ; to find out how much there is.
  1317. int  DOS_INT
  1318. mov ah,MS_M_ALLOC ; block at the end of memory
  1319. int DOS_INT ; AX=Segment of new block of memory
  1320. mov alloc_seg,ax ; save address so we can free it
  1321. if ThreeCOM
  1322. cmp bx,1000h ; do we have at least 64k ?
  1323.  jb acm_6 ; if so do 3-Com fix and start
  1324. mov si,1000h ; Transient portion 64k down
  1325. acm_6:
  1326. endif
  1327. add ax,bx ; go to top of memory we allocated
  1328. cmp ax,0a000h ; dont use memory above A000 as this
  1329. jb acm_6a ; may disappear when user does
  1330. mov ax,0a000h ; MEMMAX -V
  1331. acm_6a:
  1332. dec si
  1333. sub ax,si ; adjust address we run cmd proc at
  1334. ; Deallocate intervening block of memory
  1335. pop es
  1336. push ax
  1337. mov ah,MS_M_FREE ; Now free it up
  1338. int DOS_INT
  1339. pop ax
  1340. mov cs:_gp_far_buff,real_code
  1341. mov cs:_gp_far_buff+2,ax ; save address of temp buffer
  1342. clc ; allocated OK
  1343. acm_10:
  1344. pop es
  1345. ret
  1346. ; called to free up the cmd processor's high memory
  1347. free_com_memory:
  1348. push es
  1349. push ax
  1350. mov es,alloc_seg
  1351. mov ah,MS_M_FREE
  1352. int DOS_INT
  1353. pop ax
  1354. pop es
  1355. ret
  1356. ;Control_Break:
  1357. ; The Break handler makes the following checks taking the
  1358. ; appropriate action after each test:-
  1359. ;
  1360. ; 1) Is COMMAND.COM the current process (Get PSP) if NO ABORT
  1361. ; 2) Is the break_flag SET if YES jump to the C break handler
  1362. ;    "break_handler" after insuring that the segment registers
  1363. ;    have all be set correctly.
  1364. ;
  1365. assume cs:DGROUP, ds:nothing, es:nothing
  1366. ; Set up the default Control Break Handler.
  1367. handler_init:
  1368. ifndef DOSPLUS
  1369. mov ax,4453h ; Get the address of the
  1370. int DOS_INT ; internal Critical Error
  1371. jc handler_i10 ; handler Ignore on Error
  1372. mov word ptr critical+0,ax ; Save the handler Offset (AX)
  1373. mov word ptr critical+2,bx ; and Segment (BX)
  1374. endif
  1375. mov al,24h ; Set the default Critical
  1376. mov dx,dataOFFSET critical_error ; Error Handler
  1377. mov bx,dataOFFSET crit_error_entry
  1378. call set_vector ; Setup correct ISR
  1379. handler_i10:
  1380. mov al,23h ; Set the default Control
  1381. mov dx,dataOFFSET control_break ; Break Handler
  1382. mov bx,dataOFFSET control_break_entry
  1383. ;; jmp set_vector ; Setup correct ISR
  1384. ;
  1385. ; Convert the address of the interrupt #AL service routine, whose
  1386. ; address is CS:DX to be PSP:xxxx. Five NOP must be coded after the
  1387. ; interrupt service routine for the JMPF instruction which corrects
  1388. ; the code segment.
  1389. ;
  1390. set_vector:
  1391. push ds
  1392. push es
  1393. mov es,[low_seg]
  1394. mov es:byte ptr 0[bx],0EAh ; JMPF opcode
  1395. mov es:word ptr 1[bx],dx ; Offset of Interrupt vector
  1396. mov es:word ptr 3[bx],cs ; Insert the correct code seg
  1397. mov dx,bx
  1398. mov bx,es
  1399. sub bx,__psp ; Calculate the correct offset for
  1400. mov cl,4 ; the interrupt handler if the segment
  1401. shl bx,cl ; must be that of our PSP
  1402. add dx,bx
  1403. mov ds,__psp
  1404. mov ah,MS_S_SETINT
  1405. int DOS_INT
  1406. pop es
  1407. pop ds
  1408. ret
  1409. ;extrn _int_break:near ; C Break/Error handling routine 
  1410. assume cs:DGROUP, ds:DGROUP, es:nothing
  1411. control_break PROC FAR
  1412. ;;db 5 dup(90h) ; Reserve space for JMPF CS:$+5
  1413. push ax ; Save the Users registers
  1414. push bx
  1415. push ds
  1416. call get_ds ; Get our Local DS
  1417. mov ds,ax
  1418. cmp _cbreak_ok,0 ; is our handler initialised ?
  1419.  je break_05 ;  no, don't call it
  1420. cmp reload_flag,0 ; Are we part way through reloading
  1421. clc ;  the command processor?
  1422.  jnz break_05 ; if so do not abort.
  1423. mov ah, MS_P_GETPSP ; Get the current PSP address
  1424. int DOS_INT
  1425. cmp bx,[__psp] ; Is this our address
  1426. stc ; Assume not and Set the carry flag
  1427. jz break_10 ; if internal, restart the command loop
  1428. ; if external, abort process
  1429. break_05:
  1430. pop ds
  1431. pop bx
  1432. pop ax
  1433. ret
  1434. ;
  1435. ; This section of code corrects the stack and jumps to the 
  1436. ; C code Control Break Handler _int_break. Beware that the
  1437. ; stack segment need not be the DS because the READ_LINE routine
  1438. ; executes on a high stack and the CED programs will emulates
  1439. ; a Control-Break on the wrong Stack.
  1440. ;
  1441. break_10:
  1442. cli ; Swap to the correct stack not
  1443. mov ax,ds ; forgetting that we might be running
  1444. mov es,ax ; on old 8088 or 8086 so interrupts
  1445. mov ss,ax ; must be disabled
  1446. mov sp,stack_min ; Get the lowest possible stack address
  1447. add sp,12 ; Add a little to avoid problems with
  1448. sti ; the stack check code.
  1449. mov ax,0100h ; Termination Code Control-C Abort
  1450. push ax ; Save on the Stack for C routine
  1451. push ax ; Force a dummy return address on the
  1452. ; stack (NOT USED)
  1453. call get_cs ; Put the Segment and Offset address
  1454. push ax ; of the C break Handler on the stack
  1455. mov ax,codeOFFSET _int_break; and execute a RETF to it.
  1456. push ax
  1457. ret 
  1458. control_break ENDP
  1459. critical_error PROC FAR
  1460. ;;db 5 dup(90h) ; Reserve space for JMPF CS:$+5
  1461. push ds ; Save the Critical Error DS
  1462. push ax
  1463. call get_ds ; Get the Command Processor DS
  1464. mov ds,ax ; and call the original routine
  1465. ifdef DOSPLUS
  1466. mov  ax, _n_option ; check for /n command line option
  1467. cmp ax, 0
  1468. pop ax
  1469. jne skip_criterr
  1470. call com_criterr ; local criterr handler
  1471. jmp criterr_cont
  1472. skip_criterr:
  1473. mov al,3 ; /n option => always return fail
  1474. criterr_cont:
  1475. else
  1476. pop ax
  1477. pushf
  1478. call critical ; stored previous handler
  1479. endif
  1480. cmp al,02h ; Did the user request a Terminate
  1481.  jne critical_e20 ; Yes so check if they are trying to
  1482. push ax ; terminate the command processor
  1483. push bx
  1484. mov ah, MS_P_GETPSP ; Get the current PSP address
  1485. int DOS_INT
  1486. cmp bx,[__psp] ; Is this our address?
  1487.  jne critical_e10 ; no so return with Abort code
  1488. cmp in_exec,0 ; are we EXECing a program ?
  1489.  jne critical_e10 ;  then return the error
  1490. cmp reload_flag,0 ; then unless we are reloading command
  1491.  je break_10 ;  processor break here to prevent
  1492. critical_e10: ;  higher levels generating repeated
  1493. pop bx ;  critical errors (eg. when searching
  1494. pop ax ;  a path)
  1495. critical_e20:
  1496. pop ds
  1497. iret
  1498. critical_error ENDP
  1499. ;
  1500. ; INT2E is a backdoor entry to the "Permanent" Command interpreter 
  1501. ; which will execute the command at DS:SI.
  1502. ;
  1503. int2E_far_entry proc far
  1504. db 5 dup(90h) ; Reserve space for JMPF CS:$+5
  1505. ; ds:si -> command line preceded by byte count
  1506. ; check we're not re-entering
  1507. mov ax, 1
  1508. xchg cs:i2e_lock, ax
  1509. test ax, ax
  1510.  jz i2e_10
  1511. iret
  1512. i2e_10:
  1513. push bx
  1514. push cx
  1515. push dx
  1516. push si
  1517. push di
  1518. push bp
  1519. push ds
  1520. push es
  1521. ; if ds = si = 0 then set batch_seg_ptr to zero and get out.
  1522. ; This is a clean way of halting batch processing.
  1523. mov ax,ds
  1524. cmp ax,0
  1525. jne i2e_15
  1526. cmp si,0
  1527. jne i2e_15
  1528. mov si,cs:_batch_seg_ptr
  1529. mov ds,cs:_batch_seg_ptr+2
  1530. mov [si],ax
  1531. jmp i2e_exit2
  1532. i2e_15:
  1533. ; swap stack
  1534. mov cs:i2e_user_ss, ss
  1535. mov cs:i2e_user_sp, sp
  1536. cli
  1537. mov ss, cs:exec_ss
  1538. mov sp, cs:exec_sp
  1539. sti
  1540. ; allocate 128 bytes for command line, since the C code needs a 128 
  1541. ; byte buffer anyway
  1542. mov cx, 128
  1543. ; save stack p
  1544. mov cs:i2e_stack, sp
  1545. ; have we got enough room for command line 
  1546. mov ax, sp
  1547. sub ax, cx
  1548. sub ax, cs:heap_top
  1549. cmp ax, 256
  1550.  jge i2e_25
  1551. jmp i2e_exit
  1552. i2e_25:
  1553. sub sp, cx
  1554. mov cs:i2e_cmd, sp
  1555. ; copy command line
  1556. push ss
  1557. pop es
  1558. mov di, sp
  1559. lodsb ; get line count
  1560. and ax,7fh ; limit to 128 bytes
  1561. add ax,sp ; terminating NULL goes here
  1562. rep movsb ; copy the command line
  1563. xchg ax,di ; DI -> NUL posn
  1564. xor al,al
  1565. stosb ; replace CR with NUL
  1566. push cs
  1567. pop ds
  1568. ; reload non-resident code if necessary
  1569. cmp high_code, TRUE
  1570.  jnz i2e_30
  1571. mov reload_flag, 1
  1572. call reload_code
  1573. mov reload_flag, 0
  1574. i2e_30:
  1575. ; install our own Break and Criterr handlers - e.g. if second copy
  1576. ; of the command processor is running, install original handlers so
  1577. ; that they are looking at the same data as we are.
  1578. ; N.B. __psp is currently that of original command processor
  1579. mov ax, (MS_S_GETINT*256) + 23h
  1580. int DOS_INT
  1581. mov i2e_i23seg, es
  1582. mov i2e_i23off, bx
  1583. mov ax, (MS_S_GETINT*256) + 24h
  1584. int DOS_INT
  1585. mov i2e_i24seg, es
  1586. mov i2e_i24off, bx
  1587. call handler_init
  1588. ; save the command processor's __psp variable, and then set it to the
  1589. ; psp of the process that called us. This is so that the Break and 
  1590. ; Criterr abort code can correctly determine whether the int2e command 
  1591. ; was internal or external
  1592. mov ah, MS_P_GETPSP
  1593. int DOS_INT
  1594. push bx ; save calling process's psp - EJH
  1595. mov bx, [__psp]
  1596. ; Set current PSP to our own - EJH
  1597. mov ah, MS_P_SETPSP
  1598. int DOS_INT
  1599. ; call C code
  1600. mov ax, code_seg
  1601. mov i2e_c_seg, ax
  1602. push i2e_cmd
  1603. call i2e_c_entry
  1604. pop ax ; clean up stack
  1605. ; Set current psp back to that of calling process - EJH
  1606. pop bx
  1607. mov ah, MS_P_SETPSP
  1608. int DOS_INT
  1609. ; restore interrupt vecs
  1610. push ds
  1611. lds dx, i2e_i23vec
  1612. mov ax, (MS_S_SETINT*256) + 23h
  1613. int DOS_INT
  1614. lds dx, cs:i2e_i24vec
  1615. mov ax, (MS_S_SETINT*256) + 24h
  1616. int DOS_INT
  1617. pop ds
  1618. cmp high_code, TRUE ; If not a .EXE then free
  1619.  jnz i2e_ret ; any memory alocated by
  1620. call free_com_memory ; the Command Processor
  1621. i2e_ret:
  1622. i2e_exit:
  1623. ; swap back the stack
  1624. cli
  1625. mov ss, i2e_user_ss
  1626. mov sp, i2e_user_sp
  1627. sti
  1628. i2e_exit2:
  1629. pop es
  1630. pop ds
  1631. pop bp
  1632. pop di
  1633. pop si
  1634. pop dx
  1635. pop cx
  1636. pop bx
  1637.     sub ax, ax          
  1638. mov cs:i2e_lock, 0
  1639. ret 2
  1640. int2E_far_entry endp
  1641. _TEXT SEGMENT
  1642. assume cs:CGROUP, ds:DGROUP, es:nothing, ss:nothing
  1643. public _exec ; EXEC routine
  1644. ;
  1645. ; WORD CDECL exec(BYTE *path, UWORD type, BYTE *line, BOOLEAN back);
  1646. ;
  1647. ;   back    10[bp]      
  1648. ; line 08[bp]
  1649. ; type 06[bp]
  1650. ; path 04[bp]
  1651. ;
  1652. _exec:
  1653. ;-----
  1654. push bp
  1655. mov bp,sp
  1656. push si
  1657. push di
  1658. push ds
  1659. push es
  1660.     inc in_exec         
  1661.     cmp in_exec,1       
  1662.  je _exec10 ; Menuing system
  1663. push exec_ss ; save old stack_save if we
  1664. push exec_sp ;  are being re-entered
  1665. _exec10:
  1666. mov si,08[bp] ; the Command Line
  1667. mov exec_env,0000
  1668. mov exec_clineoff,si
  1669. mov exec_clineseg,ds
  1670. mov exec_fcb1seg,ds
  1671. mov exec_fcb2seg,ds
  1672. push ds
  1673. pop es
  1674. ;
  1675. ; Extract two valid filenames from the CR terminated
  1676. ; string passed in DS:SI. The FCBs will be generated in FCB1 and FCB2.
  1677. ;
  1678. inc si
  1679. mov di,dataOFFSET fcb1 ; Blank fill the first FCB
  1680. call zap_fcb
  1681. call make_fcb ; Build first FCB
  1682. mov di,dataOFFSET fcb2 ; Blank fill the Second FCB
  1683. call zap_fcb
  1684. call make_fcb ; Build second FCB
  1685. mov ax,cs
  1686. jmp exec ; do FAR jmp to msdos_exec as we can't
  1687. _exec_ret: ;  trust the stack when CALLing
  1688. dec in_exec ; Has PCTOOLS un-installed itself ?
  1689.  jz _exec20 ; No so the stack contents are valid
  1690.  js _exec_bad ; Yes, so exit by Ctrl-Break
  1691. pop exec_sp ; old stack save back again
  1692. pop exec_ss ;  in the case of re-entry
  1693. _exec20:
  1694. pop es
  1695. pop ds
  1696. pop di
  1697. pop si
  1698. pop bp
  1699. mov ax,return_code
  1700. neg ax
  1701. ret
  1702. ;
  1703. ; We have returned from the EXEC function un-expectedly (because
  1704. ; of PCTOOLS De-installation ?). Therefore the contents of the stack
  1705. ; are invalid and we generate a Control-Break.
  1706. ;
  1707. _exec_bad:
  1708. mov ax,0100h ; Termination Code Control-C Abort
  1709. push ax ; Save on the Stack for C routine
  1710. push ax ; Force a dummy return address on stack
  1711. mov in_exec,al ; zero in_exec count for next time
  1712. extrn _int_break:near ; C Break/Error handling routine 
  1713. jmp _int_break ; now treat as ctrl-break
  1714. ;
  1715. ; Initialise the FCB entry a DX:DI and copy the Drive, FileName
  1716. ; and extension form DS:SI when SI != 0FFFFh
  1717. ;
  1718. zap_fcb:
  1719. mov ax,2000h ; Zero Fill first byte and last 4
  1720. stosb ; Drive code 0
  1721. xchg al,ah
  1722. mov cx,11 ; FileName and Ext to ' '
  1723. rep stosb
  1724. xchg al,ah
  1725. mov cl,4 ; Last four bytes to 00
  1726. rep stosb
  1727. sub di,16
  1728. ret
  1729. make_fcb:
  1730. call scan_filechar ; Get the Next File Character
  1731. push si
  1732. push di
  1733. push ax ; Save Character and Pointers
  1734. mov ax,(MS_F_PARSE shl 8) + 1 ; Parse the command line
  1735. int DOS_INT
  1736. pop ax
  1737. pop di ; Restore the Character and Pointer
  1738. cmp ah,'/' ; Was the arg preceeded by a '/'
  1739. jne make_fcb10 ; If it was roll back the cmd line 
  1740. pop si ; pointer and blank all but the 1st
  1741. inc si ; char in the FCB
  1742. add di,2 ; Such that /FRED gives an FCB of 'F'
  1743. mov cx,10 ; and si points to the 'R'
  1744. mov al,' '
  1745. rep stosb
  1746. ret
  1747. make_fcb10:
  1748. pop ax ; discard original SI, skip name
  1749. jmp scan_sepchar ; skip until separator
  1750. ;
  1751. ; SCAN_SEPCHAR will search through the command line DS:SI
  1752. ; which contains CX characters and return with SI pointing
  1753. ; to the next SEPARATOR character.
  1754. ;
  1755. ; On Entry: DS:SI Character String
  1756. ;
  1757. ; On Exit: DS:SI First Non Separator
  1758. ;
  1759. scan_sepchar:
  1760. push di ; Save DI  ES points at this segment
  1761. mov ah,0 ; Invalidate Separator Character
  1762. scan_s10:
  1763. mov al,[si] ; Get the Character to Test
  1764. cmp al,CR
  1765. jz scan_s20 ; Have we reached the end of the string
  1766. mov cx,legal_length ; Scan the table of legal 
  1767. mov di,dataOFFSET legal_table ; separators
  1768. repnz scasb ; Scan the List
  1769. jz scan_s20 ; Separator Located
  1770. inc si ; the character pointer
  1771. jmp SHORT scan_s10
  1772. scan_s20:
  1773. pop di
  1774. ret
  1775. ;
  1776. ; SCAN_FILECHAR will search through the command line DS:SI
  1777. ; and return with SI pointing to the next NON_SEPARATOR character.
  1778. ;
  1779. ; On Entry: DS:SI Character String
  1780. ;
  1781. ; On Exit: DS:SI First Non Separator
  1782. ; AH Last Valid Separator
  1783. ;
  1784. scan_filechar:
  1785. push di ; Save DI  ES points at this segment
  1786. mov ah,0 ; Invalidate Separator Character
  1787. scan_f10:
  1788. mov al,[si] ; Get the Character to Test
  1789. cmp al,CR
  1790. jz scan_f20 ; Have we reached the end of the string
  1791. mov cx,legal_length ; Scan the table of legal 
  1792. mov di,dataOFFSET legal_table ; separators
  1793. repnz scasb ; Scan the List
  1794. jnz scan_f20 ; Non Separator Located
  1795. mov ah,al ; Save the Separator and increment
  1796. inc si ; the character pointer
  1797. jmp SHORT scan_f10
  1798. scan_f20:
  1799. pop di
  1800. ret
  1801. _TEXT ENDS
  1802. legal_table db ':.;,=+',9,' /<>|',22h,'[]'
  1803. legal_length equ 15
  1804. assume cs:DGROUP, ds:DGROUP, es:nothing, ss:nothing
  1805. public msdos_exec ; so it shows in map file
  1806. msdos_exec PROC FAR
  1807. push ax
  1808. cmp high_code,TRUE ; Check if the Command Processor Code
  1809. jnz msdos_e10 ; has been relocated to high memory
  1810. call free_com_memory ; free cmd processor memory
  1811. msdos_e10:
  1812. pop ax
  1813. mov bx,dataOFFSET exec_block
  1814. mov dx,04[bp] ; Get the Full Command Name
  1815. mov exec_ss,ss ; Save SS:SP in case somebody (NOVELL)
  1816. mov exec_sp,sp ; corrupts them
  1817. ; The following 2 JMPF are kludged so that the INT22 vector saved in
  1818. ; the child's PSP has the segment of the comand processors PSP.
  1819. ; This is vital for many TSR management utilities.
  1820. ;
  1821. ; swap stack to conventional memory
  1822. cli ;
  1823. mov ax,__psp ;
  1824. mov ss,ax ;
  1825. mov sp,0100h ;
  1826. sti ;
  1827. db 0EAh ; JMPF Opcode
  1828. dw dataOFFSET psp_dofunc4b ; Corrected Offset
  1829. exec_psp dw 0 ; PSP Segment
  1830. assume cs:DGROUP, ds:nothing, es:nothing, ss:nothing
  1831. func4b_return:
  1832. mov ss,exec_ss ; Restore the real SS:SP
  1833. mov sp,exec_sp ; Using a CS overide 
  1834.  jc msdos_e20 ; if no error
  1835. xor ax,ax ; then zero return code
  1836. jmp msdos_e21
  1837. msdos_e20:
  1838. mov ah,59h ; get extended error code
  1839. sub bx,bx
  1840. int 21h
  1841. msdos_e21:
  1842. mov return_code,ax
  1843. call get_ds ; Point DS & ES to CSdata
  1844. mov ds,ax
  1845. mov es,ax
  1846. assume cs:DGROUP, ds:DGROUP, es:nothing, ss:nothing
  1847. call handler_init ; Re-initialise Control-Break and
  1848. ; Critical error handlers for Novell
  1849. cmp high_code,TRUE ; Is the Command Code in High
  1850.  jnz msdos_e30 ; memory ?
  1851. mov reload_flag,1 ; Reloading Command Processor
  1852. call reload_code ; Reload Command Processor Code
  1853. mov reload_flag,0 ; Command Processor Loaded
  1854. msdos_e30:
  1855. mov ax,code_seg ; Update the CS for the high code
  1856. mov  msdos_exec_ret_seg,ax ; in case it has moved and return
  1857. jmp msdos_exec_ret
  1858. msdos_exec ENDP
  1859. _TEXT SEGMENT
  1860. assume cs:CGROUP, ds:DGROUP, es:nothing, ss:nothing
  1861. Public _readline
  1862. _readline:
  1863. ;---------
  1864. cld
  1865. push bp
  1866. mov bp,sp
  1867. push si
  1868. push di
  1869. push es
  1870. ifdef DOSPLUS
  1871. mov ax,4456h ; Swap to the Command process
  1872. mov dl,1 ; History Buffer in DR DOS
  1873. int DOS_INT
  1874. else
  1875. push ds
  1876. call get_history_buffers ; get history buffers
  1877. mov P_SB_SEG[bx],ax ; swap to command one
  1878. pop ds
  1879. endif
  1880. mov ax,5d09h
  1881. int DOS_INT ; close remote spool files
  1882. mov ax,5d08h
  1883. mov dl,1
  1884. int DOS_INT ; Set truncate flag with redirected I/O
  1885. mov ah,MS_P_GETPSP ; get the current PSP
  1886. int DOS_INT ;  then compare the STDERR entry in the
  1887. mov es,bx ;  XFT with the Magic Number for CON
  1888. cmp es:byte ptr [18h+STDERR],1
  1889. mov dx,4[bp] ; get the buffer address and current
  1890. mov ax,cs ; AX = transient code segment
  1891. call readline ; do far call to msdos_readline
  1892. ifdef DOSPLUS
  1893. mov ax,4456h ; Swap to the Application process
  1894. mov dl,0 ; History Buffer in DR DOS
  1895. int DOS_INT
  1896. else
  1897. push ds
  1898. call get_history_buffers ; get history buffers
  1899. mov P_SB_SEG[bx],dx ; swap to application one
  1900. pop ds
  1901. endif
  1902. pop es
  1903. pop di
  1904. pop si
  1905. pop bp
  1906. ret
  1907. ifdef CDOS
  1908. get_history_buffers proc near
  1909. ; On Entry:
  1910. ; None
  1911. ; On Exit:
  1912. ; AX = command history buffers
  1913. ; DX = application history buffers
  1914. ; DS:BX -> pd
  1915. ; NB. both DS and ES are corrupted by this call
  1916. ;
  1917. mov ds,_sysdat_seg ; DS points to SYSDAT and ES to the
  1918. mov bx,ds:word ptr [68h] ; current process's UDA
  1919. mov dl,P_CNS[bx] ; DL = console number
  1920. mov es,P_UDA[bx]
  1921. push bx
  1922. mov ax,XIOS_HISTBUF ; Get the History Buffer Address's
  1923. call XIOS_ENTRY ;  by calling ths XIOS
  1924. pop bx
  1925. ret
  1926. get_history_buffers endp
  1927. endif
  1928. _TEXT ENDS
  1929. assume cs:DGROUP, ds:DGROUP, es:nothing
  1930. ;
  1931. ; msdos_readline(BYTE *buffer);
  1932. ;
  1933. ; On Entry:
  1934. ; flags - ZF set if we need to do Sidekick Plus check
  1935. ; DS:DX -> buffer
  1936. ; AX:0  -> Resident Section
  1937. ; buffer
  1938. ;
  1939. ; The memory allocation for the hi-mem part of command.com has already been
  1940. ; altered to minimise the chances of SideKick Plus overwriting the code.
  1941. ; But it still can happen, say either on a machine with limited memory or
  1942. ; other TSR's also loaded. In order to cater for this case we move the actual
  1943. ; readline call into the resident portion and checksum things before returning
  1944. ; to high memory - thus we can reload command.com if it get overwritten.
  1945. ;
  1946. msdos_readline PROC FAR
  1947. pushf ; save the result for later
  1948. mov bx,sp ; SP before swapping stacks.
  1949. cli ; to RLSTACK
  1950. mov ss,ax ; above the Code and Messages
  1951. mov sp,codeOFFSET rlstack
  1952. sti
  1953. push bx ; save old SP
  1954. push ds
  1955. sub sp,260 ; make room for buffer on stack
  1956. mov di,sp ; save the address
  1957. push ds
  1958. push dx ; save real BUFFER for later...
  1959. push di ;  and buffer on stack
  1960. mov si,dx ; point DS:SI at real buffer
  1961. mov dx,di ; point DX at stack buffer
  1962. push ss ; now get all the seg regs
  1963. pop es ; pointing to himem
  1964. mov cx,256/2
  1965. rep movsw ; copy resident buffer to stack
  1966. push ss ; DS:DX is stack buffer
  1967. pop ds
  1968. mov ax,4810h ; give DOSKEY a chance
  1969. int 2Fh
  1970. or ax,ax ; zero means DOSKEY has done it
  1971.  jz msdos_rl10
  1972. mov word ptr [di],21cdh ; poke INT 21 and
  1973. mov byte ptr 2[di],0cbh ;  RETF instruction
  1974. push cs ; save an address for the
  1975. mov ax,dataOFFSET msdos_rl10;  RETF to return to
  1976. push ax
  1977. mov ah, MS_C_READSTR ; parameter for INT 21 readline
  1978. push ds ; finally jump to the INT 21
  1979. push di ;  we have poked
  1980.     ret             
  1981. msdos_rl10:
  1982. pop si ; source is readline buffer
  1983. pop di ; recover old address
  1984. pop es ;  and seg of real buffer
  1985. mov cl,ds:byte ptr [si] ; get MAX length
  1986. xor ch,ch ; make it a word
  1987. cld
  1988. rep movsb ; copy the string
  1989. add sp,260 ; recover my readline buffer space
  1990. pop ds
  1991. pop bx ; recover old SP
  1992. cli ; Now restore the normal C stack
  1993. call get_ds ; which is at DS:BX.
  1994. mov ss,ax
  1995. mov sp,bx
  1996. mov es,ax
  1997. sti
  1998. popf ; recover result of STDERR test
  1999.  jne msdos_r10 ; if not CON, then skip the check
  2000. cmp high_code,TRUE ; Is the Command Code in High
  2001.  jnz msdos_r10 ; memory ?
  2002. mov reload_flag,1 ; Reloading Command Processor
  2003. call reload_code ; Reload Command Processor Code
  2004. mov reload_flag,0 ; Command Processor Loaded
  2005. msdos_r10:
  2006. mov ax,code_seg ; Update the CS for the high code
  2007. mov  word ptr -08[bp],ax ; in case it has moved and return
  2008. ret
  2009. msdos_readline ENDP
  2010. ; Cmd processor is in high memory so check it out
  2011. reload_code:
  2012. cmp in_exec,1 ; If we landed here from an undefined area
  2013. je alloc_mem ; then free cmd processor memory
  2014. call free_com_memory
  2015. alloc_mem:
  2016. call alloc_com_memory ; Allocate memory for the Command
  2017.  jc alloc_mem_error ; processor code.
  2018. push ax
  2019. call check_crc ; see if code has been trashed
  2020. pop ax
  2021. je still_there
  2022. mov code_seg,ax
  2023. jmp load_com ; Read in command Processor Code
  2024. still_there:
  2025. cmp ax,code_seg ; has the memory configuration changed?
  2026. je hasnt_moved ; (it will during Novell remote boot)
  2027. push ds
  2028. push es
  2029. mov cx,real_code
  2030. mov es,ax ; move the code to the new location
  2031. mov ds,code_seg ;
  2032. sub si,si ; ds:si -> old location
  2033. sub di,di ; es:di -> new location
  2034. rep movsb ; do it
  2035. mov cs:code_seg,es ; update code_seg with new location
  2036. pop es
  2037. pop ds
  2038. call check_crc ; recalculate the crc
  2039. jne load_com ; if its not valid we need to load
  2040. ; from disk
  2041. hasnt_moved:
  2042. ret
  2043. alloc_mem_error:
  2044. ; We can't reload COMMAND.COM because we haven't any memory
  2045. ifdef DLS
  2046. mov dx,_reload_msgm
  2047. else
  2048. mov dx,dataOFFSET _reload_msgm
  2049. endif
  2050. call reload_err ; say we can't reload COMMAND.COM
  2051. jmp $ ; stop forever....
  2052. check_crc:
  2053. ; return with ZF set if himem crc's correctly
  2054. push ds
  2055. mov ds,code_seg
  2056. mov si,2
  2057. call calc_crc
  2058. pop ds ; Compare this crc with the one we got earlier
  2059. cmp crc,ax
  2060. ret
  2061. ; If checksum is wrong load a new copy into high memory and patch new RET addr
  2062. open_err:
  2063. ifdef DLS
  2064. mov dx,_reload_msgf
  2065. else
  2066. mov dx,dataOFFSET _reload_msgf
  2067. endif
  2068. call reload_err ; prompt for COMMAND.COM
  2069. mov ah,MS_C_RAWIN ; Wait for the User to Press
  2070. int DOS_INT ; a key
  2071. load_com:
  2072. push ds
  2073. mov ds,[low_seg]
  2074. mov dx,dataOFFSET reload_file
  2075. mov ax,(MS_X_OPEN*256)+40h ; Try to open COMMAND.COM
  2076. int DOS_INT ; al=40h means NONE DENIED share mode
  2077. pop ds
  2078.  jc open_err
  2079. mov bx,ax
  2080. xor dx,dx ; Take account of EXE header
  2081. cmp exe_file,FALSE ; if we were loaded as an EXE
  2082. je load_com_10
  2083. add dx,200h ; Assume header is 200h bytes
  2084. load_com_10:
  2085. xor cx,cx ; Now read the command processor code
  2086. add dx,total_length ; Seek to area of COMMAND.COM
  2087. mov ax,(MS_X_LSEEK*256)+0 ; containing code
  2088. int DOS_INT
  2089.  jc read_err
  2090. push ds
  2091. mov cx,real_code
  2092. mov ds,code_seg ; DS:DX - > High memory area
  2093. xor dx,dx
  2094. mov ah,MS_X_READ ; Read the code into memory
  2095. int DOS_INT
  2096. pop ds
  2097. read_err:
  2098. mov ah,MS_X_CLOSE ; Close the file
  2099. int DOS_INT
  2100. call check_crc ; try and see if we loaded OK
  2101.  jne open_err ; if not complain and try again
  2102. ret
  2103. reload_err:
  2104. ; On Entry:
  2105. ; DX = offset of final part of error message
  2106. ;
  2107. push dx ; save final part of message
  2108. mov bx,STDERR ; Display on standard Error
  2109. ifdef DLS
  2110. mov dx,_reload_msgs
  2111. else
  2112. mov dx,dataOFFSET _reload_msgs
  2113. endif
  2114. call reload_err10
  2115. push ds
  2116. mov ds,[low_seg]
  2117. mov dx,dataOFFSET reload_file ; Filename
  2118. call reload_err10
  2119. pop ds
  2120. pop dx ; recover msg offset
  2121. ;
  2122. ; Calculate the length of the message to be displayed and output using
  2123. ; MS_X_WRITE.
  2124. ;
  2125. ; DS:DX String to Output
  2126. ; BX Output Handle
  2127. ;
  2128. reload_err10:
  2129. xor al,al ; String Terminator
  2130. push es
  2131. push ds ; look for terminating BYTE
  2132. pop es ;  in string at DS:DX
  2133. mov di,dx ;  and get length to display
  2134. mov cx,0ffffh
  2135. repnz scasb ; look for terminator
  2136. not cx ; see how far we had to look
  2137. dec cx ; forget about the terminator
  2138. mov ah,MS_X_WRITE
  2139. int DOS_INT
  2140. pop es
  2141. ret
  2142. ED_TEXT ENDS
  2143. endif
  2144. page
  2145. _TEXT SEGMENT
  2146. assume cs:CGROUP, ds:DGROUP, ss:DGROUP
  2147. ifdef CDOSTMP
  2148. RSP_start:
  2149. mov ax,ds
  2150. mov es,ax
  2151. cli ; Swap stacks with interrupts disabled
  2152. mov ss,ax ; just in case we're on an 8088/86
  2153. mov sp,dataOFFSET stack_top
  2154. sti
  2155. mov insys,0 ; Reset the INSYS Flag
  2156. mov _gp_far_buff,dataOFFSET temp_buffer
  2157. mov _gp_far_buff+2,ax ; save address of temp buffer
  2158. mov dl,defconsole ; Set this process's Default Console
  2159. bdos C_SET
  2160. bdos C_ATTACH
  2161. bdos P_PDADR ; Get the address of the current
  2162. mov sysdat,es ; PD and SYSDAT
  2163. mov dl,BOOTDRV ; Get the BOOT Drive
  2164. mov es:P_DSK[bx],dl ; Update the running process
  2165. mov bx,dataOFFSET pd_seg ; Update the default drive field
  2166. mov P_DSK[bx],dl ; In the P_CREATE process descriptor
  2167. mov bx,es:INT17_PTR ; Initialise the default printer
  2168. mov al,defconsole ; from the INT17 Mapping Array
  2169. mul es:byte ptr [bx]
  2170. add bx,ax
  2171. mov dl,es:1[bx]
  2172. bdos L_SET
  2173. mov bx,es:INT14_PTR ; Initialise the default printer
  2174. mov al,defconsole ; from the INT14 Mapping Array
  2175. mul es:byte ptr [bx]
  2176. add bx,ax
  2177. mov dl,es:1[bx]
  2178. bdos A_SET
  2179. mov [code_seg],cs ; Update the CODE_SEG and EXEC_SEG
  2180. mov [exec_seg],ds ;     variables
  2181. mov dl,0FFh ; Set the BDOS Error Mode to Return
  2182. bdos F_ERRMODE ; with No Display
  2183. mov dx,ds ; Initialise the DMA Segment
  2184. bdos F_DMASEG ; Pointer to Our DS
  2185. bdos P_PDADR ; Set ES:BX to the Process Descriptor
  2186. mov word ptr _pd,bx ; Save these values locally
  2187. mov word ptr _pd+2,es
  2188. mov _sysdat_seg,es
  2189. or es:P_CONMODE[bx],PCM_FCTLC
  2190. mov es:P_PARENT[bx],0 ; Zero the Parent Pointer
  2191. mov ax,es:P_UDA[bx] ; Finally get our UDA and save it. 
  2192. mov uda,ax
  2193. mov ax,es:P_PSP[bx]
  2194. mov [__psp],ax
  2195. mov ax,XIOS_HISTBUF ; Get the History Buffer Address's
  2196. mov dl,defconsole ; for console number
  2197. call xios
  2198. mov cmd_histbuf,ax ; AX == Command Level History Buffer
  2199. mov prog_histbuf,dx ; DX == Program History Buffer
  2200. les bx,_pd ; Get the Process descriptor address
  2201. mov es:P_SB_SEG[bx],ax ; and use the Command Line 
  2202. ; History Buffer
  2203. ; File Ownership stuff
  2204. les bx,_pd ; Get our process descriptor address
  2205. mov al,es:P_CNS[bx] ; get the current VC No.
  2206. xor ah,ah
  2207. mov bx,CCBLIST ; XIOS CCB$LIST
  2208. add bx,ax
  2209. add bx,ax
  2210. mov bx,es:word ptr [bx] ; extract the correct
  2211. mov ah,CCB_PCNS[bx] ; Physical Console Number.
  2212. mov ch,0
  2213. mov cl,NVCNS ; now work through all consoles
  2214. mov bx,CCBLIST ; looking for 1st one with this PC
  2215. RSP_start10:
  2216. mov di,es:word ptr [bx] ; Get the CCB address
  2217. cmp ah,CCB_PCNS[di] ; Is this the same physical console
  2218.  je RSP_start20 ; no, ignore this one
  2219. add bx,2 ; onto next CCB
  2220. loop RSP_start10
  2221. jmp RSP_start60 ; impossible....
  2222. RSP_start20:
  2223. cmp al,CCB_VCNS[di] ; is it the same virtual console ?
  2224.  je RSP_start40 ;  yes, allocate new FA_ structure
  2225. RSP_start30:
  2226. push di
  2227. mov dx,5
  2228. bdos P_DELAY ; wait a bit
  2229. pop di ; then see if it has been allocated
  2230. mov si,CCB_OWNER[di] ; si -> owning process
  2231. mov si,es:P_FILE_ACCESS[si] ; File Access structure
  2232. test es:FA_FLAGS[si],FAF_TMP_INIT ; is it the new one ?
  2233.  jz RSP_start30 ; no, delay again
  2234. inc es:FA_COUNT[si] ; one more user for this structure
  2235. les bx,_pd
  2236. xchg si,es:P_FILE_ACCESS[bx] ; replace existing one
  2237. dec es:FA_COUNT[si] ; one less user for old one
  2238. jmp RSP_start60
  2239. RSP_start40:
  2240. push ax ; save PC/VC
  2241. cmp ah,0 ; is it the main box ?
  2242.  je RSP_start45
  2243. mov dx,5*50 ; delay PC Terminals 5 secs while
  2244. bdos P_DELAY ;  main box starts up
  2245. RSP_start45:
  2246. mov DX,FA_LENGTH ; we need this much SYSDAT memory
  2247. bdos S_MEMORY ;  for our file access structure
  2248. pop dx ; recover PC/VC
  2249. cmp ax,0FFFFh ; if no memory
  2250.  je RSP_start50 ;  then just keep root one
  2251. les di,_pd ; replace file access structure
  2252. xchg ax,es:P_FILE_ACCESS[di]
  2253. xchg ax,di
  2254. dec es:FA_COUNT[di] ; we have stopped using this structure
  2255. mov es:FA_USER[bx],0 ; user # is super user
  2256. mov es:FA_GROUP[bx],0 ; and group is super group
  2257. mov es:FA_DEF_ACCESS[bx],0 ; initialise the new structure
  2258. mov es:FA_COUNT[bx],1
  2259. RSP_start50:
  2260. les bx,_pd
  2261. mov bx,es:P_FILE_ACCESS[bx]
  2262. mov es:FA_FLAGS[bx],FAF_TMP_INIT
  2263. RSP_start60:
  2264. ; File Ownership stuff ends
  2265. push ds
  2266. mov es,sysdat ; Get SYSDAT
  2267. mov dx,VERSION ; get OS label offset in SUP segment
  2268. mov ds,CCPMSEG ; get SUP segment for signon string
  2269. bdos C_WRITESTR ; print OS label on current console
  2270. pop ds
  2271. endif
  2272. ;
  2273. ;
  2274. assume cs:CGROUP, ds:DGROUP, es:DGROUP
  2275. ;
  2276. ; zero data areas (_BSS and c_common)
  2277. ;
  2278. memory_init:
  2279. push ss
  2280. pop es
  2281. cld ; set direction flag (up)
  2282. mov di,dataOFFSET _edata ; beginning of bss area
  2283. mov cx,dataOFFSET _end ; end of bss area
  2284. sub cx,di
  2285. xor ax,ax
  2286. rep stosb ; zero bss
  2287. ; C segmentation conventions set up here (DS=SS and CLD)
  2288. push ss ; set up initial DS=ES=SS, CLD
  2289. pop ds
  2290. assume ds:DGROUP
  2291. ; do necessary initialization BEFORE command line processing !
  2292. ifndef CDOSTMP
  2293. push es
  2294. mov ax,4458h ; We now have an IOCTL function
  2295. int 21h ;  to get our private data
  2296.      jc mem_init10  
  2297. ifdef DOSPLUS       
  2298. ;les ax,DRDOS_PD
  2299. ;les ax,es:dword ptr 0000h[bx]
  2300. ;mov word ptr _pd,ax
  2301. ;mov word ptr _pd+2,es
  2302. ;mov _sysdat_seg,es
  2303. else
  2304. mov es:byte ptr [bx],-1 ; say COMSPEC is loaded
  2305. mov cl,P_PDADR ; Set ES:BX to the Process Descriptor
  2306. mov ax,4459h ; use Int 21h so we don't crash if
  2307. int 21h ;  under DOS and we will give an error
  2308. mov word ptr _pd,bx ;  from COM.C init().
  2309. mov word ptr _pd+2,es ; Save these values locally
  2310. mov _sysdat_seg,es
  2311. endif
  2312. mem_init10:
  2313. pop es
  2314. endif
  2315. xor bp,bp ; mark top stack frame for SYMDEB
  2316. ifdef CDOSTMP
  2317. mov ax,dataOFFSET cmdline ; Pass a pointer to a NULL string
  2318. else
  2319. call get_cmdline ; Copy the command line to a local
  2320. endif
  2321. push ax ; buffer and pass the address to MAIN
  2322. call C_code_entry ; main ( cmd )
  2323. add sp,2 ; Restore the Stack
  2324. mov ah,MS_X_EXIT ; use whatever is in ax after 
  2325. int DOS_INT ; returning here from main
  2326. page
  2327. ;
  2328. ; For TURBOC and METAWARE C the majority of the Command Processor
  2329. ; messages are linked with the CGROUP in the MSG segment. When the
  2330. ; compiler generates DGROUP relative references large offsets are
  2331. ; produced. This occurs because the DGROUP is linked before the CGROUP
  2332. ; and its MSG Segment. FARPTR converts a NEAR pointer into a FAR
  2333. ; by checking the value of the offset against the DGROUP length.
  2334. ; Offset greater than TOTAL_LENGTH must be in MSG so the pointer
  2335. ; is converted to CS:x-TOTAL_LENGTH otherwise DS:x.
  2336. ;
  2337. public _farptr
  2338. _farptr:
  2339. push bp
  2340. mov bp,sp
  2341. mov ax,04[bp]
  2342. mov dx,ds
  2343. cmp ax,total_length
  2344. jbe farptr_10
  2345. ifndef WATCOMC
  2346. sub ax,total_length
  2347. endif
  2348. mov dx,cs
  2349. farptr_10:
  2350. mov bx,dx
  2351. pop bp
  2352. ret
  2353. ifdef DLS
  2354. public _msgfarptr
  2355. _msgfarptr:
  2356. push bp
  2357. mov bp,sp
  2358. mov ax,04[bp]
  2359. add ax,offset CGROUP:_MSG
  2360. mov dx,cs
  2361. mov bx,dx
  2362. pop bp
  2363. ret
  2364. endif
  2365. ; We need some additional support for the CMD_LIST - it contains near pointers
  2366. ; to other items in the CGROUP. This routine turns a NEAR pointer into a FAR
  2367. ; pointer.
  2368. public _cgroupptr
  2369. _cgroupptr:
  2370. push bp
  2371. mov bp,sp
  2372. mov ax,04[bp]
  2373. mov dx,cs
  2374. mov bx,dx
  2375. pop bp
  2376. ret
  2377. ifdef DLS
  2378. ;/* Get the address of the msg_language variable in the DR BDOS. */
  2379. ;GLOBAL BYTE FAR * CDECL get_msg_lang()
  2380. public _get_msg_lang
  2381. _get_msg_lang:
  2382. mov ax, 4458h ; IOCTL func: get ptr private data
  2383. int 21h ; pointer returned in ES:BX
  2384.  jc _get_msg_lang_err ; skip if invalid function
  2385. add bx, 9 ; DLS version byte at offset 9
  2386. cmp es:byte ptr [bx], 1 ; correct version?
  2387.  jne _get_msg_lang_err ;  no - skip
  2388. inc bx ; DLS language byte at offset 10
  2389. mov ax,bx
  2390. mov dx,es ; return pointer in DX:AX
  2391. ret
  2392. _get_msg_lang_err:
  2393. mov ax,codeOFFSET dummy_lang
  2394. mov dx,cs
  2395. ret
  2396. dummy_lang db 0 ; default to primary language
  2397. endif
  2398. page
  2399. ifndef CDOSTMP
  2400. ;
  2401. ; This following routine copies the initial command line from the PSP
  2402. ; into the CMDLINE data area. Processing any special switches and
  2403. ; adding a terminating null character. The offset of the copy is
  2404. ; returned in AX.
  2405. ;
  2406. get_cmdline:
  2407. if 0
  2408. mov di,dataOFFSET cmdline
  2409. else
  2410. mov di,heap_top ; copy cmdline onto the heap
  2411. endif
  2412. push ds ; Preserve DS and point to PSP
  2413. mov ds,__psp ; Get the PSP address
  2414. xor cx,cx ; Now copy the command line
  2415. mov cl,ds:0080h ; Get the Command length
  2416. mov si,0081h ; and its start location
  2417.  jcxz get_cmdl20
  2418. get_cmdl10:
  2419. lodsb ; Terminate the copy after
  2420. cmp al,0Dh ; CX bytes or earlier if a
  2421. jz get_cmdl20 ; CR or LF character is found.
  2422. cmp al,0Ah ; FrameWork Install Program and
  2423. jz get_cmdl20 ; Bitstream FontWare
  2424. stosb
  2425. loop get_cmdl10
  2426. get_cmdl20:
  2427. xor al,al ; Zero Terminate the command
  2428. stosb ; line copy for C.
  2429. pop ds
  2430. if 0
  2431. mov ax,dataOFFSET cmdline ; Return the command line 
  2432. else
  2433. mov ax,di ; new bottom of heap
  2434. xchg ax,heap_top ; return old one = cmdline
  2435. endif
  2436. ret
  2437. ;
  2438. ; This routine will install the DS relative dummy INT 2E handler with
  2439. ; a PSP:XXXX entry in the interrupt vector table. A JMPF is coded
  2440. ; after the handler entry point inorder to correct CS.
  2441. ;
  2442. Public _install_perm
  2443. _install_perm:
  2444. push es
  2445. mov ax,__psp ; Modify the INT 22 and 2E
  2446. mov es,ax ; vectors if the current process
  2447. cmp ax,PSP_PARENT ; is the ROOT DOS process. ie
  2448. jnz inst_p10 ; PSP_PARENT == PSP
  2449. mov al,2Eh ; Install the Command Processor
  2450. mov dx,dataOFFSET int2E_entry ; Backdoor entry
  2451. call inst_p30
  2452. mov al,22h ; Update the Command Processor
  2453. mov dx,dataOFFSET int22_entry ; Terminate address
  2454. call inst_p30
  2455. push ds ; When this is the ROOT process
  2456. push si ; then update the PSP copies of
  2457. push di ; interrupt vectors 22, 23, 24
  2458. push ds ; because some TSR management
  2459. pop es ; programs examine these variables
  2460. lea di,psp_save_area ; ES:DI -> save area for PSP
  2461. mov ds,__psp
  2462. lea si,PSP_TERM_IP ; DS:SI -> data in PSP to save
  2463. mov cx,6
  2464. rep movsw ; save the data for later EXIT
  2465. push ds
  2466. pop es
  2467. lea di,PSP_TERM_IP ; ES:DI -> PSP
  2468. mov ds,cx
  2469. mov si,022h * 4 ; DS:SI -> real interrupt vecs
  2470. mov cx,6
  2471. rep movsw
  2472. pop di
  2473. pop si
  2474. pop ds
  2475. inst_p10:
  2476. pop es
  2477. ret
  2478. inst_p30:
  2479. push ds
  2480. mov bx,[low_seg]
  2481. sub bx,__psp ; Calculate the correct offset for
  2482. mov cl,4 ; the interrupt handler if the segment
  2483. shl bx,cl ; must be that of our PSP
  2484. add dx,bx
  2485. mov ds,__psp
  2486. mov ah,MS_S_SETINT
  2487. int DOS_INT
  2488. pop ds
  2489. ret
  2490. page
  2491. ;
  2492. ; This routine will restore the Int 22 terminate address copy in
  2493. ; the PSP in preperation for an EXIT (DeskView bug).
  2494. ;
  2495. Public _restore_term_addr
  2496. _restore_term_addr:
  2497. push es
  2498. mov ax,__psp ; Restore the PSP we altered
  2499. mov es,ax ; if the current process
  2500. cmp ax,PSP_PARENT ; is the ROOT DOS process. ie
  2501.  jne restore_ta10 ; PSP_PARENT == PSP
  2502. push si
  2503. push di
  2504. lea si,psp_save_area
  2505. lea di,PSP_TERM_IP
  2506. mov cx,6
  2507. rep movsw
  2508. pop di
  2509. pop si
  2510. restore_ta10:
  2511. pop es
  2512. ret
  2513. page
  2514. ;
  2515. ; This routine will restore the Novell error mode - BAP
  2516. ;
  2517. Public _restore_error_mode
  2518. _restore_error_mode:
  2519. mov dl,net_error_mode
  2520. mov ah,0ddh ; set error mode to the value
  2521. int 21h ; it was when COMMAND was
  2522. ret ; executed
  2523. page
  2524. ;
  2525. ; MASTER_ENV will create a Master Environment of 04[bp] bytes unless
  2526. ; the environment is already larger in which case the environment
  2527. ; is increased by 128 bytes.
  2528. ;
  2529. Public _master_env
  2530. _master_env:
  2531. push bp
  2532. mov bp,sp
  2533. push si
  2534. push di
  2535. push es
  2536. ifdef DOSPLUS
  2537. ; mov ax,(MS_M_STRATEGY*256)+1
  2538. ; mov bx,1 ; set memory strategy to best fit
  2539. ; int DOS_INT
  2540. endif
  2541. mov bx,04[bp] ; Save the Specified Size
  2542. add bx,15 ; and force it to be an integer 
  2543. and bx,not 15 ; multiple of 16
  2544. mov es,__psp ; Get the PSP Segment Address
  2545. mov cx,PSP_ENVIRON ; Get the environment segemnt
  2546. jcxz master_env10 ; Have we been loaded by DesQview ?
  2547. mov es,cx ; Scan through the environment and
  2548. xor di,di ; determine the Environment size and
  2549. xor ax,ax ; the Load file name
  2550. mov cx,7FFFh
  2551. master_env05:
  2552. repne scasb ; Scan for a ZERO byte
  2553. jcxz master_env10 ; Abort if maximum size exceeded
  2554. inc di ; Check if the next character was a 0
  2555. cmp al,es:-1[di] ; if YES then this is the end of the
  2556. jnz master_env05 ; environment
  2557. mov cx,di ; Calculate the environment Size
  2558. ;
  2559. ; CX contains the current environment size in bytes. 0 for a DesQview
  2560. ; system or an empty environment.
  2561. ;
  2562. master_env10:
  2563. cmp bx,cx ; Is the current environment larger
  2564. jae master_env15 ; No allocate requested value
  2565. mov bx,128
  2566. add bx,cx
  2567. master_env15:
  2568. push cx ; Save current Environment Size
  2569. mov cl,4 ; convert request to paragraphs
  2570. shr bx,cl
  2571. mov ah,MS_M_ALLOC ; Allocate Memory
  2572. int DOS_INT
  2573. pop cx
  2574. jc master_env30 ; Abort Memory Allocation Failed
  2575. mov es,__psp ; Copy the Environemt
  2576. xchg ax,PSP_ENVIRON ; Update the Environment Pointer
  2577. push ds
  2578. mov ds,ax ; DS -> Initial Environment
  2579. mov es,PSP_ENVIRON ; ES -> Master Environment
  2580. mov si,0
  2581. mov di,si
  2582. jcxz master_env20 ; If this was a Desqview exec then
  2583. rep movsb ; skip the environment copy and
  2584. ; just initialize to 0000
  2585. if TRUE ; Invalidate the contents of the
  2586. not ds:word ptr 00h ; current environment so Novell
  2587. else ; Netware finds the correct Master
  2588. push es ; environment under Concurrent DOS.
  2589. mov es,ax ;
  2590. mov ah,MS_M_FREE ; A possible alternative is to free
  2591. int DOS_INT ; the old environment but this would
  2592. pop es ; change the memory allocations for
  2593. endif ; sub-sequent loads.
  2594. master_env20:
  2595. pop ds
  2596. xor ax,ax
  2597. stosw
  2598. master_env30:
  2599. ifdef DOSPLUS
  2600. ; mov ax,(MS_M_STRATEGY*256)+1
  2601. ; xor bx,bx ; set memory strategy to first fit
  2602. ; int DOS_INT
  2603. endif
  2604. pop es
  2605. pop di
  2606. pop si
  2607. pop bp
  2608. ret
  2609. endif
  2610. page
  2611. ifndef DOSPLUS
  2612. ;
  2613. ; UWORD FAR *sysdat(WORD *);
  2614. ;
  2615. Public _sysdat
  2616. _sysdat:
  2617. push bp
  2618. mov bp,sp
  2619. push es
  2620. BDOS S_SYSDAT ; Get the SYSDAT segment address
  2621. mov ax,word ptr 04[bp] ; and the SYSDAT byte offset
  2622. mov bx,es ; and return a FAR pointer to the
  2623. mov dx,bx ; data required. MSC uses DX:AX
  2624. pop es ; but cater for other compilers 
  2625. pop bp ; just in case.
  2626. ret
  2627. endif
  2628. ifdef DOSPLUS
  2629. ;
  2630. ; BOOLEAN CDECL int10_cls();
  2631. ;
  2632. ; int10_cls will return TRUE if it issued an INT10 function to
  2633. ; clear the screen.
  2634. ;
  2635. Public _int10_cls
  2636. _int10_cls:
  2637. push bp
  2638. push si
  2639. push di
  2640. push es
  2641. mov ax,(MS_X_IOCTL*256)+0 ; Get the device attributes for
  2642. mov bx,STDOUT ; STDOUT
  2643. int DOS_INT
  2644. mov ax,0000 ; Assume that the test fails
  2645.  jc int10_exit ; and return FALSE to the caller
  2646. and dl,092h ; Check that STDOUT is the Console
  2647. cmp dl,092h ; Out DEVICE and it supports INT29
  2648.  jnz int10_exit ; Fast output
  2649. ;;mov es,ax ; Now check that the INT29 routine
  2650. ;;mov bx,es:word ptr (29h*4)+2; is below the INT20 service routine
  2651. ;;cmp bx,es:word ptr (20h*4)+2; ie that this is a BIOS device driver
  2652. ;; jae int10_exit ; No way Jose
  2653. ; So what if it isn't?
  2654. mov ax,1A00h ; ANSI.SYS installation check
  2655. int 2Fh ; AL = FF on return if ANSI installed
  2656. cbw ; AX = FFFF if ANSI present
  2657. inc ax ; AX = 0 if ANSI present
  2658.  jz int10_exit
  2659. ; get number of lines
  2660. call cginfo ; get screen resolution
  2661. push dx ; screen lines
  2662. mov ah, 0fh ; get mode
  2663. int 10h
  2664. and al,7fh
  2665. mov ah, 0 ; set mode, clear screen (al bit 7 clear)
  2666. int 10h
  2667. call cginfo ; has resolution changed?
  2668. pop ax ; restore screen lines
  2669. cmp al, dl ; has # of screen lines changed?
  2670.  je int10_done ; skip if still the same
  2671. mov ax, 1112h ; character generator
  2672. mov bl, 0 ; set 8x8 double dot font
  2673. int 10h
  2674. mov ax, 1103h ; set block specifier
  2675. mov bl, 0
  2676. int 10h
  2677. int10_done:
  2678. mov ax,1 ; All done
  2679. int10_exit:
  2680. pop es
  2681. pop di
  2682. pop si
  2683. pop bp
  2684. ret
  2685. cginfo:
  2686. mov dl, 24 ; assume default # for CGA/MDA
  2687. mov ax, 1130h ; character generator info
  2688. mov bh, 0
  2689. int 10h
  2690. ret ; dl = nlines - 1
  2691. endif
  2692. ifdef CDOSTMP
  2693. xios:
  2694. push ds ; Save the entry segment registers
  2695. push es ; then call the XIOS correctly with 
  2696. ; DS pointing to SYSDAT and ES to the
  2697. mov es,uda ; current process's UDA
  2698. mov ds,sysdat
  2699. call XIOS_ENTRY
  2700. pop es
  2701. pop ds
  2702. ret
  2703. endif
  2704. ifndef DOSPLUS
  2705. ;
  2706. ; _vc_data(&vc_base, &vc_num, &pc_num)
  2707. ;
  2708. ; VC_DATA returns the first Virtual Console attached to the current
  2709. ; physical console, the number of virtual consoles attached and the
  2710. ; physical console.
  2711. ;
  2712. Public _vc_data
  2713. _vc_data:
  2714. push bp
  2715. mov bp,sp
  2716. push es
  2717. push si
  2718. push di
  2719. mov si,04[bp] ; SI == &VC_BASE
  2720. mov word ptr [si],0000 ; *vc_base = 0
  2721. les bx,_pd ; Get our process descriptor address
  2722. mov ah,0
  2723. mov al,NVCNS
  2724. mov cx,ax
  2725. mov al,es:P_CNS[bx] ; get the current VC No.
  2726. mov bx,CCBLIST ; XIOS CCB$LIST
  2727. mov di,ax ; Calculate the correct entry in
  2728. shl di,1 ; the CCB$LIST which points to our
  2729. mov di,es:word ptr [di+bx] ; CCB and then extract the correct
  2730. mov al,CCB_PCNS[di] ; Physical Console Number.
  2731. mov di,08[bp] ; Get the address of the PC_NUM
  2732. mov word ptr [di],ax ; and save the Physical Console Number
  2733. mov di,0000 ; From CCB 0
  2734. vc_d10:
  2735. push di
  2736. mov di,es:word ptr [di+bx] ; Get the CCB ad卹ess
  2737. cmp al,CCB_PCNS[di] ; Is this theY$ame physical console
  2738. pop di ; Restore the original DI
  2739. jz vc_d30 ; Yes then save info
  2740. vc_d20:
  2741. inc word ptr [si] ; *VC_BASE++
  2742. inc di ; Point to the next entry in
  2743. inc di ; the CCB$LIST and try again
  2744. loop vc_d10
  2745. jmp vc_exit
  2746. vc_d30:
  2747. mov si,06[bp] ; VC_NUM
  2748. mov word ptr [si],0000 ; *VC_NUM = 0
  2749. vc_d40:
  2750. push di
  2751. mov di,es:word ptr [di+bx] ; Get the CCB address
  2752. cmp al,CCB_PCNS[di] ; Is this the same physical console
  2753. pop di ; Yes then increment the count
  2754. jnz vc_exit ; and continue.
  2755. inc word ptr [si] ; *VC_NUM++
  2756. inc di ; Point to the next entry in
  2757. inc di ; the CCB$LIST and try again
  2758. loop vc_d40
  2759. vc_exit:
  2760. pop di
  2761. pop si
  2762. pop es
  2763. pop bp
  2764. ret
  2765. endif
  2766. _TEXT ENDS
  2767. page
  2768. ifdef CDOSTMP
  2769. RSF_DYNAMIC equ 0001h ; create at boot time
  2770. RSF_NONBANK equ 0002h ; allocate non-banked
  2771. RSF_SPECIAL equ 0004h ; requires separate code
  2772. RSF_ENVIRON equ 0008h ; requires large environment
  2773. PD_SEG SEGMENT
  2774. ;
  2775. ; This is the standard process descriptor for a TMP. During 
  2776. ; the Concurrent P_CREATE function the contents of this process 
  2777. ; descriptor are copied to a full size descriptor inside SYSDAT.
  2778. ;
  2779. dw 0,0 ; link fields
  2780. db PS_RUN ; status
  2781. db 200 ; priority
  2782. dw PF_SYS+PF_KEEP+PF_SPECIAL; flags
  2783. db 'Tmp     ' ; Process Name
  2784. dw 40h/10h ; uda seg
  2785. db 0,0 ; disk,user
  2786.                 db      0,0              ; ldisk,luser
  2787. dw 0FFFFh  ; mem (Shared Code)
  2788. dw 0,0 ; dvract,wait
  2789.                 db      0,0              ; org,net
  2790.                 dw      0                ; parent
  2791. cns             db      0,0              ; cns,abort
  2792.                 db      0,0              ; cin,cout
  2793.                 db      0,0              ; lst,sf3
  2794.                 db      0,0              ; sf4,sf5
  2795. dw 0,0 ; reserved
  2796.                 dw      0,0              ; pret,scratch
  2797. PD_SEG ENDS
  2798. UDA_SEG SEGMENT
  2799. uda_size dw ULEN,80h,0,0 ;0-7
  2800. dw 0,0,0,0 ;8-fh
  2801. dw 0,0,0,0 ;10-17
  2802. dw 0,0,0,0 ;18-1f
  2803. dw 0,0,0,0 ;20-27
  2804. dw 0,0,0,0 ;28-2f
  2805. dw 0,0 ;30-33
  2806. uda_SP dw dataOFFSET uda_stack,0 ;34-37
  2807. dw 0,0,0,0 ;38-3f
  2808. dw 0,0,0,0 ;40-47
  2809. dw 0,0,0,0 ;48-4f
  2810. uda_CS dw 0 ;50-51
  2811. uda_DS dw 0 ;52-53
  2812. uda_ES dw 0 ;54-55
  2813. uda_SS dw 0 ;56-57
  2814. dw 0,0,0,0 ;58-5f
  2815. insys db 1,0 ;60-61
  2816. dw 0,0,0 ;62-67
  2817. db (ULEN-6Eh)dup(0CCH) ; Initialise System Stack
  2818. uda_stack dw codeOFFSET RSP_start ; Initial Offset
  2819. dw ? ; Initial Segment (Unknown)
  2820. dw ? ; Initial Flags (Unknown)
  2821. UDA_SEG ENDS
  2822. endif
  2823. ifdef DOSPLUS
  2824. _TEXT SEGMENT
  2825. public _show_help
  2826. public _put_resident_high
  2827. public _get_config_env
  2828. public _get_original_envsize ; BAP added this
  2829. _show_help PROC NEAR
  2830. ;
  2831. ; VOID show_help(index)
  2832. ; WORD index
  2833. ;
  2834. ;out 0fdh,al
  2835. push bp
  2836. mov bp,sp
  2837. sub sp,4 ; require 2 WORD local variables
  2838. mov ah,MS_M_ALLOC ; allocate memory for the help text
  2839. mov bx,help_length ; bx = no. paragraphs
  2840. mov cl,4
  2841. shr bx,cl
  2842. int DOS_INT ; do it
  2843. jnc show_help_05
  2844. jmp show_help_err0 ; exit on error
  2845. show_help_05:
  2846. mov -2[bp],ax ; save segment of allocated memory
  2847. push ds
  2848. mov ds,[low_seg]
  2849. mov dx,dataOFFSET reload_file
  2850. mov ax,(MS_X_OPEN*256)+0 ; Open the COMMAND.COM file
  2851. int DOS_INT ; do it
  2852. pop ds
  2853. jc show_help_err1 ; exit on error
  2854. mov bx,ax ; bx = file handle
  2855. mov -4[bp],ax ; save handle for later
  2856. xor cx,cx
  2857. xor dx,dx
  2858. cmp exe_file,TRUE ; if command.com is an EXE file take
  2859. jne show_help_10 ; account of the EXE header
  2860. add dx,200h
  2861. show_help_10:
  2862. add dx,total_length
  2863. add dx,cgroup_length
  2864. add dx,cend_length ; dx = file offset of help text
  2865. mov ax,(MS_X_LSEEK*256)+0 ; seek to the right location
  2866. int DOS_INT ; do it
  2867. jc show_help_err2 ; exit on error
  2868. push ds
  2869. mov ds,-2[bp] ; ds = help text segment
  2870. xor dx,dx ; dx = 0; 
  2871. mov ah,MS_X_READ ; read from COMMAND.COM file
  2872. mov cx,help_length ; cx = no. bytes required
  2873. int DOS_INT ; do it
  2874. pop ds
  2875. jc show_help_err2 ; exit on error
  2876. cmp ax,0 ; zero bytes read means there's no
  2877. je show_help_err2 ; help seg tagged to file.
  2878. ifdef DLS
  2879. call _get_msg_lang ; get a far pointer to msg_language var
  2880. mov es,dx ; dx:ax = far pointer on return
  2881. mov bx,ax ;
  2882. mov bx,es:[bx] ; bx = msg_language
  2883. shl bx,1 ; multiply bx by 2
  2884. else
  2885. xor bx,bx ; bx = 0
  2886. endif
  2887. mov es,-2[bp] ; ds = help text segment
  2888. mov bx,es:[bx] ; bx -> help message offset table
  2889. mov ax,4[bp] ; ax = message index
  2890. shl ax,1 ; multiply by 2
  2891. add bx,ax ; bx -> offset of required message
  2892. mov bx,es:[bx] ; bx -> message
  2893. call write_string ; display the message
  2894. show_help_err2:
  2895. mov ah,MS_X_CLOSE ; close the file
  2896. mov bx,-4[bp] ; bx = file handle
  2897. int DOS_INT ; do it
  2898. show_help_err1:
  2899. mov ah,MS_M_FREE ; free the memory
  2900. push es
  2901. mov es,-2[bp] ; es = segment to free
  2902. int DOS_INT ; do it
  2903. pop es
  2904. show_help_err0:
  2905. add sp,4
  2906. pop bp
  2907. ret
  2908. write_string:
  2909. ;extrn _str:byte
  2910. ; es -> help segment
  2911. ; bx -> message in help segment
  2912. write_string_00:
  2913. ;mov di,dataOFFSET _str ; di -> local buffer
  2914. mov di,[heap_top]
  2915. write_string_05:
  2916. mov al,es:[bx] ; get a character
  2917. cmp al,0ah ; check for NEWLINE...
  2918. jnz write_string_10 ; ...jump if its not
  2919. mov al,0dh ; replace LF with CR LF
  2920. mov [di],al ; 
  2921. inc di ; 
  2922. mov al,0ah ;
  2923. mov [di],al ; 
  2924. inc di ;
  2925. mov al,0 ;
  2926. mov [di],al ; terminate string
  2927. call flush_buff ; display it
  2928. inc bx ;
  2929. jmp write_string_00 ; start again
  2930. write_string_10:
  2931. cmp al,0 ; check for NULL...
  2932. jnz write_string_20 ; ...jump if its not
  2933. mov [di],al ; store char
  2934. call flush_buff ; display string
  2935. jmp write_string_90 ; exit
  2936. write_string_20:
  2937. cmp al,'%' ; messages have doubled %'s because
  2938. jnz write_string_30 ; were intended for printf originally.
  2939. inc bx ; => skip next character.
  2940. write_string_30:
  2941. mov [di],al ; store char
  2942. inc di ;
  2943. inc bx ;
  2944. jmp write_string_05 ; loop
  2945. write_string_90:
  2946. ret
  2947. flush_buff:
  2948. extrn strlen_:near
  2949. extrn c_write_:near
  2950. ;mov ax,dataOFFSET _str ; watcom C requites first param in AX
  2951. mov ax,[heap_top]
  2952. call strlen_ ; get length of string
  2953. mov dx,ax ; watcom C requires second param in DX
  2954. ;mov ax,dataOFFSET _str ; watcom C requires first param in AX
  2955. mov ax,[heap_top]
  2956. call c_write_ ; display the string
  2957. ret
  2958. _show_help ENDP
  2959. try_high_memory PROC NEAR
  2960. ; This function attempts to allocate some high memory at FFFF:E0 by modifying
  2961. ; the HIMEM FREE CHAIN maintained by the BDOS.
  2962. ; on entry: bx = no. paras required (preserved)
  2963. ; on exit:  Carry Set = unsuccessful
  2964. ;           otherwise
  2965. ;           ax = FFFF = segment of allocated memory
  2966. ;           HIMEM Free Chain is modified.
  2967.   
  2968. push ds
  2969. push es
  2970. push bx
  2971. mov cl,4 ; multiplying bx by 4...
  2972. shl bx,cl ; ...gives memory required in bytes
  2973. mov dx,bx ; put it in dx because bx is used for
  2974. ; somthing else
  2975. add dx,HISEG_OFF
  2976. mov ax,4458h ; get private data area
  2977. int DOS_INT ; do it
  2978. mov si,es:10h[bx] ; ax = start of HIMEM Free Chain
  2979. test si,si ; zero means there's no chain so...
  2980. je thm_unsuccessful; ...return unsuccessful
  2981. mov ax,0FFFFh ;
  2982. mov ds,ax ; ds:si -> first free himem area
  2983. cmp si,HISEG_OFF ; check if area starts at or below HISEG_OFF
  2984. ja thm_unsuccessful; ...return unsuccessful
  2985. mov cx,2[si] ; CX = length of free area
  2986. cmp cx,dx ; check if length >= that required
  2987. jb thm_unsuccessful; ...return unsuccessful
  2988. mov ax,[si] ; assume we will use the entire block
  2989. mov es:10h[bx],ax ;  so unlink it from the chain
  2990. mov di,HISEG_OFF ; generate HIMEM REGISTRATION link and
  2991. mov ax,di ;  update root in private data area
  2992. xchg ax,es:14h[bx]
  2993. mov [di],ax
  2994. mov 2[di],dx ; remember how much we have used
  2995. ; JBM commented this line out, I put it back in. (BAP)
  2996. sub 2[di],di
  2997. ; see above comment (JBM)
  2998. sub cx,dx ; subtract amount used from actual size
  2999. cmp cx,256 ; if less than 256 bytes are left
  3000. jb thm_success ;  then just forget about them
  3001. mov si,di ; there is enough to be worth recyling
  3002. add si,dx ; SI -> free block following allocation
  3003. mov 2[si],cx ; it's this long
  3004. mov ax,si
  3005. xchg ax,es:10h[bx] ; put at head of HMA free chain
  3006. mov [si],ax
  3007. thm_success:
  3008. mov ax,0ffffh ; return success
  3009. clc ;
  3010. jmp thm_exit ;
  3011. thm_unsuccessful:
  3012. stc ; return failure
  3013. thm_exit:
  3014. pop bx
  3015. pop es
  3016. pop ds
  3017. ret
  3018. try_high_memory ENDP
  3019. _put_resident_high PROC NEAR
  3020. ;
  3021. ; VOID put_resident_high(param)
  3022. ; WORD param;
  3023. ;
  3024. ; param = 0 Try HIGH memory, then UPPER memory
  3025. ; param = 1 Only try HIGH memory
  3026. ; param = 2 Only try UPPER memory
  3027. ;
  3028. PRH_PARAM equ word ptr 4[bp]
  3029. push bp
  3030. mov bp,sp
  3031. push si
  3032. push di
  3033. mov ax,(MS_M_STRATEGY*256)+2
  3034. int DOS_INT ; get existing HMA link
  3035. mov ah,0
  3036. push ax ; save it
  3037. mov bx,total_length ; get size of resident code/data
  3038. sub bx,(dataOFFSET hi_seg_start)-15
  3039. mov cl,4 ; subtract size of low memory stub
  3040. shr bx,cl ; bx = block size in paras.
  3041. cmp PRH_PARAM,2 ; skip the next bit if we're only 
  3042. je prh_upper ; looking at UPPER memory
  3043. call try_high_memory ; first try to allocate high memory
  3044. ; ie seg FFFF
  3045. jnc prh_success ; jump if successful
  3046. cmp PRH_PARAM,0 ; if we're only looking at HIGH memory
  3047. jne prh_exit ; then we exit now
  3048. prh_upper:
  3049. push bx ; save length
  3050. mov ax,(MS_M_STRATEGY*256)+1
  3051. mov bx,41h ; set memory strategy to best fit
  3052. int DOS_INT ;  upper only
  3053. mov ax,(MS_M_STRATEGY*256)+3
  3054. mov bx,1 ; try to link in upper memory
  3055. int DOS_INT
  3056. pop bx ; recover length
  3057.  jc prh_exit ; no upper memory, stop now
  3058. mov ah,MS_M_ALLOC ; allocate some memory
  3059. int DOS_INT ; do it
  3060.  jc prh_exit ; no upper memory, stop now
  3061. sub ax,HISEG_OFF/16 ; bias segment appropriately
  3062. prh_success:
  3063. ; AX = segment to relocate to
  3064. ;
  3065. mov es,ax ; es = new block
  3066. mov si,dataOFFSET hi_seg_start ; start at R_TEXT segment
  3067. mov di,si
  3068. mov cx,total_length ; get size of resident code/data
  3069. sub cx,si ; subtract size of low memory stub
  3070. mov [reloc_seg],ax ; These values in the low memory
  3071. mov [reloc_off],di ; stub are used by TaskMAX to find
  3072. mov [reloc_size],cx ; the relocated code/data
  3073. mov [data_seg],ax ; update data_seg variable
  3074. mov [exec_seg],ax ; and some others...
  3075. mov [readline_seg],ax
  3076. mov [func4b_seg],ax
  3077. mov [int2E_seg],ax
  3078. mov ds:word ptr [control_break_entry+3],ax
  3079. mov ds:word ptr [crit_error_entry+3],ax
  3080. add si,4 ; take account of HIMEM
  3081. add di,4 ; REGISTRATION link
  3082. sub cx,4
  3083. rep movsb ; move'em
  3084. mov bx,ds
  3085. sub bx,[__psp] ; ax = difference between psp and data
  3086. add bx,HISEG_OFF/16 ; add size of bit we leave behind
  3087. mov es,[__psp] ; es -> old location
  3088. mov ds,ax ; this is the new data seg
  3089. mov ss,ax ; and also the new stack seg
  3090. mov ah,MS_M_SETBLOCK ; modify old segment size 
  3091. int DOS_INT ; do it
  3092. prh_exit:
  3093. pop bx ; recover upper memory link
  3094. mov ax,(MS_M_STRATEGY*256)+3
  3095. int DOS_INT ; restore to original state
  3096. mov ax,(MS_M_STRATEGY*256)+1
  3097. xor bx,bx ; set memory strategy to first fit
  3098. int DOS_INT
  3099. pop di
  3100. pop si
  3101. pop bp
  3102. ret
  3103. _put_resident_high ENDP
  3104. _get_config_env PROC NEAR
  3105. ; BYTE FAR *get_config_env();
  3106. ; This function returns a pointer to the start of the config.sys
  3107. ; environment.
  3108. mov ax,4458h ; get pointer to private data
  3109. int DOS_INT ; do it
  3110. mov ax,0 ; es:bx -> private data
  3111.  jc get_cfg_env10
  3112. xchg ax,es:18[bx] ; ax = segment of config environment
  3113. get_cfg_env10:
  3114. mov bx,ax ; return FARNULL (0000:0000)
  3115. mov dx,ax
  3116. xor ax,ax
  3117. ret
  3118. _get_config_env ENDP
  3119. ; BAP - This routine finds the orignal COMMAND.COM's environment size.
  3120. ; This may not be the best way of doing it .. !
  3121. ; It finds the PSP of the original COMMAND.COM by checking the PSP seg
  3122. ; against the parent PSP seg. If they are not the same, it repeats for
  3123. ; the parent. When they are the same, it has found the original COMMAND
  3124. ; and finds the environment size.
  3125. _get_original_envsize PROC NEAR
  3126. push bp
  3127. mov bp,sp
  3128. push si
  3129. push di
  3130. push es
  3131. push cx
  3132. mov ah,51h
  3133. int DOS_INT ; get current PSP seg
  3134. try_next:
  3135. mov es,bx
  3136. mov cx,bx ; move into CX
  3137. mov bx,0
  3138. mov ax,es:16h[bx] ; get parent PSP seg in ax
  3139. cmp ax,cx ; are they the same ?
  3140. je got_org_psp ; yes - found COMMAND.COM PSP
  3141. mov bx,ax ; else make this current seg and
  3142. jmp try_next ; try again
  3143. got_org_psp:
  3144. mov es,ax ; ES = COMMAND.COM PSP seg
  3145. mov bx,0
  3146. mov ax,es:2ch[bx] ; get env seg in ax
  3147. cmp ax,0 ; seg = 0000 ?
  3148. je bomb_out ; yes - forget it
  3149. dec ax ; AX:0000 points to memory descriptor
  3150. mov es,ax
  3151. mov ax,es:3[bx] ; find length of seg ( in paras)
  3152. mov cl,4
  3153. shl ax,cl ; convert to bytes
  3154. bomb_out:
  3155. mov bx,ax
  3156. mov dx,ax
  3157. pop cx
  3158. pop es
  3159. pop di
  3160. pop si
  3161. pop bp
  3162. ret
  3163. _get_original_envsize ENDP
  3164. _TEXT ENDS
  3165. endif
  3166. ifndef CDOSTMP
  3167. R_TEXT SEGMENT
  3168. extrn _out_pipe:byte
  3169. extrn _kbdbuf:byte
  3170. R_TEXT ENDS
  3171. _TEXT SEGMENT
  3172. public _get_reload_file
  3173. _get_reload_file:
  3174. ; copy reload_file to heap
  3175. push ds
  3176. push es
  3177. push si
  3178. push di
  3179. ;mov ax,0e40h
  3180. ;int 10h
  3181. mov ax,ds
  3182. mov es,ax
  3183. mov ds,[low_seg]
  3184. mov di,[heap_top]
  3185. mov si,offset reload_file
  3186. cld
  3187. grf_loop:
  3188. lodsb
  3189. stosb
  3190. cmp al,0
  3191. jnz grf_loop
  3192. pop di
  3193. pop si
  3194. pop es
  3195. pop ds
  3196. ret
  3197. public _set_reload_file
  3198. _set_reload_file:
  3199. ; copy string on heap to reload file
  3200. push es
  3201. push si
  3202. push di
  3203. ;mov ax,0e40h
  3204. ;int 10h
  3205. mov es,[low_seg]
  3206. mov si,[heap_top]
  3207. mov di,offset reload_file
  3208. cld
  3209. srf_loop:
  3210. lodsb
  3211. stosb
  3212. cmp al,20h ; BAP from here
  3213. jne srf_brian ; if AL = 20h, poke a 00
  3214. xor al,al ; in instead, to terminate
  3215. dec di ; the file. COMSPEC can then have
  3216. stosb ; switches, but reload_file is
  3217. srf_brian: ; just the file name.
  3218. cmp al,0
  3219. jnz srf_loop
  3220. pop di
  3221. pop si
  3222. pop es
  3223. ret
  3224. public _get_out_pipe
  3225. _get_out_pipe:
  3226. ; copy out_pipe filename from low_seg to data seg
  3227. push ds
  3228. push es
  3229. push si
  3230. push di
  3231. ;mov ax,0e40h
  3232. ;int 10h
  3233. mov ax,ds
  3234. mov es,ax
  3235. mov di,offset DGROUP:_out_pipe
  3236. mov ds,[low_seg]
  3237. mov si,offset out_pipe
  3238. mov cx,8
  3239. cld
  3240. rep movsb
  3241. pop di
  3242. pop si
  3243. pop es
  3244. pop ds
  3245. ret
  3246. public _docmd_int2f
  3247. ;
  3248. ; BOOLEAN docmd_int2f(BYTE *cmdline, BYTE *cmd, UWORD count);
  3249. ;
  3250. ; cmdline db max, actual, 'COMMAND LINE', CR
  3251. ; cmd db length, 'COMMAND', CR
  3252. ; count db remaining length of tail, FF/00 internal/external flag
  3253. ;
  3254. ;
  3255. _docmd_int2f:
  3256. push bp
  3257. mov bp,sp
  3258. push bx
  3259. push si
  3260. mov bx,4[bp] ; bx -> original command line
  3261. mov si,6[bp] ; si -> upper cased command
  3262. mov cx,8[bp]
  3263. mov dx,0ffffh
  3264. mov ax,0AE00h
  3265. int 2fh
  3266. test al,al
  3267.  jz docmd_int2f_exit
  3268. mov bx,4[bp]
  3269. mov si,6[bp]
  3270. mov cx,8[bp]
  3271. mov dx,0ffffh
  3272. mov ax,0AE01h
  3273. int 2fh
  3274. mov al,1
  3275. docmd_int2f_exit:
  3276. cbw ; return true if handled
  3277. pop si
  3278. pop bx
  3279. pop bp
  3280. mov bx,ax
  3281. mov dx,ax
  3282. ret
  3283. _TEXT ENDS
  3284. endif
  3285. end ; start address