[comp.lang.c] No fork

brian@bradley.UUCP (07/18/88)

  I'm considering writing a shell for the IBM PC... I'm using Microsoft
C 5.0. This version does not provide a fork() function. Instead, they
provide a set of functions called spawn, which are similar to exec.
That is, there is a spawnve(), spawnl(), etc. Their effect is similar
to a fork(), with an exec() in the child process, and a wait() in the
parent process.

  Unfortunatley, to do I/O redirection, I need to put some code between
the fork() and the exec() in the child process. Since there is not
really a fork(), this isn't possible.

  Of course, I could do a system() with my whole command line, but this
is not a solution because 1) there is no way to pass the environment
in this case, 2) I would have to somehow translate my shell's syntax
back to MS-DOS COMMAND.COM syntax, which may not be possible, and
3) the system() function probaly will load in another copy of COMMAND.COM,
and my shell will be cutting into avaible memory at it is.

  So what I need is a way to run a child process, with (possibly)
redirected input and/or output, passing the environment, and having the
parent process resume execution after the child process completes.
Does anyone have any clues as to how this can be done?

...............................................................................

  When the going gets weird, the weird turn pro.

  Brian Michael Wendt       UUCP: {cepu,ihnp4,uiucdcs,noao}!bradley!brian
  Bradley University        ARPA: cepu!bradley!brian@seas.ucla.edu
  (309) 677-2230            ICBM: 40 40' N  89 34' W

platt@emory.uucp (Dan Platt) (07/21/88)

In article <9900005@bradley> brian@bradley.UUCP writes:
>
>  I'm considering writing a shell for the IBM PC... I'm using Microsoft
>C 5.0. This version does not provide a fork() function. Instead, they
>provide a set of functions called spawn, which are similar to exec.
>That is, there is a spawnve(), spawnl(), etc. ...

There is no fork because  DOS doesn't support multitasking.  What
DOS will support is an interupt driven suspension of one routine and
activation of another routine (this is demonstrated in the DOS print
command), or for a software suspension of one routine for a temporary
execution of another one (until memory runs out) which is what spawnve()
etc. do.

>  Unfortunatley, to do I/O redirection, I need to put some code between
>the fork() and the exec() in the child process. Since there is not
>really a fork(), this isn't possible.

You want PIPEs.  Well, there aren't any real pipes in DOS (unlike UNIX)
since there is no multitasking.  However, there is re-direction and
DOS does support a pseudo-PIPE.  The way DOS does it is to have one
process direct stdout to a temporary file PIPE*.* which is then directed
to stdin of the next process.  Multiple pipes are possible, but each
process has to be able to run sequentially; they can't be written to
run concurrently with the process.  If you really want to sweat, you could
make a hybrid where an agreed upon temporary file was used as the input,
and have the secondary process execute a little on each clock interupt...

>
>  Of course, I could do a system() with my whole command line, but this
>is not a solution because 1) there is no way to pass the environment
>in this case, 2) I would have to somehow translate my shell's syntax
>back to MS-DOS COMMAND.COM syntax, which may not be possible, and
>3) the system() function probaly will load in another copy of COMMAND.COM,
>and my shell will be cutting into avaible memory at it is.
>
>  So what I need is a way to run a child process, with (possibly)
>redirected input and/or output, passing the environment, and having the
>parent process resume execution after the child process completes.
>Does anyone have any clues as to how this can be done?
>

The only way I can see you doing it is using spawnv*() with a
temporary file used to pass the information.  You may need to 
tolerate loaded versions of COMMAND.COM.  If you are only loading
one process at a time on top of your shell, this shouldn't be too
much of a problem unless your shell is large.  You may also want
to consider using exemod on your shell program to reduce the execution
space size (your shell will take up a lot more space than command.com
unless you do this).  Most of the spawn*() and system() function calls
use DOS BIOS function calls anyway.

This is one reason to 1) Go to UNIX systems, or 2) Go to OS/2 (if it
ever flies)...


Dan Platt

brian@bradley.UUCP (07/21/88)

  My thanks to everyone who responded to my question on doing
I/O redirection for a child process without disturbing the
parent processes I/O under Microsoft C 5.0.

  Apparently the only way to do it is by using dup() to copy
stdin/stdout/stderr before starting the child process, and
dup2() to restore them afterwards.

  The only drawback is that Microsoft C already reserves 5 fildes.
If I dup() three, that only leaves 12 for the child process...

...............................................................................

  When the going gets weird, the weird turn pro.

  Brian Michael Wendt       UUCP: {cepu,ihnp4,uiucdcs,noao}!bradley!brian
  Bradley University        ARPA: cepu!bradley!brian@seas.ucla.edu
  (309) 677-2230            ICBM: 40 40' N  89 34' W

daveh@marob.MASA.COM (Dave Hammond) (07/22/88)

In article <3083@emory.uucp> platt@emory.UUCP (Dan Platt) writes:
>In article <9900005@bradley> brian@bradley.UUCP writes:
>>
>>  I'm considering writing a shell for the IBM PC... I'm using Microsoft
>>C 5.0...................[stuff deleted]................................
>
>>  Unfortunatley, to do I/O redirection.................................
>
>You want PIPEs.  Well, there aren't any real pipes in DOS (unlike UNIX)
>since there is no multitasking.  However, there is re-direction and
>DOS does support a pseudo-PIPE..........................................
>

May I recommend an excellent book (and accompanying source code diskette):

   ``On Command: Writing a Unix-like Shell for MS-DOS'', by Allen Holub

Published by M&T Publishing, 800-533-4372

The book explains subprocess spawning, i/o redirection, piping, environ
management and history substitution in detail. The optional source diskette
contains a very useable MS-DOS shell, as well.

>This is one reason to 1) Go to UNIX systems, or 2) Go to OS/2 (if it...

OPINION:
UNIX yes! OS/2... When UNIX (on a '386) can provide DOS file compatibility,
DOS program execution, X-Windows, Ethernet, TCP/IP, and hundreds of utilities,
what's the point of an OS/2 (barring discussions on bureaucratic comfort
with Big Blue).

Dave Hammond
UUCP:   {uunet|rutgers|spl1|...}!hombre!marob!daveh
-----------------------------------------------------

rwhite@nusdhub.UUCP (Robert C. White Jr.) (07/23/88)

in article <3083@emory.uucp>, platt@emory.uucp (Dan Platt) says:
> In article <9900005@bradley> brian@bradley.UUCP writes:
>>  Of course, I could do a system() with my whole command line, but this
>>is not a solution because 1) there is no way to pass the environment
>>in this case, 2) I would have to somehow translate my shell's syntax
>>back to MS-DOS COMMAND.COM syntax, which may not be possible, and
>>3) the system() function probaly will load in another copy of COMMAND.COM,
>>and my shell will be cutting into avaible memory at it is.

> The only way I can see you doing it is using spawnv*() with a
> temporary file used to pass the information.  You may need to 
> tolerate loaded versions of COMMAND.COM.  If you are only loading
> one process at a time on top of your shell, this shouldn't be to
> much of a problem unless your shell is large. 

I think you are missing one small point here.  "COMMAND.COM" is the 
MS-DOS shell.  If you write something to replace it, you must
*include* a loader of you own in the text of your shell.  If you
look up the dos function call which loads programs, you will find
that it invokes the shell (e.g. command.com) to do the loading.
If you write your own true shell, it must contain a assembly
or such which will act as the loader from then on.  Once you
have doen this, you may simply decide that the loade will remain
in low memory all the time, and never worry about loading the
loader again.

All this is you own choice.  If you only wish to write a simple
command editor/environment that is your own get out, but it is
not a "MS-DOS shell"

Put simply: If you write a _true_ shell, you will have the procedures
to do whatever you want durring loading locally available to your shell.
At that point spawn() and exec() from the Microsoft C compiler become
irrevelant.

Rob.

Ralf.Brown@B.GP.CS.CMU.EDU (07/24/88)

In article <1112@nusdhub.UUCP>, rwhite@nusdhub.UUCP (Robert C. White Jr.) writes:
}I think you are missing one small point here.  "COMMAND.COM" is the 
}MS-DOS shell.  If you write something to replace it, you must
}*include* a loader of you own in the text of your shell.  If you
}look up the dos function call which loads programs, you will find
}that it invokes the shell (e.g. command.com) to do the loading.

That is only true of DOS 1.x and PC-DOS 2.x.  MS-DOS 2.x and MS/PC-DOS 3.x
have the loader in the kernel.  PC-DOS 2.x doesn't invoke COMMAND.COM,
it just happens that COMMAND.COM intercepts INT 21h and branches to a second 
transient portion containing the 1K or so of code to do the loading.
That's why PC-DOS 2.x requires COMMAND.COM to be present, as the loader code
may have to be read in from the COMMAND.COM file on disk.

--
UUCP: {ucbvax,harvard}!cs.cmu.edu!ralf -=-=-=- Voice: (412) 268-3053 (school)
ARPA: ralf@cs.cmu.edu  BIT: ralf%cs.cmu.edu@CMUCCVMA  FIDO: Ralf Brown 1:129/31
Disclaimer? I     |Ducharm's Axiom:  If you view your problem closely enough
claimed something?|   you will recognize yourself as part of the problem.