/*****************************************************************************

 Replacement WINSTUB.EXE for windows apps. This stub will start windows and 
 the application simply by typing the application's name at the DOS prompt.
 It will also output a message to your users when they close down windows.
 The message is pointed to by 'glprnpszExit', appended to the end of this 
 string is the name of the app in lower case with the first character in 
 upper case.

 pr = private
 au = auto
 st = static

 bl = block
 gl = global
 fi = pr = file

 compile and link line - uses C6 W4 and either real or implict real lib.

 cl -AS -W[4,3] -c stub.c
 link stub,,,slibce[r],nul

 written by Peter Morris. Compuserve ID 100016,2751

*****************************************************************************/

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<memory.h>
#include<ctype.h>

#define private static

#define SPACE (char)0x0020  /* hex for ASCII space char */

void *vpZmalloc(int);                     

char *npsAddString(char *,char const * const,int);    

char *npszAddNULL(char *pString);

void vStartWinAndApp(char const * const,char const * const);

char const * const npszAppNameFirstUpper(char * const);

int main(int,char **);

private char const * const glprnpszTrying="Trying to start Windows and";
private char const * const glprnpszWindows="WIN";
private char *glprnpszExitString="Next time remember to run Windows "
                                 "before running";


/*****************************************************************************

 malloc memory 'space' initialised.

*****************************************************************************/

void *vpZmalloc(int aublnNumbytes)
{
   auto void *aublvpMem;

   aublvpMem=(void *)malloc(aublnNumbytes);
   memset(aublvpMem,SPACE,aublnNumbytes);

   return aublvpMem;
}





/*****************************************************************************

 adds a string pointed to by npsSourceString to a buufer pointed to by
 npsDest, copies nSourceLength bytes over then returns the pointer npsDest
 incremented so as to point over a space character

*****************************************************************************/

char *npsAddString(char *npsDest,char const * const npsSourceString,int nSourceLength)
{
   strncpy(npsDest,npsSourceString,nSourceLength);
   npsDest+=strlen(npsSourceString);

   return ++npsDest;
}





/*****************************************************************************

 NULL terminates a string. char to set to null is given in npsString-1

*****************************************************************************/
char *npszAddNULL(char *npsString)
{
   *(npsString-1)=(char)'\0';
   return npsString;
}





/*****************************************************************************

 starts windows and the app, this is pointed to by npszAppString and we use
 a system call to do it. if this fails we call frintf() to report the error
 else we call, when windows has shut down, fprintf with a message saying 
 what ever you like

*****************************************************************************/
void vStartWinandApp(char const * const npszAppString,char const * const npszArg0)
{
   auto char const * const aublszString=npszAppNameFirstUpper((char * const)npszArg0); 

   fprintf(stdout,"%s %s\n\n",glprnpszTrying,aublszString); 

   if(system(npszAppString)!=0)
      fprintf(stderr,"Error executing - %s, errno=%d\n",npszAppString,errno);
   else
      fprintf(stdout,"%s %s",glprnpszExitString,aublszString);
}






/*****************************************************************************

 capitalises the first char of our app's name and returns a pointer to it

*****************************************************************************/
char const * const npszAppNameFirstUpper(char * const npszAppName)
{
   auto char *aublnpszString;

   aublnpszString=strrchr(npszAppName,(int)'\\');
   aublnpszString++;
   strlwr(aublnpszString);
   *aublnpszString=(char)toascii((int)*aublnpszString);
   *aublnpszString=(char)toupper((int)*aublnpszString);

   return aublnpszString;
}





/*****************************************************************************

 main - works out how much memory is in the argv array of char pointers as
 strings plus 'WIN' plus all the spaces and a NULL terminator. calls 
 vpZmalloc to allocate the memory then adds the strings 'WIN' and argv strings
 to it. adds a null to the end of it and uuper cases it than causes windows
 to start with the app and arguments passed in lpszCmdLine to the windows
 app. finally it frees the memory.

*****************************************************************************/
int main(int argc,char **argv)
{
   auto int   aublnStrlen;
   auto int   aublnLoop;
   auto void *aublvpMem;
   auto char *aublnpszChar;

   for(aublnLoop=aublnStrlen=0;aublnLoop<argc;aublnLoop++)
      aublnStrlen+=strlen(*(argv+aublnLoop));
   aublnStrlen+=argc;
   aublnStrlen+=strlen(glprnpszWindows);
   aublnStrlen++;

   aublvpMem=vpZmalloc(aublnStrlen);
   
   if(aublvpMem)
   {
      aublnpszChar=(char *)aublvpMem;
      aublnpszChar=npsAddString(aublnpszChar,glprnpszWindows,strlen(glprnpszWindows));

      for(aublnLoop=0;aublnLoop<argc;aublnLoop++)
         aublnpszChar=npsAddString(aublnpszChar,(char const * const)*(argv+aublnLoop),strlen(*(argv+aublnLoop)));

      strupr(npszAddNULL(aublnpszChar));
      vStartWinandApp(aublvpMem,*argv);
      free(aublvpMem);
      return 0;
   }  
   else
   {
      fprintf(stderr,"Error\n\n");
      return 1;
   }
}



                    /************* EOF **************/
