home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume19 / dmake / part22 < prev    next >
Encoding:
Text File  |  1991-05-12  |  40.2 KB  |  1,302 lines

  1. Newsgroups: comp.sources.misc
  2. From: Dennis Vadura <dvadura@watdragon.waterloo.edu>
  3. Subject:  v19i043:  dmake - dmake version 3.7, Part22/37
  4. Message-ID: <1991May12.221316.16177@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: b40bfb191693aa8eeaefa4ec5985b6c2
  6. Date: Sun, 12 May 1991 22:13:16 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: Dennis Vadura <dvadura@watdragon.waterloo.edu>
  10. Posting-number: Volume 19, Issue 43
  11. Archive-name: dmake/part22
  12. Supersedes: dmake-3.6: Volume 15, Issue 52-77
  13.  
  14. ---- Cut Here and feed the following to sh ----
  15. #!/bin/sh
  16. # this is dmake.shar.22 (part 22 of a multipart archive)
  17. # do not concatenate these parts, unpack them in order with /bin/sh
  18. # file dmake/msdos/config.mk continued
  19. #
  20. if test ! -r _shar_seq_.tmp; then
  21.     echo 'Please unpack part 1 first!'
  22.     exit 1
  23. fi
  24. (read Scheck
  25.  if test "$Scheck" != 22; then
  26.     echo Please unpack part "$Scheck" next!
  27.     exit 1
  28.  else
  29.     exit 0
  30.  fi
  31. ) < _shar_seq_.tmp || exit 1
  32. if test -f _shar_wnt_.tmp; then
  33. sed 's/^X//' << 'SHAR_EOF' >> 'dmake/msdos/config.mk' &&
  34. # config file.
  35. .SOURCE.h : $(OS)
  36. X
  37. # See if we modify anything in the lower levels.
  38. .IF $(OSRELEASE) != $(NULL)
  39. X   .INCLUDE .IGNORE : $(OS)$(DIRSEPSTR)$(OSRELEASE)$(DIRSEPSTR)config.mk
  40. .END
  41. SHAR_EOF
  42. chmod 0640 dmake/msdos/config.mk ||
  43. echo 'restore of dmake/msdos/config.mk failed'
  44. Wc_c="`wc -c < 'dmake/msdos/config.mk'`"
  45. test 1663 -eq "$Wc_c" ||
  46.     echo 'dmake/msdos/config.mk: original size 1663, current size' "$Wc_c"
  47. rm -f _shar_wnt_.tmp
  48. fi
  49. # ============= dmake/msdos/dirbrk.c ==============
  50. if test -f 'dmake/msdos/dirbrk.c' -a X"$1" != X"-c"; then
  51.     echo 'x - skipping dmake/msdos/dirbrk.c (File already exists)'
  52.     rm -f _shar_wnt_.tmp
  53. else
  54. > _shar_wnt_.tmp
  55. sed 's/^X//' << 'SHAR_EOF' > 'dmake/msdos/dirbrk.c' &&
  56. /* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/msdos/RCS/dirbrk.c,v 1.1 91/05/06 15:25:29 dvadura Exp $
  57. -- SYNOPSIS -- define the directory separator string.
  58. -- 
  59. -- DESCRIPTION
  60. --     Define this string for any character that may appear in a path name
  61. --    and can be used as a directory separator.
  62. --
  63. -- AUTHOR
  64. --      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  65. --      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  66. --
  67. -- COPYRIGHT
  68. --      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  69. -- 
  70. --      This program is free software; you can redistribute it and/or
  71. --      modify it under the terms of the GNU General Public License
  72. --      (version 1), as published by the Free Software Foundation, and
  73. --      found in the file 'LICENSE' included with this distribution.
  74. -- 
  75. --      This program is distributed in the hope that it will be useful,
  76. --      but WITHOUT ANY WARRANTY; without even the implied warrant of
  77. --      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  78. --      GNU General Public License for more details.
  79. -- 
  80. --      You should have received a copy of the GNU General Public License
  81. --      along with this program;  if not, write to the Free Software
  82. --      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  83. --
  84. -- LOG
  85. --     $Log:    dirbrk.c,v $
  86. X * Revision 1.1  91/05/06  15:25:29  dvadura
  87. X * dmake Release Version 3.7
  88. X * 
  89. */
  90. X
  91. #include "extern.h"
  92. X
  93. /* dos uses /, \, and : */
  94. char*    DirBrkStr = "/\\:";
  95. X
  96. /*
  97. ** Return TRUE if the name is the full specification of a path name to a file
  98. ** starting at the root of the file system, otherwise return FALSE
  99. */
  100. PUBLIC int
  101. If_root_path(name)
  102. char *name;
  103. {
  104. X   return( (strchr(DirBrkStr, *name) != NIL(char)) ||
  105. X           (isalpha(*name) && name[1] == ':') );
  106. }
  107. SHAR_EOF
  108. chmod 0640 dmake/msdos/dirbrk.c ||
  109. echo 'restore of dmake/msdos/dirbrk.c failed'
  110. Wc_c="`wc -c < 'dmake/msdos/dirbrk.c'`"
  111. test 1776 -eq "$Wc_c" ||
  112.     echo 'dmake/msdos/dirbrk.c: original size 1776, current size' "$Wc_c"
  113. rm -f _shar_wnt_.tmp
  114. fi
  115. # ============= dmake/msdos/dirlib.h ==============
  116. if test -f 'dmake/msdos/dirlib.h' -a X"$1" != X"-c"; then
  117.     echo 'x - skipping dmake/msdos/dirlib.h (File already exists)'
  118.     rm -f _shar_wnt_.tmp
  119. else
  120. > _shar_wnt_.tmp
  121. sed 's/^X//' << 'SHAR_EOF' > 'dmake/msdos/dirlib.h' &&
  122. /* DIRLIB.H by M. J. Weinstein   Released to public domain 1-Jan-89 */
  123. X
  124. #ifndef _DIRLIB_h_
  125. #define _DIRLIB_h_
  126. X
  127. #include <stdio.h>
  128. #include "stdmacs.h"
  129. X
  130. #define MAXNAMLEN   15
  131. X
  132. struct direct {
  133. X   long              d_ino;
  134. X   unsigned short    d_reclen;
  135. X   unsigned short    d_namlen;
  136. X   char              d_name[MAXNAMLEN+1];
  137. };
  138. X
  139. typedef struct {
  140. X   char   fcb[21];
  141. X   char   attr;
  142. X   short  time;
  143. X   short  date;
  144. X   long   size;
  145. X   char   name[13];
  146. } DTA;
  147. X
  148. typedef struct {
  149. X   DTA    dd_dta;       /* disk transfer area for this dir.        */
  150. X   short  dd_stat;      /* status return from last lookup          */
  151. X   char   dd_name[1];   /* full name of file -- struct is extended */
  152. } DIR;
  153. X
  154. extern DIR           *opendir   ANSI((char *));
  155. extern struct direct *readdir   ANSI((DIR *));
  156. extern long          telldir    ANSI((DIR *));
  157. extern void          seekdir    ANSI((DIR *, long));
  158. extern void          closedir   ANSI((DIR *));
  159. extern DTA           *findfirst ANSI((char *, DTA *));
  160. extern DTA           *findnext  ANSI((DTA *));
  161. X
  162. #define rewinddir(dirp)   seekdir(dirp,0L)
  163. #endif
  164. SHAR_EOF
  165. chmod 0640 dmake/msdos/dirlib.h ||
  166. echo 'restore of dmake/msdos/dirlib.h failed'
  167. Wc_c="`wc -c < 'dmake/msdos/dirlib.h'`"
  168. test 1086 -eq "$Wc_c" ||
  169.     echo 'dmake/msdos/dirlib.h: original size 1086, current size' "$Wc_c"
  170. rm -f _shar_wnt_.tmp
  171. fi
  172. # ============= dmake/msdos/exec.asm ==============
  173. if test -f 'dmake/msdos/exec.asm' -a X"$1" != X"-c"; then
  174.     echo 'x - skipping dmake/msdos/exec.asm (File already exists)'
  175.     rm -f _shar_wnt_.tmp
  176. else
  177. > _shar_wnt_.tmp
  178. sed 's/^X//' << 'SHAR_EOF' > 'dmake/msdos/exec.asm' &&
  179. ; DESCRIPTION
  180. ;      This code is a model independent version of DOS exec that will swap
  181. ;      the calling process out to secondary storage prior to running the
  182. ;      child.  The prototype for calling the exec function is below.
  183. ;
  184. ;      exec( int swap, char far *program, char far *cmdtail,
  185. ;         int environment_seg, int env_size, char far *tmpfilename );
  186. ;
  187. ;
  188. ;      To assemble this file issue the command:
  189. ;
  190. ;         tasm /mx /t /dmmodel exec.asm
  191. ;
  192. ;      where 'model' is one of {small, compact, medium, large}, you may
  193. ;      also use MASM 5.1 to assemble this file, in this case simply replace
  194. ;      'tasm' with 'masm' in the above command line.
  195. ;
  196. ; AUTHOR
  197. ;      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  198. ;      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  199. ;
  200. ; COPYRIGHT
  201. ;      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  202. ;      This program is free software; you can redistribute it and/or
  203. ;      modify it under the terms of the GNU General Public License
  204. ;      (version 1), as published by the Free Software Foundation, and
  205. ;      found in the file 'LICENSE' included with this distribution.
  206. ;      This program is distributed in the hope that it will be useful,
  207. ;      but WITHOUT ANY WARRANTY; without even the implied warrant of
  208. ;      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  209. ;      GNU General Public License for more details.
  210. ;      You should have received a copy of the GNU General Public License
  211. ;      along with this program;  if not, write to the Free Software
  212. ;      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  213. ;
  214. ifdef have286
  215. X .286    ; define have286 with -D for 80286 processor or better
  216. X
  217. else    ; 8088/8086 compatible
  218. X    mpusha Macro
  219. X        push ax
  220. X    push cx
  221. X    push dx
  222. X    push bx
  223. X    push sp
  224. X    push bp
  225. X    push si
  226. X    push di
  227. X    Endm
  228. X
  229. X    mpopa Macro
  230. X        pop di
  231. X    pop si
  232. X    pop bp
  233. X    add sp,2
  234. X    pop bx
  235. X    pop dx
  236. X    pop cx
  237. X    pop ax
  238. X    Endm
  239. endif
  240. X
  241. ifdef msmall
  242. X            .model    small
  243. argbase        equ    4
  244. endif
  245. ifdef mcompact
  246. X        .model  compact
  247. argbase        equ    4
  248. endif
  249. ifdef mmedium
  250. X        .model    medium
  251. argbase        equ    6
  252. endif
  253. ifdef mlarge
  254. X        .model    large
  255. argbase        equ    6
  256. endif
  257. a_swap        equ    <bp+argbase+0>
  258. a_prog        equ    <bp+argbase+2>
  259. a_tail        equ    <bp+argbase+6>
  260. a_env         equ    <bp+argbase+10>
  261. a_tmp        equ    <bp+argbase+12>
  262. X
  263. a_handle    equ    <bp+argbase>
  264. X
  265. X
  266. ; Define all useful equ's
  267. swap_xms    equ    0        ; we swapped it out to xms
  268. swap_ems    equ    2        ; we swapped it out to ems
  269. swap_file    equ    4        ; we swapped it out to a file
  270. seg_no_alloc    equ    0        ; this is part of a segment
  271. seg_alloc    equ    1        ; this is a full segment header
  272. seg_data    equ    2        ; this is data for part of a segment
  273. X
  274. X
  275. ; Define any global/external variables that we will be accessing from here.
  276. X            .data
  277. X        extrn    _errno:word        ; Set to dos ret code from exec
  278. X        public  _Interrupted        ; Set to 1 if interrupted 0
  279. _Interrupted    dw    0            ; otherwise
  280. X
  281. X            .code
  282. X        assume    cs:@code, ds:@code, ss:@code, es:@code
  283. X
  284. X        even
  285. execstack    dw    64  dup (?)    ; put the temporary exec stack right
  286. exec_sp        label    word        ; at the start.
  287. X
  288. old_ss        dw    ?        ; save stack seg across exec
  289. old_sp        dw    ?        ; save stack ptr across exec
  290. progsize    dw    ?        ; original size of the program
  291. rootsize    dw    ?        ; size of base root kept during swap
  292. resend        dw    ?        ; paragraph where resident code ends
  293. envseg        dw    ?        ; paragraph of environment segment
  294. psp        dw    ?        ; our own psp
  295. swap        dw    ?        ; swapping selection flag
  296. eretcode    dw    ?        ; return code from exec
  297. interrupted    dw    ?        ; interrupted flag for exec
  298. arenahead    dw    ?        ; start of memory block list
  299. alstr        dw    ?        ; allocation strategy save spot
  300. in_exec        dw    0        ; flag, 1 ==> in exec
  301. X
  302. cmdpath        db    65  dup(?)    ; file to exec
  303. cmdtail        db    129 dup(?)    ; its command tail
  304. fcb        db    37  dup(0)    ; dummy fcb
  305. tmpseg        db    7   dup(?)    ; block header buffer
  306. X
  307. tmpname        db    65  dup(0)    ; name of temporary file resource
  308. X
  309. X        even
  310. tmphandle    dw    ?        ; handle for temporary file
  311. real_21h    dd    0        ; will be DOS's 21h vector if doing -C
  312. X
  313. std_fil_handle    dw    ?        ; file handle for -C file
  314. std_fil_number    db    ?        ; system file number for -C file
  315. our_stdout    db    ?        ; sys file number our stdout handle
  316. X
  317. error_rhdr    db    "exec: Failure reading header block", 0DH, 0AH, '$'
  318. error_rseg    db    "exec: Failure reading segment data", 0DH, 0AH, '$'
  319. error_resize    db    "exec: Failure on resize", 0DH, 0AH, '$'
  320. error_free    db    "exec: Failure to free a block", 0DH, 0AH, '$'
  321. error_string    db    "exec: Program swap failure", 0DH, 0AH, '$'
  322. error_alloc    db    "exec: Memory blocks don't match", 0DH, 0AH, '$'
  323. X
  324. X        even
  325. write_header label word
  326. X   whdr_xms_ptr        dw    word ptr whdr_xms
  327. X   whdr_ems_ptr        dw    word ptr whdr_ems
  328. X   whdr_file_ptr    dw    word ptr whdr_file
  329. X
  330. write_seg label word
  331. X   wseg_xms_ptr        dw    word ptr wseg_xms
  332. X   wseg_ems_ptr        dw    word ptr wseg_ems
  333. X   wseg_file_ptr    dw    word ptr wseg_file
  334. X
  335. read_header label word
  336. X   rhdr_xms_ptr        dw    word ptr rhdr_xms
  337. X   rhdr_ems_ptr        dw    word ptr rhdr_ems
  338. X   rhdr_file_ptr    dw    word ptr rhdr_file
  339. X
  340. read_seg label word
  341. X   rseg_xms_ptr        dw    word ptr rseg_xms
  342. X   rseg_ems_ptr        dw    word ptr rseg_ems
  343. X   rseg_file_ptr    dw    word ptr rseg_file
  344. X
  345. free_resource label word
  346. X   free_xms_ptr        dw    word ptr free_xms_resource
  347. X   free_ems_ptr        dw    word ptr free_ems_resource
  348. X   free_file_ptr    dw    word ptr free_file_resource
  349. X
  350. reset_resource label word
  351. X   reset_xms_ptr    dw    word ptr reset_xms_resource
  352. X   reset_ems_ptr    dw    word ptr reset_ems_resource
  353. X   reset_file_ptr    dw    word ptr reset_file_resource
  354. X
  355. old_ctl_brk label dword
  356. X   old_ctl_brk_off    dw    ?
  357. X   old_ctl_brk_seg     dw    ?
  358. X
  359. old_crit_err label dword
  360. X   old_crit_err_off    dw    ?
  361. X   old_crit_err_seg     dw    ?
  362. X
  363. exec_block label word
  364. X  ex_envseg    dw    ?            ; env seg, use parent's if 0
  365. X  ex_cmdtail    dd    ?            ; command tail for exec
  366. X  ex_fcb1    dd    far ptr fcb        ; fcb's aren't used by dmake
  367. X  ex_fcb2    dd    far ptr fcb
  368. X  ex_ss        dw    ?            ; saved ss for exec
  369. X  ex_sp        dw    ?            ; saved sp for exec
  370. X  ex_error    dw    0            ; error code for dos exec
  371. X
  372. X
  373. ; Special 21h (DOS call) handler to tee stdout/stderr writes to the -C file.
  374. ; Ignore 21h calls that aren't writes to 1 or 2; i.e., pass them to DOS handler.
  375. ; If write call was from this process, it's pretty simple to duplicate it
  376. ; to the -C file.  If it's from another process, we try to write to its
  377. ; inherited handle.  Worst case is where the handle wasn't inherited: someone
  378. ; closed it.  In that instance we have to switch to dmake's PSP to do the
  379. ; duplicate write.
  380. X
  381. ; Subprocesses do not get their stdout/stderr teed to the -C file if
  382. ; their stdout/stderr no longer points to the file/device that dmake's
  383. ; stdout points to.  This is tested by looking at the process's job
  384. ; file table, which is a table that maps process handles to DOS system file
  385. ; table numbers.  (The far pointer to the JFT is at the PSP offset 34h.)
  386. ; The JFT is also queried to see if the -C file was inherited.
  387. X
  388. ; O_BINARY, O_TEXT problems are ignored here.  These are fudged by the
  389. ; C library before it calls DOS; since we're working below that level
  390. ; we don't have to worry about it.
  391. X
  392. simulate_21h Macro
  393. X    pushf            ;; direct call to DOS
  394. X    call cs:[real_21h]
  395. X    Endm
  396. X
  397. X    assume cs:@code, ds:nothing, es:nothing, ss:nothing
  398. our_21h_handler proc far
  399. X    pushf
  400. X    cmp ah,40h        ; is this a write?
  401. X    jne call_dos    ; --no
  402. X    cmp bx,1        ; write on handle 1 (stdout?)
  403. X    je duplicate_it
  404. X    cmp bx,2        ; stderr?
  405. X    je duplicate_it
  406. X
  407. call_dos:
  408. X    popf
  409. X    jmp [real_21h]    ; far jump to real handler, which will do the sys call
  410. X                ; and return to the original caller
  411. X
  412. duplicate_it:
  413. X    mpusha
  414. X    push ds
  415. X    push es
  416. X    mov bp,sp
  417. X
  418. X    mov di,std_fil_handle    ; handle of the -C file
  419. X
  420. X  If @codesize eq 0
  421. X      ; Small/compact models allow for quick test of us versus subprocess.
  422. X    ; False negative (it's us with a different CS) will be picked
  423. X    ; up by code just below.  (Might happen due to call from C library.)
  424. X    ; False positives would be bad, but can't happen.
  425. X    mov ax,[bp+24]    ; caller's CS
  426. X    cmp ax,@code    ; same as us?
  427. X    je call_from_dmake
  428. X  Endif
  429. X
  430. X    mov ah,51h        ; get PSP ("undocumented version" works in DOS 2.0+)
  431. X    simulate_21h    ; PSP segment returned in BX
  432. X    cmp bx,psp        ; our PSP?
  433. X    je call_from_dmake    ; --yes, no PSP changing needed
  434. X
  435. X    mov es,bx        ; set ES to current (caller's) PSP
  436. X    lds bx,es:[34h]    ; set DS:BX pointing to caller's job file table
  437. X
  438. X    mov si,[bp+12]    ; file handle caller passed in (known to be 1 or 2)
  439. X    mov al,[bx+si]    ; system file number corresponding to caller's handle
  440. X    cmp al,our_stdout    ; same as our stdout?
  441. X    jne do_real_write    ; no--subprocess must have redirected it
  442. X
  443. X    mov al,[bx+di]    ; see if caller has dup of -C file still open
  444. X    cmp al,std_fil_number
  445. X    je use_dup        ; yes--we can write using caller's PSP
  446. X
  447. X        ; Calling process (or some intermediate process) has closed
  448. X    ; the -C descriptor.  We'll use dmake's (our) -C descriptor, but
  449. X    ; to do so we'll have to change the PSP.  Disable BREAK handling
  450. X    ; so that ^break doesn't kill the wrong process.
  451. X
  452. X    mov ax,3300h    ; get BREAK flag
  453. X    simulate_21h
  454. X    mov si,dx        ; save BREAK state in SI
  455. X    sub dx,dx        ; now turn break flag off
  456. X    mov ax,3301h
  457. X    simulate_21h    ; don't want ^Break recoginized while PSP changed
  458. X    mov bx,psp        ; set dmake's PSP
  459. X    mov ah,50h
  460. X    simulate_21h
  461. X
  462. X    mov bx,di            ; handle of -C file
  463. X    ; CX still has caller's count
  464. X    mov ds,[bp+2]        ; restore caller's DS
  465. X    mov dx,[bp+14]        ; DS:DX again points to caller's buffer
  466. X    mov ah,40h
  467. X    simulate_21h        ; write the copy
  468. X
  469. X    mov bx,es        ; caller's PSP
  470. X    mov ah,50h        ; set PSP
  471. X    simulate_21h    ; restore caller's PSP
  472. X    mov dx,si        ; break state before we changed it
  473. X    mov ax,3301h
  474. X    simulate_21h    ; restore break state
  475. X
  476. X    jmp short do_real_write
  477. X
  478. use_dup:
  479. X    mov ds,[bp+2]        ; restore caller's DS
  480. X    mov dx,[bp+14]        ; DS:DX again points to caller's buffer
  481. X
  482. call_from_dmake:
  483. X    mov bx,di            ; handle of -C file
  484. X    mov ah,40h            ; write
  485. X    ; CX still has caller's count
  486. X    simulate_21h        ; write to the file
  487. X
  488. do_real_write:
  489. X    pop es
  490. X    pop ds
  491. X    mpopa
  492. X    popf
  493. X    jmp [real_21h]    ; far jump to real handler, which will do the sys call
  494. X                ; and return to the original caller
  495. our_21h_handler endp
  496. X
  497. X    assume    cs:@code, ds:@code, ss:@code, es:@code
  498. X
  499. ;-----------------------------------------------------------------------------
  500. ; First define the critical-error and control-brk handlers. 
  501. ; The critical error handler simply pops the machine state and returns an
  502. ; access denied result code.
  503. crit_err_handler proc far
  504. X        add    sp, 6        ; ip/cs/flags ...
  505. X        pop    ax
  506. X        pop    bx
  507. X        pop    cx
  508. X        pop    dx
  509. X        pop    si
  510. X        pop    di
  511. X        pop    bp
  512. X        pop    ds
  513. X        pop    es
  514. X        push    bp        ; fix up the return flags
  515. X        mov    bp, sp
  516. X        xchg    ax, [bp+6]    ; get the flag byte.
  517. X        or    ax, 1        ; set the carry bit
  518. X        xchg    ax, [bp+6]    ; put it back.
  519. X        pop    bp
  520. X        mov    ax, 5        ; access denied
  521. X        iret
  522. crit_err_handler endp
  523. X
  524. X
  525. ;-----------------------------------------------------------------------------
  526. ; Here we set the interrupted flag, and terminate the currently running
  527. ; process.
  528. ctl_brk_handler proc far
  529. X        clc                ; make sure carry is clear
  530. X        inc    cs:interrupted        ; set the flag
  531. X
  532. ; Make certain it isn't us that is going to get terminated.
  533. ; There is a small window where the in_exec flag is set but the child is
  534. ; not running yet, I assume that DOS doesn't test for ctl_brk at that time
  535. ; as it is bussily creating a new process.
  536. X        cmp    cs:in_exec,0
  537. X        je    just_return        ; note this implies CF == 0
  538. X        stc                ; set CF to abort child
  539. just_return:    iret
  540. ctl_brk_handler endp
  541. X
  542. X
  543. ;-----------------------------------------------------------------------------
  544. ; Something really nasty happened, so abort the exec call and exit.
  545. ; This kills the calling process altogether, and is a very nasty way of
  546. ; termination since files may still be open etc.
  547. abort_exec_rhdr label near
  548. X        mov    dx, offset error_rhdr
  549. X        jmp    print_it
  550. abort_exec_rseg label near
  551. X        mov    dx, offset error_rseg
  552. X        jmp    print_it
  553. abort_exec_resize label near
  554. X        mov    dx, offset error_resize
  555. X        jmp    print_it
  556. abort_exec_free label near
  557. X        mov    dx, offset error_free
  558. X        jmp    print_it
  559. abort_exec_alloc label near
  560. X        mov    dx, offset error_alloc
  561. X        jmp    print_it
  562. abort_exec proc near
  563. X        mov    dx, offset error_string
  564. print_it:    push    dx
  565. X        mov    bx, [swap]
  566. X        call    [free_resource+bx]
  567. X        mov    ax, cs
  568. X        mov    ds, ax
  569. X        pop    dx
  570. X        mov    ah, 9
  571. X        int    21H
  572. kill_program:    mov    ax, 04cffH            ; nuke it!
  573. X        int    21H
  574. abort_exec endp
  575. X
  576. X
  577. ;-----------------------------------------------------------------------------
  578. ; lodsw/stosw loop to copy data.  Called only for word copy operations.
  579. ;     ds:si  - point at source
  580. ;    es:di  - point at destination
  581. ;    cx     - count of bytes to copy.
  582. copy_data proc near
  583. X        shr    cx, 1        ; convert to word count
  584. X        jnc    copy_words
  585. X        movsb
  586. copy_words:    rep    movsw        ; copy the words.
  587. X        ret
  588. copy_data endp
  589. X
  590. X
  591. X
  592. ;=============================================================================
  593. ; THE FOLLOWING SECTION DEALS WITH ALL ROUTINES REQUIRED TO READ XMS RECORDS.
  594. ;=============================================================================
  595. rhdr_xms proc near
  596. X        ret
  597. rhdr_xms endp
  598. X
  599. rseg_xms proc near
  600. X        ret
  601. rseg_xms endp
  602. X
  603. reset_xms_resource proc near
  604. X        ret
  605. reset_xms_resource endp
  606. X
  607. free_xms_resource proc near
  608. X        ret
  609. free_xms_resource endp
  610. ;=============================================================================
  611. X
  612. X
  613. X
  614. ;=============================================================================
  615. ; THE FOLLOWING SECTION DEALS WITH ALL ROUTINES REQUIRED TO READ EMS RECORDS.
  616. ;=============================================================================
  617. rhdr_ems proc near
  618. X        ret
  619. rhdr_ems endp
  620. X
  621. rseg_ems proc near
  622. X        ret
  623. rseg_ems endp
  624. X
  625. reset_ems_resource proc near
  626. X        ret
  627. reset_ems_resource endp
  628. X
  629. free_ems_resource proc near
  630. X        ret
  631. free_ems_resource endp
  632. ;=============================================================================
  633. X
  634. X
  635. X
  636. ;=============================================================================
  637. ; THE FOLLOWING SECTION DEALS WITH ALL ROUTINES REQUIRED TO READ FILE RECORDS.
  638. ;=============================================================================
  639. ; This routine reads a segment header from a file.
  640. ; The header is a seven byte record formatted as follows:
  641. ;    segment address        - of data
  642. ;    offset address        - of data
  643. ;     length in paragraphs    - of data
  644. ;    mode            - 1 => segment header (allocate seg on read)
  645. ;                  0 => subsegment, don't allocate on read.
  646. ; The information is placed into the tmpseg data area in the code segment.
  647. ; The routine aborts if an error is detected.
  648. rhdr_file proc near
  649. X        mov    dx, offset tmpseg    ; read the header record out
  650. X        mov    cx, 7
  651. X        mov    bx, [tmphandle]
  652. X        mov    ah, 03fH
  653. X        int    21H
  654. X        jnc    rhdr_done        ; make sure it worked
  655. X        jmp    abort_exec_rhdr
  656. X
  657. rhdr_done:    cmp    ax, 7
  658. X        je    exit_rhdr_file
  659. X        or    ax, ax
  660. X        je    signal_eof
  661. X        jmp    abort_exec_rhdr
  662. X
  663. signal_eof:    stc
  664. exit_rhdr_file:    ret
  665. rhdr_file endp
  666. X
  667. X
  668. ;-----------------------------------------------------------------------------
  669. ; Read a segment from the temporary file whose handle is in cs:tmphandle.
  670. ; The routine aborts if an error is detected.
  671. rseg_file proc near
  672. X        push    ds
  673. X        mov    ds, word ptr cs:tmpseg; Now read the whole segment
  674. X        mov    dx, word ptr cs:tmpseg+2
  675. X        mov    cx, word ptr cs:tmpseg+4
  676. X        mov    bx, cs:tmphandle
  677. X        mov    ah, 03fH
  678. X        int    21H
  679. X        pop    ds
  680. X        jnc    rseg_done
  681. X        jmp    abort_exec_rseg
  682. X
  683. rseg_done:    cmp    ax, [word ptr tmpseg+4]
  684. X        je    exit_rseg_file
  685. X        jmp    abort_exec_rseg        ; If we didn't get read full
  686. exit_rseg_file:    ret                ; segment then abort
  687. rseg_file endp
  688. X
  689. X
  690. ;-----------------------------------------------------------------------------
  691. ; Seek to the beginning of the file.
  692. reset_file_resource proc near
  693. X        mov    bx, [tmphandle]
  694. X        xor    cx, cx
  695. X        mov    dx, cx
  696. X        mov    ax, 04200H        ; seek to begining of file
  697. X        int    21H
  698. X        ret
  699. reset_file_resource endp
  700. X
  701. X
  702. ;-----------------------------------------------------------------------------
  703. ; unlink the temporary file allocated for swapping.
  704. ; We close the file first, and then delete it.   We ignore errors here since
  705. ; we can't do anything about them anyway.
  706. free_file_resource proc near
  707. X        mov    bx, [tmphandle]        ; get the file handle
  708. X        mov    ah, 03eH        ; close the file
  709. X        int    21H
  710. X        mov    dx, offset tmpname    ; Now delete the temp file
  711. X        mov    ah, 041H
  712. X        int    21H
  713. X        ret
  714. free_file_resource endp
  715. ;=============================================================================
  716. X
  717. X
  718. X
  719. ;=============================================================================
  720. ; CODE TO SWAP THE IMAGE IN FROM SECONDARY STORAGE
  721. ;=============================================================================
  722. swap_in proc near
  723. X        mov    bx, [alstr]        ; get previous alloc strategy
  724. X        mov    ax, 5801H        ; and set it back
  725. X        int    21H
  726. X        mov    bx, [swap]        ; get type of resource
  727. X        call    [reset_resource+bx]    ; reset the resource
  728. X        mov    es, [psp]        ; resize the program back
  729. X        mov    bx, [progsize]        ; to original size
  730. X        mov    ah, 04AH
  731. X        int    21H
  732. X        jnc    read_seg_loop
  733. X        jmp    abort_exec
  734. X
  735. read_seg_loop:    mov    bx, [swap]        ; get type of resource
  736. X        call    [read_header+bx]    ; get seg header
  737. X        jc    exit_swap_in        ; all done
  738. X        mov    al, [tmpseg+6]
  739. X        cmp    al, seg_no_alloc    ; see if dummy segment header
  740. X        je    read_seg_loop
  741. X        cmp    al, seg_alloc        ; do we need to do an alloc?
  742. X        jne    read_data        ; nope
  743. X
  744. ; Allocate back the memory for a segment that is not the [psp], note that this
  745. ; must come back to the same segment we had previously since other segments
  746. ; may have pointers stored in their variables that point to this segment using
  747. ; segment:offset long pointers.
  748. X        mov    bx, [word ptr tmpseg+4]    ; get count of paragraphs
  749. X        mov    ah, 048H        ; dos_alloc
  750. X        int    21H
  751. X        jc    alloc_error        ; oops!
  752. X        cmp    ax, [word ptr tmpseg]    ; did we get the same segment?
  753. X        je    read_seg_loop        ; yup!
  754. alloc_error:    jmp    abort_exec_alloc
  755. X
  756. read_data:    mov    bx, [swap]
  757. X        call    [read_seg+bx]        ; this must succeed, if fail
  758. X        jmp    read_seg_loop        ; we never come back here
  759. X
  760. exit_swap_in:    mov    bx, [swap]        ; all done, so free resource
  761. X        call    [free_resource+bx]
  762. X        ret
  763. swap_in endp
  764. X
  765. X
  766. ;=============================================================================
  767. ; CODE TO SWAP THE IMAGE OUT TO SECONDARY STORAGE
  768. ;=============================================================================
  769. ; This routine is called to swap the non-resident portion of the program
  770. ; out to the resource specified by the value of [cs:swap].  If the swap out
  771. ; fails, then appropriate routines are called to free the resources allocated
  772. ; up to that point.
  773. ;
  774. ; The steps used to swap the program out are as follows:
  775. ;    - calculate new size of program to remain resident and size to swap
  776. ;      out.
  777. ;    - write out non-resident portion of current segment
  778. ;    - walk DOS allocation chain and write out all other segments owned by
  779. ;      the current program that are contiguous with the _psp segment
  780. ;    - copy the environment down to low memory
  781. ;    - resize the current _psp segment to savesize
  782. ;    - free all segments belonging to program except current _psp segment
  783. swap_out proc near
  784. X        mov    ax, 05800H    ; get memory alocation strategy
  785. X        int    021H
  786. X        mov    [alstr], ax    ; and save it for future restoration.
  787. X        mov    di, [psp]    ; compute length of program to current
  788. X        mov    bx, cs        ; value of cs, and find program size
  789. X        sub    bx, di        ; by looking at length stored in
  790. X        mov    ax, di        ; arena header found in front of psp
  791. X        dec    ax
  792. X        mov    es, ax
  793. X        mov    si, es:3    ; si is size of program in paragraphs
  794. X        mov    [progsize], si    ; progsize now contains the size.
  795. X
  796. ; Now compute length of program segment to save.
  797. ; Length is:   cs - psp + (offset overlay_code_here+15 >> 4)
  798. X        mov    ax, offset overlay_code_here+15
  799. X        shr    ax, 1
  800. X        shr    ax, 1
  801. X        shr    ax, 1
  802. X        shr    ax, 1
  803. X        add    bx, ax            ; bx is size of program to keep
  804. X        sub    si, bx            ; si is # of paragraphs to save.
  805. X        add    di, bx            ; di is paragraph to start at
  806. X        mov    rootsize, bx
  807. X        mov    resend, di        ; cs:resend is saved start para
  808. X        mov    al, seg_no_alloc    ; set no allocation for segment
  809. X        call    write_segment
  810. X        jc    abort_swap_out
  811. X
  812. ; We have now saved the portion of the program segment that will not remain
  813. ; resident during the exec.  We should now walk the DOS allocation chain and
  814. ; write out all other segments owned by the current process.
  815. save_segments:    mov    ax, [psp]
  816. X        dec    ax
  817. X        mov    es, ax
  818. X        mov    bx, offset write_segment_data
  819. X        call    walk_arena_chain
  820. X        jc    abort_swap_out
  821. X
  822. ; Now we must walk the chain of allocated memory blocks again and free
  823. ; all those that are owned by the current process, except the one that is
  824. ; the current process' psp.
  825. free_segments:    mov    ax, [psp]
  826. X        dec    ax
  827. X        mov    es,ax
  828. X        mov    bx, offset free_dos_segment
  829. X        call    walk_arena_chain
  830. X        jnc    resize_program
  831. X        jmp    abort_exec_free        ; can't fix it up now.
  832. X
  833. ; We now resize the program to the size specified by cs:rootsize.  This will
  834. ; free most of the memory taken up by the current program segment.
  835. resize_program: mov    es, [psp]        ; es is segment to resize.
  836. X        mov    bx, [rootsize]        ; bx is size of segment.
  837. X        mov    ah, 04aH        ; resize memory block
  838. X        int    21H
  839. X        jnc    swap_out_ok
  840. X        jmp    abort_exec_resize    ; disaster
  841. swap_out_ok:    ret
  842. X
  843. ; The swap out failed for some reason, so free any allocated resources
  844. ; and set the carry bit.
  845. abort_swap_out:    mov    bx, [swap]
  846. X        call    [free_resource+bx]
  847. X        xor    ax, ax
  848. X        mov    [swap], ax        ; clear the swap flag
  849. X        stc
  850. X        ret
  851. swap_out endp
  852. X
  853. X
  854. ;=============================================================================
  855. ; CODE TO SET-UP FOR AND EXEC THE CHILD PROCESS
  856. ;=============================================================================
  857. ; Actually execute the program.  If cs:swap is set, this code will invoke the
  858. ; swap-out/swap-in code as required.
  859. do_exec proc near
  860. X        cmp    [swap], 0        ; does the user want to swap?
  861. X        je    no_swap_out        ; nope
  862. X        call    init_swap        ; figger out where to swap to
  863. X        jc    no_swap_out        ; if carry set then don't swap
  864. X        call    swap_out
  865. X
  866. no_swap_out:    cmp    [interrupted], 0    ; were we interrupted?
  867. X        jne    leave_exec        ; yep, so clean up, don't exec
  868. X
  869. ; free passed in environment block if it is non zero.
  870. ; This way the parent program does not need to free it.
  871. X        mov    ax, [envseg]
  872. X        or    ax, ax
  873. X        je    setup_block
  874. X        push    ax
  875. X        mov    es, ax
  876. X        mov    ah, 49H
  877. X        int    21H
  878. X        pop    ax
  879. X
  880. ; set up the parameter block for the DOS exec call.
  881. ;    offset  contents
  882. ;        00  segment address of environment to be passed,
  883. ;          0 => use parents env.
  884. ;        02  pointer to command tail for new process.
  885. ;        06  pointer to fcb1
  886. ;        0a  pointer to fcb2
  887. setup_block:    mov    ax, [envseg]
  888. X        mov    [ex_envseg], ax
  889. X        mov    cx, cs
  890. X        mov    [word ptr ex_cmdtail], offset cmdtail
  891. X        mov    [word ptr ex_cmdtail+2], cx
  892. X
  893. ; set up registers for exec call
  894. ;    ds:dx    - pointer to pathname of program to execute
  895. ;    es:bx    - pointer to above parameter block
  896. X        mov    dx, offset cmdpath
  897. X        mov    es, cx
  898. X        mov    bx, offset exec_block
  899. X
  900. ; Under DOS 2.x exec is notorious for clobbering registers and guarantees
  901. ; to preserve only cs:ip.
  902. X        push    ds
  903. X        mov    [ex_sp], sp
  904. X        mov    [ex_ss], ss
  905. X        mov    [ex_error], 0        ; clear exec error code
  906. X        inc    [in_exec]        ; set internal flag
  907. X        mov    ax, 04b00H
  908. X        int    21H
  909. X
  910. ; returned from exec, so restore possibly clobbered registers.
  911. X        mov    ss, cs:ex_ss
  912. X        mov    sp, cs:ex_sp
  913. X        pop    ds
  914. X
  915. ; check to make certain the exec call worked.
  916. X        jnc    it_worked
  917. X
  918. ; exec call failed.  Save return code from msdos.
  919. X        mov    [ex_error], ax
  920. X        jmp    leave_exec
  921. X
  922. it_worked:    mov    ah, 04dH    ; get the return code
  923. X        int    21H
  924. X        cbw
  925. X        mov    [eretcode], ax
  926. X
  927. leave_exec:    cmp    [swap], 0    ; check swap, if non-zero swap back in
  928. X        je    no_swap_in
  929. X        call    swap_in
  930. X
  931. ; Clear the in_exec after the swap back in.  This way we are guaranteed to
  932. ; get parent in and the resources freed should a ^C be hit when we are reading
  933. ; the image in.
  934. no_swap_in:    mov    [in_exec], 0
  935. X        ret
  936. do_exec endp                
  937. X
  938. X
  939. X
  940. ;==============================================================================
  941. ; Everything past this point is overwriten with the environment and new
  942. ; program after the currently executing program is swapped out.
  943. ;==============================================================================
  944. overlay_code_here label word
  945. X
  946. ;-----------------------------------------------------------------------------
  947. ; Figure out where we can swap to and initialize the resource we are going to
  948. ; use.  We try XMS, EMS, and a tempfile (if specified), in that order.  We set
  949. ; [cs:swap] to the correct value based on which of the resources exists.
  950. ; If none can be used, then [cs:swap] is set to 0, and no swap takes place.
  951. ; The exec code will still attempt to execute the child in this instance, but
  952. ; may fail due to lack of resources.   Each swap_out_* routine must provide
  953. ; its own clean-up handler should it not be able to write all program
  954. ; segments to the swap resource.
  955. init_swap proc near
  956. X        mov    [swap], 0
  957. ;call    init_xms
  958. ;jnc    init_done
  959. ;call    init_ems
  960. ;jnc    init_done
  961. X        call    init_file
  962. init_done:    ret
  963. init_swap endp
  964. X
  965. X
  966. ;-----------------------------------------------------------------------------
  967. ; This routine is used to walk the DOS allocated memory block chain
  968. ; starting at address supplied in the es register.  For each block it
  969. ; calls the routine specified by the bx register with the segment length
  970. ; in si, and its address in di.  It does not apply the routine to the
  971. ; segment if the segment is the same as the current program's [cs:psp] value.
  972. memheader struc
  973. X   magic    db    ?    ; either 'Z' for end or 'M' for allocated
  974. X   owner    dw    ?    ; psp of owner block
  975. X   len        dw    ?    ; length in paragraphs of segment
  976. memheader ends
  977. X
  978. walk_arena_chain proc near
  979. X        mov    si, word ptr es:3        ; get length
  980. X        mov    di, es
  981. X        inc    di
  982. X        mov    ax, word ptr es:1
  983. X
  984. ; Stop the search if the block is NOT owned by us.  Ignore our own psp block
  985. ; and our environment segment block.
  986. X        cmp    ax, cs:psp            ; is it owned by us?
  987. X        jne    walk_done            ; NOPE!  -- all done
  988. X        cmp    di, cs:envseg            ; skip our environment
  989. X        je    next_block
  990. X        cmp    di, cs:psp            ; skip our psp
  991. X        je    next_block
  992. X
  993. ; Now save state and call the routine pointed at by [bx].
  994. X        push    di
  995. X        push    si
  996. X        push    bx
  997. X        call    bx
  998. X        pop    bx
  999. X        pop    si
  1000. X        pop    di
  1001. X        jc    exit_walk            ; if error then stop
  1002. X        mov    al, byte ptr es:0        ; check if at end 
  1003. X        cmp    al, 'Z'
  1004. X        je    walk_done
  1005. X
  1006. next_block:    add    di, si                ; go on to next segment
  1007. X        mov    es, di
  1008. X        jmp    walk_arena_chain
  1009. walk_done:    clc
  1010. exit_walk:    ret
  1011. walk_arena_chain endp
  1012. X
  1013. X
  1014. ;-----------------------------------------------------------------------------
  1015. ; This routine takes a dos segment found in the di register and free's it.
  1016. free_dos_segment proc near
  1017. X        mov    es, di        ; free dos memory block
  1018. X        mov    ah, 49H
  1019. X        int    21H
  1020. X        ret
  1021. free_dos_segment endp
  1022. X
  1023. X
  1024. ;-----------------------------------------------------------------------------
  1025. ; Called to invoke write_segment with proper values in the al register.  Only
  1026. ; ever called from walk_arena_chain, and so al should be set to seg_alloc.
  1027. write_segment_data label near
  1028. X        mov    al, seg_alloc    ; and fall through into write_segment
  1029. ;-----------------------------------------------------------------------------
  1030. ; This routine writes a segment as a block of data segments if the number of
  1031. ; paragraphs to write exceeds 0x0fff (rarely the case).
  1032. ; It stuffs the info into tmpseg, and then calls wheader and wseg to get the
  1033. ; data out.
  1034. ;
  1035. ;    di:dx    segment:offset of segment;  offset is ALWAYS zero.
  1036. ;    si    number of paragraphs to write.
  1037. ;    al    mode of header to write
  1038. write_segment proc near
  1039. X        push    di
  1040. X        push    si
  1041. X        xor    dx,dx
  1042. X        mov    bx, [swap]
  1043. X        call    [write_header+bx]
  1044. X        pop    si
  1045. X        pop    di
  1046. X        jc    exit_wseg
  1047. X
  1048. do_io_loop:    cmp    si, 0        ; are we done yet?
  1049. X        je    exit_wseg    ; yup so leave.
  1050. X        mov    cx, si        ; # of paragraphs to move
  1051. X        cmp    cx, 0fffH    ; see if we have lots to move?
  1052. X        jle    do_io
  1053. X        mov    cx, 0fffH    ; reset to max I/O size
  1054. X
  1055. do_io:        push    cx        ; save # of paragraphs we are writing
  1056. X        shl    cx, 1        ; shift cx by four to the left
  1057. X        shl    cx, 1
  1058. X        shl    cx, 1
  1059. X        shl    cx, 1
  1060. X        push    di        ; save the start, and count left
  1061. X        push    si
  1062. X        mov    si, cx
  1063. X        xor    dx,dx
  1064. X        mov    al, seg_data
  1065. X        mov    bx, [swap]
  1066. X        push    bx
  1067. X        call    [write_header+bx]
  1068. X        pop    bx
  1069. X        call    [write_seg+bx]
  1070. X        pop    si
  1071. X        pop    di
  1072. X        pop    dx        ; original paragraph count in dx
  1073. X        jc    exit_wseg    ; it failed so exit.
  1074. X        add    di, dx        ; adjust the pointers, and continue.
  1075. X        sub    si, dx
  1076. X        jmp     do_io_loop
  1077. exit_wseg:    ret
  1078. write_segment endp
  1079. X
  1080. X
  1081. ;=============================================================================
  1082. ; THE FOLLOWING SECTION DEALS WITH ALL ROUTINES REQUIRED TO WRITE XMS RECORDS.
  1083. ;=============================================================================
  1084. init_xms proc near
  1085. X        ret
  1086. init_xms endp
  1087. X
  1088. whdr_xms proc near
  1089. X        ret
  1090. whdr_xms endp
  1091. X
  1092. wseg_xms proc near
  1093. X        ret
  1094. wseg_xms endp
  1095. ;=============================================================================
  1096. X
  1097. X
  1098. ;=============================================================================
  1099. ; THE FOLLOWING SECTION DEALS WITH ALL ROUTINES REQUIRED TO WRITE EMS RECORDS.
  1100. ;=============================================================================
  1101. init_ems proc near
  1102. X        ret
  1103. init_ems endp
  1104. X
  1105. whdr_ems proc near
  1106. X        ret
  1107. whdr_ems endp
  1108. X
  1109. wseg_ems proc near
  1110. X        ret
  1111. wseg_ems endp
  1112. ;=============================================================================
  1113. X
  1114. X
  1115. ;=============================================================================
  1116. ; THE FOLLOWING SECTION DEALS WITH ALL ROUTINES REQUIRED TO WRITE FILES.
  1117. ;=============================================================================
  1118. ;-----------------------------------------------------------------------------
  1119. ; Attempt to create a temporary file.  If the tempfile name is NIL then return
  1120. ; with the cary flag set.
  1121. init_file proc near
  1122. X        mov    al, [tmpname]
  1123. X        or    al, al
  1124. X        je    err_init_file
  1125. X        mov    dx, offset tmpname
  1126. X        xor     cx, cx
  1127. X        mov    ah, 03cH
  1128. X        int    21H
  1129. X        jc    err_init_file        ; if carry set then failure
  1130. X        mov    [tmphandle], ax        ; init swapping
  1131. X        mov    [swap], swap_file
  1132. X        jmp    exit_init_file
  1133. err_init_file:    stc
  1134. exit_init_file: ret
  1135. init_file endp
  1136. X
  1137. X
  1138. ;-----------------------------------------------------------------------------
  1139. ; This routine writes a segment header to a file.
  1140. ; The header is a seven byte record formatted as follows:
  1141. ;    segment address        - of data
  1142. ;    offset address        - of data
  1143. ;     length in paragraphs    - of data
  1144. ;    mode            - 1 => segment header (allocate seg on read)
  1145. ;                  0 => subsegment, don't allocate on read.
  1146. ; Routine takes three arguments:
  1147. ;    di:dx    segment:offset of segment
  1148. ;    si    number of paragraphs to write.
  1149. ;    al    mode of header to write
  1150. whdr_file proc near
  1151. X        mov    [word ptr tmpseg], di    ; save the segment/offset
  1152. X        mov    [word ptr tmpseg+2], dx
  1153. X        mov    [word ptr tmpseg+4], si    ; save the segment length
  1154. X        mov    [tmpseg+6], al
  1155. X        mov    dx, offset tmpseg    ; write the header record out
  1156. X        mov    cx, 7
  1157. X        mov    bx, [tmphandle]
  1158. X        mov    ah, 040H
  1159. X        int    21H
  1160. X        jc    exit_whdr_file        ; make sure it worked
  1161. X        cmp    ax, 7
  1162. X        je    exit_whdr_file        ; oh oh, disk is full!
  1163. err_whdr_file:    stc
  1164. exit_whdr_file:    ret
  1165. whdr_file endp
  1166. X
  1167. X
  1168. ;-----------------------------------------------------------------------------
  1169. ; Write a segment to the temporary file whose handle is in cs:tmphandle
  1170. ; Parameters for the write are assumed to be stored in the tmpseg data area.
  1171. ; function returns carry set if failed, carry clear otherwise.
  1172. wseg_file proc near
  1173. X        push    ds
  1174. X        mov    ds, word ptr cs:tmpseg ; Now write the whole segment
  1175. X        mov    dx, word ptr cs:tmpseg+2
  1176. X        mov    cx, word ptr cs:tmpseg+4
  1177. X        mov    bx, cs:tmphandle
  1178. X        mov    ah, 040H
  1179. X        int    21H
  1180. X        pop    ds
  1181. X        jc    exit_wseg_file        ; make sure it worked
  1182. X        cmp    ax, [word ptr tmpseg+4]
  1183. X        je    exit_wseg_file
  1184. err_wseg_file:    stc                ; it failed (usually disk full)
  1185. exit_wseg_file:    ret
  1186. wseg_file endp
  1187. ;=============================================================================
  1188. X
  1189. X
  1190. ;=============================================================================
  1191. ; _exec: THIS IS THE MAIN ENTRY ROUTINE TO THIS MODULE
  1192. ;=============================================================================
  1193. ; This is the main entry routine into the swap code and corresponds to the
  1194. ; following C function call:
  1195. ;
  1196. ; exec( int swap, char far *program, char far *cmdtail, int environment_seg,
  1197. ;    char far *tmpfilename );
  1198. ;
  1199. ; Exec performs the following:
  1200. ;    1. set up the local code segment copies of arguments to the exec call.
  1201. ;    2. switch to a local stack frame so that we don't clobber the user
  1202. ;       stack.
  1203. ;    3. save old interrupt vectors for ctrl-brk.
  1204. ;    4. install our own handler for the ctrl-brk interrupt, our handler
  1205. ;       terminates the current running process, and returns with non-zero
  1206. ;       status code.
  1207. ;    5. get our psp
  1208. ;    6. setup arguments for exec call
  1209. ;    7. exec the program, save result code on return.
  1210. ;       8. restore previous ctrl-brk and crit-error handler.
  1211. ;       9. restore previous process stack, and segment registers.
  1212. ;      10. return from exec with child result code in AX
  1213. ;       and global _Interrupted flag set to true if child execution was
  1214. ;       interrupted.
  1215. X
  1216. ; NOTE:  When first called the segments here assume the standard segment
  1217. ;        settings.
  1218. X        assume cs:@code, ds:DGROUP,es:DGROUP,ss:DGROUP
  1219. X
  1220. X        public    _exec
  1221. _exec proc
  1222. X            push    bp        ; set up the stack frame
  1223. X        mov    bp, sp
  1224. X        push    si        ; save registers we shouldn't step on.
  1225. X        push    di
  1226. X        push    ds
  1227. X
  1228. ; set up for copying of parameters passed in with long pointers.
  1229. X        push    cs        ; going to use lodsb/stosb, set up es
  1230. X        pop    es        ; as destination.
  1231. X        assume  es:@code    ; let the assembler know :-)
  1232. X        cld            ; make sure direction is right
  1233. X
  1234. ; Copy all parameters into the bottom of the code segment.  After doing so we
  1235. ; will immediately switch stacks, so that the user stack is preserved intact.
  1236. X        mov    ax, ss:[a_swap]        ; save swap
  1237. X        mov    es:swap, ax
  1238. X        mov    ax, ss:[a_env]        ; save env seg to use
  1239. X        mov    es:envseg, ax
  1240. X
  1241. X        mov     di, offset cs:cmdpath    ; copy the command
  1242. X        lds     si, ss:[a_prog]        ; 65 bytes worth
  1243. X        mov    cx, 65
  1244. X        call    copy_data
  1245. X
  1246. X        mov    di, offset cs:cmdtail    ; copy the command tail
  1247. X        lds    si, ss:[a_tail]        ; 129 bytes worth
  1248. X        mov    cx, 129
  1249. X        call    copy_data
  1250. X
  1251. X        mov    di, offset cs:tmpname    ; copy the temp file name
  1252. X        lds    si, ss:[a_tmp]        ; 65 bytes worth.
  1253. X        mov    cx, 65
  1254. X        call    copy_data
  1255. X
  1256. ; Now we save the current ss:sp stack pointer and swap stack to our temporary
  1257. ; stack located in the current code segment.  At the same time we reset the
  1258. ; segment pointers to point into the code segment only.
  1259. swap_stacks:    mov    ax, ss
  1260. X        mov    es:old_ss, ax
  1261. X        mov    es:old_sp, sp
  1262. X        mov    ax, cs
  1263. X        mov    ds, ax
  1264. X        mov    ss, ax            ; set ss first, ints are then
  1265. X        mov    sp, offset cs:exec_sp    ; disabled for this instr too
  1266. X        assume  ds:@code, ss:@code    ; let the assembler know :-)
  1267. X
  1268. ; Now we save the old control break and critical error handler addresses.
  1269. ; We replace them by our own routines found in the resident portion of the
  1270. ; swapping exec code.
  1271. set_handlers:    mov    [interrupted], 0    ; clear interrupted flag
  1272. X        mov    [eretcode], 0        ; clear the return code
  1273. X        mov    ax, 03523H        ; get int 23 handler address
  1274. X        int    21H
  1275. X        mov    cs:old_ctl_brk_off, bx
  1276. X        mov    cs:old_ctl_brk_seg, es
  1277. X        mov    dx, offset ctl_brk_handler
  1278. X        mov    ax, 02523H        ; set int 23 handler address
  1279. X        int    21H
  1280. X
  1281. X        mov    ax, 03524H        ; get int 24 handler address
  1282. X        int    21H
  1283. X        mov    cs:old_crit_err_off, bx
  1284. X        mov    cs:old_crit_err_seg, es
  1285. SHAR_EOF
  1286. true || echo 'restore of dmake/msdos/exec.asm failed'
  1287. fi
  1288. echo 'End of part 22, continue with part 23'
  1289. echo 23 > _shar_seq_.tmp
  1290. exit 0
  1291.  
  1292. exit 0 # Just in case...
  1293. -- 
  1294. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1295. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1296. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1297. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1298.