diff options
Diffstat (limited to 'dmake/msdos/spawn.c')
-rw-r--r-- | dmake/msdos/spawn.c | 415 |
1 files changed, 0 insertions, 415 deletions
diff --git a/dmake/msdos/spawn.c b/dmake/msdos/spawn.c deleted file mode 100644 index bc6bb4c64783..000000000000 --- 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) ); -} |