summaryrefslogtreecommitdiff
path: root/dmake/msdos/spawn.c
diff options
context:
space:
mode:
Diffstat (limited to 'dmake/msdos/spawn.c')
-rw-r--r--dmake/msdos/spawn.c415
1 files changed, 0 insertions, 415 deletions
diff --git a/dmake/msdos/spawn.c b/dmake/msdos/spawn.c
deleted file mode 100644
index c5e995565..000000000
--- a/dmake/msdos/spawn.c
+++ /dev/null
@@ -1,415 +0,0 @@
-/* RCS $Id: spawn.c,v 1.3 2007-10-15 15:43:28 ihi Exp $
---
--- SYNOPSIS
--- Spawnvpe code to emulate spawnvpe call common to DOS compilers.
---
--- DESCRIPTION
--- This implementation is further integrated into dmake in that it
--- determines the program to execute and if it's extension is either
--- .bat or .ksh it executes it using the appropriate shell based on the
--- setting of .MKSARGS. If .MKSARGS is set then in addition
--- to the command tail getting built the arguments are also passed in the
--- environment pursuant to the published MKS argument passing conventions.
--- If the variable Swap_on_exec is set and the DOS OS supports it
--- then the dmake executable image is swapped to secondary storage prior
--- to running the child process. This is requested by setting the
--- appropriate flag in the call to exec.
---
--- This and the exec.asm routine are derived from work that was supplied
--- to me by Kent Williams (williams@umaxc.weeg.uiowa.edu) and by
--- Len Reed, (..!gatech!holos0!lbr or holos0!lbr@gatech.edu., Holos
--- Software, Inc., Tucker, Ga.). I sincerely acknowledge their help since
--- their Turbo C, and MSC 6.0 code lead directly to this combined
--- swapping exec that hopefully works with either compiler in all memory
--- models.
---
--- AUTHOR
--- Dennis Vadura, dvadura@dmake.wticorp.com
---
--- WWW
--- http://dmake.wticorp.com/
---
--- COPYRIGHT
--- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
---
--- This program is NOT free software; you can redistribute it and/or
--- modify it under the terms of the Software License Agreement Provided
--- in the file <distribution-root>/readme/license.txt.
---
--- LOG
--- Use cvs log to obtain detailed change logs.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#if defined(_MSC_VER) && _MSC_VER >= 600
- /* Ignore the MSC 6.0 library's "const"-riddled prototype
- for spawnvpe.
- */
-# define spawnvpe _ignore_msc_spawnvpe
-# include <process.h>
-# undef spawnvpe
- int spawnvpe(int, char *, char **, char **);
-#else
-# include <process.h>
-#endif
-
-#include <dos.h>
-#include <errno.h>
-#include <string.h>
-#include <alloc.h>
-#include <fcntl.h>
-#include "extern.h"
-#include "dosdta.h"
-#include "exec.h"
-#include "sysintf.h"
-
-extern int Interrupted;
-
-/* variables and functions local to this file */
-static char *_findexec ANSI((char *, int *));
-static char **_getpath ANSI(());
-static char far *_dos_alloc ANSI((uint16));
-
-static uint16 _swap_mask;
-static int _mks_args;
-static char dot_com[] = ".COM",
- dot_exe[] = ".EXE",
- dot_bat[] = ".BAT",
- dot_ksh[] = ".KSH";
-
-/* Kinds of executables */
-#define SCR 1
-#define COM 2
-#define EXE 4
-#define ALL (SCR|COM|EXE)
-
-/* How to make a long pointer */
-#define CF(x) (char far *)x
-
-/* Make sure we know how to get a segment out of a long pointer */
-#ifndef FP_SEG
-#define FP_SEG(fp) ((unsigned)((unsigned long)(fp) >> 16))
-#endif
-
-iz81252 changed the parameters for Pack_argv() but this file did not get fixed!
-PUBLIC int
-spawnvpe(mode, program, av, ep)/*
-=================================
- Spawn a process using an environment and a vector of arguments.
- The code computes a new environment, puts the MKS arguments into
- it if need be, and calls the appropriate routines to search the
- path and to invoke the process. */
-int mode;
-char *program;
-char **av;
-char **ep;
-{
- char pwd[PATH_MAX+1];
- char **envp = ep; /* Cause we are going to mess with it. */
- char **argv = av; /* Same with this one. */
- char cmdtail[129];
- char far *environment;
- char *tail;
- char *swptmp;
- unsigned int envsize;
- unsigned int cmdsize;
- int cmdtailen;
- int i;
- int doswap;
-
- /* First check to see if we can find the program to execute this way we
- * don't alloc the environment and other such stuff prior to figuring out
- * we don't know how to run the program. */
-find_program:
- if((program = _findexec(program, &i)) == NIL(char)) {
- errno = ENOENT;
- return( -1 );
- }
-
- /* i is set to TRUE in _findexec if the exec is a shell
- * script (either .BAT or .KSH file), returns FALSE for all others. */
- if( i && !Packed_shell ) {
- /* Restore the spaces into the command line that were erased by
- * the previous call to Pack_argv. This enables us to repack the
- * command as a shell command using Pack_argv again. */
- for( i=0; argv[i] != NIL(char); i++ ) {
- int x = strlen(argv[i]);
- if( argv[i+1] != NIL(char) ) argv[i][x] = ' ';
- }
-
- argv = Pack_argv( FALSE, TRUE, *argv );
- Packed_shell = TRUE; /* Previous call implies shell = TRUE. */
-
- /* Go and find the program again, I hate goto's but it seems silly to
- * use tail recursion here just for aesthetic purity. */
- program = *argv;
- goto find_program;
- }
-
- /* Compute size of *argv vector for passing as MKS style arguments */
- cmdsize = strlen(*argv)+2;
-
- /* So we have decided on a program to run, therefore pack the command tail
- * and build the environment to pass to the exec code. This loop packs the
- * DOS command tail, and computes the size of all arguments for the MKS
- * argument passing convention. Note that we reserve one less byte in the
- * command tail if we are not using MKS style argument passing.
- *
- * Make sure the command tail contains at leat a space. Some commands fail
- * to work if the command tail is only a \r, STUPID DOS! */
- cmdtailen = ((_mks_args = ((Glob_attr & A_MKSARGS) != 0)) != 0)?3:2;
- tail = cmdtail+1;
-
- if( argv[1] != NIL(char) )
- for( i=1; argv[i] != NIL(char); i++ ) {
- int arglen = strlen(argv[i]);
-
- cmdsize += arglen+2; /* Compute all args size for MKS */
-
- if( (cmdtailen += arglen+1) <= 128 ) {
- register char *p = argv[i];
- tail[-1] = ' '; /* put in the space */
- while( *tail++ = *p++ ); /* put in the arg */
- }
- else if( !_mks_args ) {
- errno = E2BIG; /* unless its MKS exit if arglist */
- return(-1); /* is too long. */
- }
- }
- else
- *tail++ = ' ';
-
- /* Finish the command tail set up, placing the length in the first byte,
- * and the \r \n \0 at the end for DOS, MKS and us respectively. */
- *cmdtail = tail-cmdtail-2;
- tail[-1] = '\r';
- if( _mks_args ) *tail++ = '\n';
- *tail = '\0';
-
- /* Compute size of environment, skipping any MKS arguments passed in our
- * environment */
- for(; *envp && **envp == '~'; envp++ );
- for(i=0, envsize=_mks_args?cmdsize:1; envp[i] != NIL(char); i++ )
- envsize += strlen(envp[i]) + 1;
-
- /* Check the DOS version number here. If it is < 3.0 then we don't
- * even want to think about executing the swapping code. Permanently
- * set swap to 0. */
- doswap = (_osmajor < 3) ? 0 : Swap_on_exec;
-
- /* Set up temporary file for swapping */
- swptmp = doswap?tempnam(NIL(char),"mk"):"";
-
- /* Allocate an appropriate sized environment block and align it on a
- * paragraph boundary. It will later get copied to an appropriately low
- * place in the executable image so that when we swap out the environment
- * is still present. Use
- * _dos_alloc
- * to allocate the environment segment. The segment is freed by the call
- * to exec. */
- environment = _dos_alloc( envsize = ((envsize+16)>>4) );
- *environment = '\0';
-
- /* First copy the arguments preceeded by ~ character if we are using
- * MKS style argument passing */
- if( _mks_args )
- for(; *argv; argv++) {
- register char *p = *argv;
-
- *environment++ = '~';
- while( *environment++ = *p++ ); /* Far dest, poss near ptr */
- }
-
- /* Now stick in the current evironment vectors. */
- for(; *envp; envp++) {
- register char *p = *envp;
- while( *environment++ = *p++ ); /* Far dest, poss near ptr */
- }
-
- /* Clear the interrupted flag, and exec */
- Interrupted = 0;
-
- /* Preserve the current working directory accross a spawn call
- * DOS is brain dead about this. This way we have some hope of cleaning
- * up the swapping tempfiles after we return. */
- strcpy(pwd,Get_current_dir());
- i = exec(doswap,CF(program),CF(cmdtail),FP_SEG(environment),CF(swptmp));
- Set_dir(pwd);
-
- /* Now free the temporary file name */
- if( doswap ) FREE(swptmp);
-
- /* If swap was interrupted then quit properly from dmake. */
- if( Interrupted ) Quit();
-
- return(i);
-}
-
-
-PUBLIC void
-Hook_std_writes( file )
-char *file;
-{
- if( file!= NIL(char) ) {
- int mode = O_BINARY | O_WRONLY | O_CREAT | O_TRUNC;
- int handle;
-
- if (*file == '+') {
- ++file; /* -F +file means append to file */
- mode = O_BINARY | O_WRONLY | O_CREAT | O_APPEND;
- }
- handle = open(file, mode, S_IREAD | S_IWRITE);
- if (handle < 0) {
- Fatal( "Could not open -F file");
- }
- (void) lseek(handle, 0L, SEEK_END);
- do_hook_std_writes(handle);
- }
- else
- do_unhook_std_writes();
-}
-
-
-/*
-** _findexec finds executables on the path.
-** Note that it is pretty simple to add support for other executable types
-** shell scripts, etc.
-**
-** This follows the command.com behavior very closely.
-*/
-static char *
-_findexec( s, is_shell )/*
-==========================
- Cloned closely from code provided by Kent Williams. Stripped his down to
- a reduced search since dmake doesn't need to recompute the PATH vector
- each time it does the search since it cannot alter the path vector once
- it begins to make recipes. Also modified it to use findfirst and findnext
- as provided for dirlib package that I got off the net. */
-char *s;
-int *is_shell;
-{
- unsigned found_flags;
- char **pathv = NIL(char *);
- char *ext = NIL(char);
- char *buf = NIL(char);
- char *p[2];
- char *dot_scr;
- char *dot;
-
- p[0] = ""; p[1] = NIL(char);
- if( strchr("./\\", *s) || s[1] == ':' )
- pathv = p;
- else if( (pathv = _getpath()) == NIL(char *) )
- return( NIL(char) );
-
- /* Compute the extension we need if any. */
- if( (dot = strrchr(s,'.')) != NIL(char) &&
- dot > strrchr(s,'/') && dot > strrchr(s,'\\') )
- ext = dot+1;
-
- dot_scr = _mks_args ? dot_ksh : dot_bat;
- *is_shell = FALSE;
-
- for( found_flags = 0; *pathv && !found_flags; pathv++ ) {
- DTA dta;
-
- if( !ext ) {
- char *name;
- buf = Build_path( *pathv, name=DmStrJoin(s, ".???", -1, FALSE) );
- FREE(name);
- }
- else
- buf = Build_path( *pathv, s );
-
- if( findfirst((char *)strupr(buf), &dta) != NIL(DTA) ) {
- if( !ext ) {
- char *dot;
-
- /* search order is .com .exe (.ksh || .bat)
- * there has to be a '.' */
- do {
- dot = strrchr(dta.name,'.');
- if(0 == strcmp(dot,dot_com))
- found_flags |= COM;
- else if(0 == strcmp(dot,dot_exe))
- found_flags |= EXE;
- else if( 0 == strcmp(dot,dot_scr) )
- found_flags |= SCR;
- } while( found_flags != ALL && findnext(&dta) != NIL(DTA) );
-
- if(found_flags & COM) ext = dot_com;
- else if(found_flags & EXE) ext = dot_exe;
- else if(found_flags & SCR) {
- ext = dot_scr;
- *is_shell = TRUE;
- }
-
- if( found_flags ) {
- char *name;
- buf = Build_path( *pathv, name=DmStrJoin(s,ext,-1,FALSE) );
- FREE(name);
- strupr(buf);
- }
- }
- else
- found_flags++;
- }
- }
-
- return( found_flags ? buf : NIL(char) );
-}
-
-
-/*
-** getpath turns the DOS path into a char *vector, It is gotten and
-** transformed only once since dmake can't modify the value of PATH while
-** it is making targets.
-*/
-static char **
-_getpath()
-{
- static char **dir = NIL(char *);
- register char *p;
-
- if( !dir ) {
- register char *t;
- int i;
- char *semi = NIL(char);
-
- if( (p = getenv("PATH")) == NIL(char) ) p = "";
- for( i=1, t=p; *t; t++ ) if( *t == ';' ) i++;
-
- TALLOC(dir, i+1, char *);
- p = DmStrDup(p);
-
- for( i=0; p; p = semi ? (semi+1):NIL(char),i++ ){
- if( (semi = strchr(p,';')) != NIL(char) ) *semi = '\0';
- dir[i] = p;
- }
- dir[i]=NIL(char);
- }
-
- return( dir );
-}
-
-
-static char far *
-_dos_alloc( size )/*
-====================
- This routine allocates size paragraphs from DOS. It changes the memory
- allocation strategy to allocate from the tail and then changes it back.
- to using first fit. */
-uint16 size;
-{
- union REGS r;
-
- r.h.ah = 0x48;
- r.x.bx = size;
-
- intdos( &r, &r );
- if( r.x.cflag ) No_ram();
-
- return( (char far *) MK_FP(r.x.ax, 0) );
-}