summaryrefslogtreecommitdiff
path: root/systems/msdos/tx/src/spawno.doc
blob: 8467c46d7e791a0664747a8a46ba0fba6dcc780e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
SPAWNO v4.13   12/12/91   disk/EMS/XMS/INT15 swapping replacement for spawn()
(c) Copyright 1990,1991,1992 Ralf Brown.  All Rights Reserved.


-----------------
LICENSE

This document and the associated header file, libraries, and source and
object modules may be freely copied provided that:
     1) all of the files are copied as a group (such as in a single
	archive).  See below for a list of files.
     2) the files are not modified in any way (including removal or
	alteration of copyright notices or this license)
     3) no charge beyond a cost-recovery fee not to exceed $5, or a
	general telecommunications connection fee, is made

The source and/or object code comprising the public SPAWNO distribution
may be incorporated at no charge into programs which are distributed or
sold to others provided that:
     1) credit is given in the documentation.  A mention such as
	   "This product uses the SPAWNO routines by Ralf Brown
	    to minimize memory use while shelling to DOS and
	    running other programs."
	is sufficient.
     2) you drop me a line telling me that you are using SPAWNO and
	in which product(s) you are using it (see addresses at the
	end of this file).  I'm interested in finding out how wide-
	spread the use of SPAWNO becomes.


-----------------
DISCLAIMER

Although both I and others have tested the code which comprises SPAWNO,
it is entirely possible that SPAWNO may malfunction in environments or
under circumstances in which it has not been tested.  This code is
provided AS IS, and the author disclaims any and all responsibility for
damages (both consequential and incidental) resulting from the use or
misuse of SPAWNO.  Sole responsibility for determining the suitability
of the code rests with the user.


-----------------
FILES

The disk or archive you received should contain the following files:

	SPAWNO.DOC	this file
	SPAWNO.H	the header file providing prototypes for the functions
	SPAWNx.LIB	versions of the library for each of [T]iny, [S]mall,
			[C]ompact, [M]edium, [L]arge, and [H]uge memory
			models.
	SPAWNTP.OBJ	Turbo Pascal version of SPAWNO
	SPAWNO.PAS	Turbo Pascal unit encapsulating SPAWNO
	SPAWN_MS.ZIP	Microsoft C versions of compiler-specific functions
	MSC.BAT		replace Turbo C specific functions in libraries with
			Microsoft C versions.
	NOREPLAC.BAT	remove replacements for the standard spawn..()
			functions from the libraries.
	SWAPTEST.C	example program for testing
	TEST.PAS	example program for testing
	SOURCE.ZIP	archive containing partial source code for SPAWNO
	    _SPAWNO.H	    header file for recompiling library
	    *.C		    source for the spawn..() and spawn...o() functions
	    RULES.ASI	    shortened and modified Turbo C macro file
	    SPAWNO.INC	    include file for various important constants
	    SPAWNPTH.ASM    source for the path search
	    CHECKEXT.ASM    check for 'file', 'file.EXE', and 'file.COM'
	    SWAP_EMS.ASM    support routines for swapping to EMS
	    SWAPLIST.ASM    specify which swap types will be linked in
	    SPAWNENV.ASM    make an environment block from an array of strings 	
	    SPAWNERR.ASM    set _doserrno and errno
	    MAKEFILE


-----------------
WHAT'S NEW

Changes/fixes from versions 4.00 to 4.10:
	Now swaps to disk with non-NULL swap list in large-data memory models
	Now correctly deletes swap file if child program changes directories
	If the given program name is "FOO", and both "FOO" and either
	   "FOO.COM" and/or "FOO.EXE" exist in the same directory, it will
	   now execute either "FOO.COM" or "FOO.EXE" rather than "FOO", as
	   both version 4.00 and the Borland library functions do.  To
	   execute "FOO", pass "FOO." rather than just "FOO" to the function.
	Fixed bug which may have led to a partially corrupted environment
	   in a few circumstances
Changes/fixes since version 4.10:
	Fixed bug which caused the PSP to restore incorrectly after a spawn
	   when DS != SS.
	Fixed bug introduced in v4.10 which caused a crash on return from the
	   child program if there was insufficient disk space for the swap
	   file.
	Fixed error in va_start call in various *.C files.  This problem
	   results in compile-time errors when compiling under BC++ in
	   certain modes (but the code compiled without warnings under
	   Turbo C 2.0).

-----------------
INSTALLATION

If you are using Turbo C, Turbo C++, or Borland C++, simply dearchive
the libraries and header file and place them where your compiler can
find them.  If you are using Microsoft C, dearchive SPAWN_MS.ZIP and
then run the MSC batch file to replace the compiler-specific functions
in the libraries with Microsoft C versions.  Please do not run this
batch file on your original copy of the libraries.

If you are using Turbo Pascal, unarchive SPAWNTP.OBJ and SPAWNO.PAS.
Compile SPAWNO.PAS and then add a USES SPAWNO; line to your program.
After that you can call the function SPAWN() as desired.  The
distribution does not contain a pre-compiled version because .TPU
files are not compatible between different versions of Turbo Pascal.


-----------------
INSTRUCTIONS

As distributed, SPAWNO contains replacements for the standard spawn..()
functions.  You can use SPAWNO with absolutely no changes to your
existing source code; however, you will probably want to call
init_SPAWNO() from main(), and include SPAWNO.H for that source file.
The initialization function takes two arguments: the first is a string
containing a list of directories (separated by semicolons) in which to
attempt to store the swap file when swapping to disk. The second
specifies which swap devices to attempt to use; it may be either
SWAP_ANY or the ORing or addition of any combination of SWAP_DISK,
SWAP_EMS, SWAP_EXT, and SWAP_XMS (such as SWAP_DISK|SWAP_XMS).	If you
do not call init_SPAWNO(), the defaults are to attempt all swap devices
and to store the swap file in the current directory when swapping to
disk.  init_SPAWNO() will set the swap file directory list to the first
of the following to have a non-NULL, non-empty value: the environment
variable SWAPDIR, the passed parameter, the environment variable TEMP,
and the environment variable TMP.  Note that init_SPAWNO is the only
function in the library which uses these environment variables.

After making the above change, recompile your existing code, but include
the SPAWNO library in the link step.  Note that SPAWNO does not support
the P_OVERLAY spawn type--any calls using that argument should be
replaced with the corresponding exec..() function.  If a SPAWNO function
is called with P_OVERLAY, it simply returns an error.

For backwards compatibility with previous versions of SPAWNO, and for
those who (for whatever reason) require the use of both the swapping and
standard spawn..() functions, there is a second set of functions which
take an explicit swap directory argument.  To use them, include the
header file SPAWNO.H.  Then use the functions provided in this
archive--spawnvo(), spawnlo(), spawnvpo(), etc--as you would the
corresponding spawnv(), spawnl(), etc, except replace the first argument
by a string containing the path where the swap file is to be stored.
Note that the swap file path is required even when swapping to XMS, EMS,
or plain extended memory, as SPAWNO will swap to disk anyway if there is
not enough memory available.

If you require the use of both the swapping and standard spawn..()
functions, you will need to run the NOREPLAC.BAT batch file to remove
the modules containing the replacements for the standard functions or
arrange the linker command line such that SPAWNx.LIB is listed after the
standard runtime library (for Turbo/Borland C users, the latter requires
a separate TLINK command, as TCC/BCC places any libraries specified on
the command line prior to the runtime library).	 Please do not run
NOREPLAC on your original copy of the libraries, as the process is
destructive and cannot be reversed.

The spawn?p??() functions search for both .COM and .EXE files in the
current directory and then in the pathed directories if no extension is
given, but use the specified extension if present.  If a full pathname
is given to those functions, only the specified directory is searched.
If both a path and an extension are given, only that specific file will
be loaded.  The other spawn..() functions check the current directory
only.  For all functions, if the specified filename does not contain an
extension, SPAWNO will try the exact name given and the name with .COM
and .EXE extensions. The extension-less name will be used if neither
.COM nor .EXE exist.  To force the use of the extensionless file even
if a .COM or .EXE with the same name exists in the same directory,
append a period, i.e. use "PROGRAM." rather than just "PROGRAM" as
the name.

When linking, you must include SPAWNx.LIB.  A sample TCC line would be

    tcc -mc <other-flags> sample spawnc.lib library.lib

This results in 208 to 288 bytes remaining in memory (depending on swap
type) while the spawned program executes.  However, if you want to keep
an interrupt hooked which might be invoked while spawned, you must set
__spawn_resident large enough that *all* code and data which could be
invoked by that interrupt is kept resident[1].	SPAWNO automatically
deactivates INT 23h and INT 24h and restores them before returning to
the caller unless __spawn_keepints is set to 1, so no extra work is
required if those two are the only interrupts hooked by the program.

----
[1] Due to the segment layout used by C compilers, this option is probably
    useful only when calling SPAWNO from assembly-language code (which can
    localize such code and data near the start of the executable) or a
    small program which uses a large amount of space in the far heap.


-----------------
ERROR CODES

SPAWNO will return errno = ENOMEM (_doserrno = 8) if there is insufficient
swap space available.


-----------------
ERROR MESSAGES

SPAWNO: stack too small, retrying
	SPAWNO did not correctly determine the stack requirements for
	the system on which it is running, but was able to determine
	that the specified minimum size is insufficient.  On the retry,
	the stack size is increased by one paragraph.  Since SPAWNO
	cannot always detect the problem, which would result in
	memory chain corruption, you should increase the value of
	__spawn_res_stack to prevent a recurrence of this error
	message.  For most systems, the default value of 4 paragraphs
	will be sufficient.

SWAP ERR
	The resident stub detected an error while trying to reload the
	main portion of the program and aborted.  This may be due to
	loading a TSR while swapped out or deleting the swap file.

SPAWNO: error reloading program, aborting
	The main portion of SPAWNO detected an error while attempting
	to restore the remainder of the program to memory.


-----------------
LIMITATIONS

After freeing all memory owned by the program except the initial (PSP)
memory block and the environment, at least 384 bytes of conventional
memory must be available.  SPAWNO uses this for its temporary stack.
This is of particular importance for the Turbo Pascal variant, because
setting the maximum heap size to the available memory or greater will
use up all RAM and prevent SPAWNO from allocating its temporary stack
unless memory is fragmented or there is DOS 5 high memory available.

SPAWNO may report insufficient memory even though the program to be
executed would fit with up to 600 bytes to spare, due to the fact that
part of the stack and all of the data used by DOS to start the program
may be overwritten after the child program starts executing.

Functions which pass an explicit environment attempt to allocate enough
memory to build the environment block which is passed to the DOS EXEC
function.  If neither malloc() nor a DOS memory allocation request are
successful, SPAWNO passes the original environment rather than the
specified environment.

As distributed, SPAWNO functions which do not take an explicit
environment pointer pass the calling program's original environment to
the child, rather than the current environment as modified by putenv().
You may recompile SPAWNO to pass the current environment (see
_SPAWNO.H); if you do so, the caveat discussed in the previous paragraph
will apply to all of the spawn..() functions.


-----------------
SUPPORT

Since I am not getting any money, I can't promise any support.	Those
who have purchased the complete source code will receive priority over
those who haven't, but even they will only receive support to the
extent that I have spare time....


-----------------
ACKNOWLEDGEMENTS

Thanks to Gene McManus for testing the Microsoft versions of SPAWNO 3.0
and 4.0.


-----------------
FUTURE PLANS

The next release will drop support for DOS 2.x (which is now over
eight years old) to reduce the code size and further reduce the size
of the resident stub.


-----------------
SPAWNO versus THE COMPETITION

Product:		SPAWNO		XSPAWN		SWAP
Version:		 4.13		 1.34		 1.0
Author:		     Ralf Brown	  Whitney Software  Marty Del Vecchio
Memory models:		tsmclh		tsmclh		 tsm
Supported DOS vers:    2.0-5.0	       2.1-5.0	      3.0-5.0
Code size [1]:	       4.3-5.9K        4.4-9K		 1.5K
Resident stub (bytes): 208-288	      1277+2*env     1.8K+env [2]
Direct replacement for
    spawn..():		 yes		 yes		  no
Use in existing code
    without changes:	 yes		  no		  no
Swap to disk:		 yes		 yes		 yes
Swap to EMS:		 yes		 yes		 yes
Swap to XMS:		 yes		  no		  no
Swap to INT 15h ext:	 yes		  no		  no
Multiple swap dirs:	 yes		 yes		  no
Automatic unique swap
    file naming:	 yes		 yes		  no
May leave interrupts
    hooked [3]:		 yes		  no		 yes
Swaps DOS5 high memory:	 yes		   ?		   ?
Free for any use:	 yes		 yes		 yes
Source included:       partial [4]	 yes		 yes

Notes:
[1] For both SPAWNO and XSPAWN, the amount added to the executable's
    size depends on which functions of the library are called and which
    of the additional C runtime library function that are called by
    SPAWNO/XSPAWN would have been included anyway.  SPAWNO's size may
    be reduced by removing one or more swap types; the savings are
    about 400 bytes per swap type (without EMS and non-XMS (INT 15h)
    swapping, SPAWNO would add as little as 3.4K to the executable).

[2] SWAP's resident size depends on the location of the object code
    within the executable.  The size reported here is the resident
    size when SWAP immediately follows the Turbo C 2.0 startup code.
    It will be larger in later versions of the Borland C compilers due
    to the increasing size of the startup code.

[3] For SPAWNO, enough of the program must be left in memory to keep all
    interrupt handlers resident.  XSPAWN has no provision for keeping
    an interrupt handler resident unless swapping is disabled; it does
    however permit selection whether a given interrupt handler will
    automatically be restored to its original value or pointed at an
    IRET instruction while swapped out.	 For SWAP, the swapper module
    must be linked in after all code and data which might be accessed
    by the interrupt handler(s).

[4] Full SPAWNO source code is available for licensing.  See ORDER.FRM for
    details.


-----------------
Functions:
	void init_SPAWNO(const char *swap_directories, int swap_types) ;

	/* replacements for the standard functions */
	int spawnv(int type, const char *name, const char **args) ;
	int spawnvp(int type, const char *name, const char **args) ;
	int spawnve(int type, const char *name, const char **args,
		    const char **env) ;
	int spawnvpe(int type, const char *name, const char **args,
		     const char **env) ;
	int spawnl(int type, const char *name, const char *argv0, ...) ;
	int spawnlp(int type, const char *name, const char *argv0, ...) ;
	int spawnle(int type, const char *name, const char *argv0, ...) ;
	int spawnlpe(int type, const char *name, const char *argv0, ...) ;
	int system(const char *command) ;
	/* Note: the above functions return -1 (error) if 'type' is not */
	/*	 P_WAIT	 */

	/* setup function */
	void init_SPAWNO(const char *overlay_path, int swap_types) ;
	/* setup swapping options for the compatibility functions above */

	/* SPAWNO-specific functions */
	int spawnvo(const char *overlay_path, const char *name,
		    const char **args) ;
	int spawnvpo(const char *overlay_path, const char *name,
		     const char **args) ;
	int spawnveo(const char *overlay_path, const char *name,
		     const char **args,const char **env) ;
	int spawnvpeo(const char *overlay_path, const char *name,
		     const char **args,const char **env) ;
	int spawnlo(const char *overlay_path, const char *name,
		     const char *argv0, ...) ;
	int spawnlpo(const char *overlay_path, const char *name,
		     const char *argv0, ...) ;
	int spawnleo(const char *overlay_path, const char *name,
		     const char *argv0, ...) ;
	int spawnlpeo(const char *overlay_path, const char *name,
		     const char *argv0, ...) ;
	int systemo(const char *overlay_path, const char *command) ;
	/* Note: the ..o() functions use only the current directory if */
	/*	 overlay_path is NULL; the only function which checks  */
	/*	 the environment variables SWAPDIR and TEMP is	       */
	/*	 init_SPAWNO(). 				       */

Global variables:
       char __spawn_xms ;
	    Specify whether to use XMS memory for swapping (if available).
	    0 = no, 1 = yes, default = 1
	    This variable is set by init_SPAWNO().
       char __spawn_ems ;
	    Specify whether to use EMS memory for swapping (if available).
	    0 = no, 1 = yes, default = 1
	    This variable is set by init_SPAWNO().
       char __spawn_ext ;  /* 0 = don't use non-XMS extended memory for swap */
	    Specify whether to use non-XMS extended memory (via INT 15h) for
	    swapping (if available).  0 = no, 1 = yes, default = 1
	    This variable is set by init_SPAWNO().
	    Note: SPAWNO should not be allowed to swap to extended memory if
	    running under a multitasker or task switcher, as other programs
	    would be able to grab the same memory used by SPAWNO to store the
	    swapped-out program.  For this reason, SPAWNO automatically
	    disables swapping to non-XMS extended memory if it detects that
	    TopView, DESQview, or any other TopView API-compatible multi-
	    tasker is active, or the DOS 5 task switcher is loaded, or
	    MS Windows 3 is running in real or standard mode (enhanced mode
	    is not readily detectable from a program, unfortunately).
       const char *pascal ___spawn_swap_dirs ;
	    Specify the list of directories in which to attempt to store
	    the swap file when swapping to disk.  The directories are
	    separated by semicolons just as they would be in the PATH
	    environment variable.  Default = NULL (same as ".": current
	    directory)
	    This variable is set by init_SPAWNO().
	    Note: SPAWNO will not swap to disk if this variable is set to an
	    empty string; if it is set to NULL, SPAWNO will use the default
	    directory list of ".".
       char __spawn_keepints ;
	    Specify whether to deactivate INT 23h and INT 24h handlers by
	    temporarily restoring the vectors stored in the PSP.
	    0 = no, nonzero = yes, default = 0
       char __spawn_swap_UMA ;
	    Specify whether to swap out memory blocks in the upper memory
	    area (640K-1M).  0 = no, 1 = yes, default = 1
	    Note: This option only has an effect under MSDOS 5.0 or higher
	    with the line DOS=UMB or DOS=HIGH,UMB in CONFIG.SYS.
       unsigned __spawn_resident ;
	    Specify the minimum number of paragraphs in the memory block
	    containing the PSP to keep resident while in the child program.
	    This value will be increased if necessary to be large enough to
	    hold the swapping code; it may also be increased slightly if it
	    causes the end of the shrunken PSP block to fall within a
	    specific section of SPAWNO's code.  You may force the entire
	    main block to stay in memory by setting this variable to 0xFFFF;
	    however, the environment and any additional memory blocks
	    allocated by the program will still be swapped out.  default = 0
	    Note: in addition to the PSP memory block, a small second block
	    is used for the stack needed by the swapping code (see below).
       unsigned __spawn_res_stack ;
	    Specify the minimum number of paragraphs of the stack to keep
	    resident while in the child program.  Default = 4, minimum = 2
	    (two paragraphs is only sufficient for bare DOS; TSRs which
	    hook INT 21h will increase the stack requirements, but four is
	    sufficient for most systems).  SPAWNO attempts to compute the
	    necessary stack size, but this variable allows the computed
	    value to be overridden if necessary.

External functions called by SPAWNO:
	malloc()   \ only when passing an array of environment strings
	free()	   /

External variables referenced by SPAWNO:
	int errno ;
	int _doserrno ;
	unsigned int _psp ;
	char **environ ;  (only when passing an array of environment strings)

Other:
	This version of SPAWNO overwrites the PSP, so the commandline
	will be lost unless it was copied before the first spawn().


-----------------
Functions (Turbo Pascal):
	init_SPAWNO(swap_dirs : string ; swap_types : integer ;
		    min_resident : integer ; resident_stack : integer) ;
	spawn(program_name : string ; arguments : string ;
	      envseg : integer) : integer ;

Global Variables (Turbo Pascal):
	spawno_error : integer ;   (error code when spawn() returns -1)


-----------------
Send comments, bug reports, etc. to

     Internet: ralf+@cs.cmu.edu
     Fidonet:  Ralf Brown 1:129/26.1 (or post a message to me on DR_DEBUG--I
				     have to route netmail outside Zone 1
				     via Internet -> Fidonet gateways, which
				     is not always reliable)
or
     Ralf Brown 		   (this address will be valid until
     813 Copeland Way, Suite 26     at least November 1, 1993)
     Pittsburgh, PA 15232