Calling the MS-DOS EXEC Service from within a TSR Application

ID Number: Q39536

3.x 4.00 4.01

MS-DOS

Question:

We are writing a terminate-and-stay-resident (TSR) software

application and would like to use the MS-DOS EXEC function (MS-DOS

Interrupt 21H, Function 4BH), but we are not able to get it to work.

Will this function work from within a TSR application? In other words,

is there any difference between executing a child process by using the

EXEC service from a TSR application as opposed to a normal

application?

Response:

There are many considerations for using the MS-DOS EXEC function from

a TSR application. This is not a simple issue. We have to make the

following assumptions:

1. You have a TSR application residing in memory that wants to call

the MS-DOS EXEC function to execute another child application.

2. The TSR is written in assembly language. Working from such a

theoretical base, we don't have to worry about idiosyncrasies and

abstractions of the run-time library functions of high-level

languages (e.g. how the Microsoft C Compiler is handling its spawn,

EXEC, or system functions). For applications working this close to

the system, it's a good idea to program in assembly language

anyway, since you have to be very familiar with every machine

instruction that you make.

3. Your program is intelligent enough to know when it can and cannot

issue MS-DOS services--reentrancy problems will bring a TSR

application to a quick halt if the program is not careful. The

application must be able to detect when MS-DOS is in a critical

section and must refrain from issuing MS-DOS calls; otherwise, the

application will have problems. One of the best sources of

information on how to do this is article 11 of "The MS-DOS

Encyclopedia."

4. The program is running under the proper environment (i.e., PSP or

PHP). This, like the reentrancy issues, is described in detail in

article 11 of "The MS-DOS Encyclopedia." Without this, there is a

good chance that MS-DOS will be confused as to who is issuing

MS-DOS calls: the foreground application or your TSR application.

At this point, we can hopefully assume that we have a "well-behaved"

TSR application that knows when to attempt calling MS-DOS, and how to

save and restore its environment to avoid any confusion with the

foreground application; also, we don't have to be concerned with the

limitations of an HLL (High Level Language) run-time library.

These, of course, are a lot of limitations.

From this point, your TSR should be able to safely call the MS-DOS

EXEC function.

Complications

At this point, your TSR application will most likely run into problems

when it is not able to find enough memory to EXEC a program. A TSR is

almost always at the mercy of the current foreground application's

environment, and how the environment is controlling the system. These

programs often allocate the largest chunk of free memory when they are

invoked, and they do not leave you enough to use for your EXEC. An

example of this is COMMAND.COM, which allocates all available memory

so that it can place its transient portion at the top of memory. Most

.COM files allocate all of memory; the only way that you could have

free space is if the program issues MS-DOS Interrupt 21H Service 4AH,

SETBLOCK. This would free up some of the memory it has allocated for

this process, perhaps giving you enough room to EXEC your program.

Many .EXE files have this allocation size set to a smaller value; this

field is in the EXE header.

The result of all of this careful planning and coding is that you may

be able to EXEC a program, depending on the current application

running, how much memory it has allocated, and how much memory is

free. Thus, writing a TSR that uses EXEC is possible if it is done

carefully, but it is dependent on the foreground application. That is,

the success of the EXEC is based on the currently running program and

how much memory is available (which is largely a factor of the

currently running program).

Another example of how a TSR application may foul up the foreground

application is if it does something such as allocating memory to

perform an EXEC operation. If the foreground application has freed up

enough memory to allow you to work with, it very well may be that the

foreground application is planning on using this memory for its own

purposes, for example, EXECing its own child process. It will not

expect a background TSR application to allocate this memory and use it

for its own use. This may have unpredictable results in the operation

of the foreground application.

MS-DOS is a single-tasking environment that does not have the proper

support for multiple processes. Instead of the operating system

performing time slicing between processes, more than one process is

able to occupy memory only by hooking onto interrupts and interrupting

another application. How successful a background application is at

interrupting this foreground application is almost entirely up to the

background application, and MS-DOS has no control over this. Once the

background application is in control of the system, it may not be able

to perform what it wants, since it is at the mercy of the current

environment in which the foreground application is running. Writing

TSR applications is a haphazard and risky thing to do.