home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wfdos.zip / WFDOS-S.C < prev    next >
Text File  |  1995-04-15  |  17KB  |  380 lines

  1. /*┌─ WFDOS-S.C ──────────────────────────────────────────────────────────────────┐*/
  2. /*│ WFDOS - Invoke DOS program in background mode from IBM WorkFrame/2.          │*/
  3. /*│                                                                              │*/
  4. /*│ Copyright:                                                                   │*/
  5. /*│ ▀▀▀▀▀▀▀▀▀▀                                                                   │*/
  6. /*│ (c) Copyright Per Jessen, 1994.                                              │*/
  7. /*│ Permission is granted to any individual or institution to use, copy, or      │*/
  8. /*│ redistribute this software so long as all of the original files are included │*/
  9. /*│ unmodified, that it is not sold for profit, and that this copyright notice   │*/
  10. /*│ is retained.                                                                 │*/
  11. /*│                                                                              │*/
  12. /*│ Disclaimer:                                                                  │*/
  13. /*│ ▀▀▀▀▀▀▀▀▀▀▀                                                                  │*/
  14. /*│ The code is provided on an "AS IS" basis without any warranty of any kind.   │*/
  15. /*│ The author shall not be liable for any damages arising out of your use of    │*/
  16. /*│ this code, even if he has been advised of the possibility of such damages.   │*/
  17. /*└──────────────────────────────────────────────────────────────────────────────┘*/
  18. /*┌──────────────────────────────────────────────────────────────────────────────┐*/
  19. /*│ The purpose of this package is to re-direct the output from a background     │*/
  20. /*│ DOS-session from the screen to the Monitor Window in the IBM Workframe/2.    │*/
  21. /*│ This enables a transparent integration of DOS-tools, such as language pro-   │*/
  22. /*│ cessors etc., in the Workframe/2.                                            │*/
  23. /*│ Briefly, the Server (WFDOS-S.EXE) sets up a named pipe, and passes it on to  │*/
  24. /*│ the Client (WFDOS-C.EXE), which is then started in the DOS-environment.      │*/
  25. /*│ When the pipe is established, the Server provides the Client with a program- │*/
  26. /*│ name and a list of arguments. The Client will then redirect the normal std-  │*/
  27. /*│ out and stderr streams to the pipe, before transferring control to the pro-  │*/
  28. /*│ gram to be executed. Any output from this program is now effectively routed  │*/
  29. /*│ to the Server, which will display it in the Monitor Window.                  │*/
  30. /*│                                                                              │*/
  31. /*│ Arguments:                                                                   │*/
  32. /*│                                                                              │*/
  33. /*│                                                                              │*/
  34. /*│   ───── WFDOS-S ────┬─────┬─────┬───────────┬─────┬────────────┬──────      │*/
  35. /*│                     └─ ? ─┘     └─ /m<lvl> ─┘     └─ /c<path> ─┘             │*/
  36. /*│                                                                              │*/
  37. /*│   ─────────────────────────┬────────────────────────────┬────────────      │*/
  38. /*│                            │                           │                   │*/
  39. /*│          └─── /o<option> ───┘           └─── /v<file> ───┘                   │*/
  40. /*│                                                                              │*/
  41. /*│   ──── <DOSprogram> ───────────── <DOSargument> ───────┬─────────────┤      │*/
  42. /*│                                                        │                    │*/
  43. /*│                            └────────────────────────────┘                    │*/
  44. /*│                                                                              │*/
  45. /*│                                                                              │*/
  46. /*│ ? .......: Display arguments format.                                         │*/
  47. /*│ /m ......: Set message-level.                                                │*/
  48. /*│ <lvl> ...: Message-level 0 = Suppress all informational messages.            │*/
  49. /*│            Message-level 1 = Display logo only - default.                    │*/
  50. /*│            Message-level 2 = Display Client runtime-information.             │*/
  51. /*│            Message-level 3 = Display Server and Client runtime information.  │*/
  52. /*│ /c ......: Override default path to the Client - WFDOS-C.EXE.                │*/
  53. /*│ <path>...: The path to the Client - WFDOS-C.EXE.                             │*/
  54. /*│            By default, any searchpath specified in the environment-variable  │*/
  55. /*│            WFDOS_CLIENT is also searched.                                    │*/
  56. /*│ /o ......: Override default VDM-options.                                     │*/
  57. /*│ <option>.: A specific VDM-option override.                                   │*/
  58. /*│ /v ......: Override default VDM-options.                                     │*/
  59. /*│ <file>...: The fully or partially qualified name of a file containing the    │*/
  60. /*│            VDM-options.                                                      │*/
  61. /*│            By default, the current directory and any searchpath specified in │*/
  62. /*│            environment-variable WFDOS_CLIENT is also searched.               │*/
  63. /*│ <DOSpgm>.: The fully or partially qualified name of a DOS-program to call.   │*/
  64. /*│            If partially qualified, standard search-paths are applied.        │*/
  65. /*│ <DOSarg>.: 0-n arguments to be supplied to the DOS-program.                  │*/
  66. /*│                                                                              │*/
  67. /*│ All arguments must be separated by at least one blank.                       │*/
  68. /*│                                                                              │*/
  69. /*│            ───────────────────────  o  ───────────────────────               │*/
  70. /*│                                                                              │*/
  71. /*│ Changelog:                                                                   │*/
  72. /*│ ───────────────────────────────────────────────────────────────────────────  │*/
  73. /*│ 94.04.29 - Version 2.00 released to the public domain (CompuServe).          │*/
  74. /*│ 94.05.13 - Version 2.01 fixes problem re rc=460 from DosStartSession.        │*/
  75. /*│            (not released - VDM-session is started as an INDEPENDENT)         │*/
  76. /*│ 94.05.31 - Version 2.02 - a more or less complete re-write.                  │*/
  77. /*│ 94.07.11 - Version 2.03 - "DPMI_DOS_API=ENABLED", unique pipename.           │*/
  78. /*│            Note: This version was not released to the public domain.         │*/
  79. /*│ 94.07.31 - Version 2.04 - support for all VDM-options, plus VDM option-file. │*/
  80. /*│ 94.09.03 - Version 2.05 - minor bugfix: clientrc wasn't returned.            │*/
  81. /*└──────────────────────────────────────────────────────────────────────────────┘*/
  82. #define INCL_DOSPROFILE
  83. #define INCL_DOSNMPIPES
  84. #define INCL_DOSPROCESS
  85. #define INCL_DOSSESMGR
  86. #define INCL_DOSFILEMGR
  87. #define INCL_DOSMISC
  88. #include <os2.h>
  89. #include <stdio.h>
  90. #include <stdlib.h>
  91. #include <string.h>
  92. #include "WFDOS.H"
  93.  
  94. static UCHAR  work[BFR_SIZE];
  95. static UCHAR  DOSClient[256]  = "";
  96. static UCHAR  DOSargList[256] = "";
  97. static UCHAR  DOSTitle[100]   = DOSSESTITLE;
  98. static UCHAR  pipeName[L_tmpnam+10] = PIPE_PREF;
  99. static USHORT msglevel = MLVL_DEFAULT;         /* Message-level settings     */
  100. static UCHAR  *logo = SERVER_LOGO;
  101.  
  102. static STARTDATA startData =
  103. {
  104.    32,                                   /* Structure length                  */
  105.    SSF_RELATED_INDEPENDENT,              /* No session relationship           */
  106.    SSF_FGBG_BACK,                        /* Background execution              */
  107.    SSF_TRACEOPT_NONE,                    /* No need to trace                  */
  108.    "",                                   /* Session name - title              */
  109.    "",                                   /* ProgramName - DOS Client          */
  110.    "",                                   /* Arguments - pipename              */
  111.    NULL,                                 /* Program termination queue         */
  112.    "",                                   /* Environment string                */
  113.    SSF_INHERTOPT_PARENT,
  114.    SSF_TYPE_VDM                          /* Virtual DOS Machine               */
  115. };
  116.  
  117. /*┌──────────────────────────────────────────────────────────────────────────────┐*/
  118. /*│ readVDMoverrides:                                                            │*/
  119. /*│ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀                                                            │*/
  120. /*│ Read options from the specified options-file, and append them to the over-   │*/
  121. /*│ ride-string.                                                                 │*/
  122. /*└──────────────────────────────────────────────────────────────────────────────┘*/
  123. void readVDMoverrides( UCHAR *optionfile, UCHAR **overrides )
  124. {
  125.    FILE  *options;
  126.    UCHAR *work, *optname, *p;
  127.    UCHAR *o_drive, *o_path, *o_fname, *o_ext;
  128.  
  129.    /* Get some workspace */
  130.    work=malloc(1024+1024+_MAX_DRIVE+_MAX_DIR+_MAX_FNAME+_MAX_EXT+10);
  131.    optname=work+1024+1;
  132.    o_drive=optname+1024+1;
  133.    o_path=o_drive+_MAX_DRIVE+1;
  134.    o_fname=o_path+_MAX_DIR+1;
  135.    o_ext=o_fname+_MAX_FNAME+1;
  136.          
  137.    /* Determine fullpath of the given filespec */
  138.    _splitpath( _fullpath(work, optionfile, 1024), o_drive, o_path, o_fname, o_ext );
  139.                                 
  140.    strcpy( work, o_drive ); strcat( work, o_path );
  141.    strcpy( optionfile, o_fname ); strcat( optionfile, o_ext );
  142.  
  143.    /* Get a possible path from the environment. */
  144.    if ( DosScanEnv( "DPATH", &p )==0 )
  145.    {
  146.       /* We wanna search current directory second, so append a ';.;' before ... */
  147.       strcat(work, ";.;" );
  148.       /* ... appending DPATH.           */
  149.       strcat( work, p );
  150.    }
  151.  
  152.    /* Search current directory and DPATH. If not found ...    */
  153.    if ( DosSearchPath( 0, work, optionfile, optname, 1024 ) )
  154.    {             
  155.       printf("%s"WARN_NOOPTIONFILE_MS" \"%s\".\n", logo, optionfile );
  156.       logo="";
  157.       return;
  158.    }
  159.  
  160.    p=*overrides;
  161.  
  162.    if ( (options=fopen( optname, "r" ))!=NULL )
  163.    while ( fgets( p, 80, options )!=NULL )
  164.    {
  165.       p+=strlen(p)-1;
  166.       if ( *p!='\n' ) p++;
  167.       *(p++)='\0';
  168.    }
  169.    fclose( options );
  170.    free(work);
  171.  
  172.    *overrides=p;
  173. }
  174.  
  175. /*┌──────────────────────────────────────────────────────────────────────────────┐*/
  176. /*│ processVDMoutput:                                                            │*/
  177. /*│ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀                                                            │*/
  178. /*│ Read the output from the VDM, remove extraneous '\r's, copy output to OS/2,  │*/
  179. /*│ and look for the returncode from the DOS-program.                            │*/
  180. /*└──────────────────────────────────────────────────────────────────────────────┘*/
  181. USHORT processVDMoutput( HPIPE hpipe )
  182. {
  183.    USHORT rc;
  184.    ULONG  length;
  185.    UCHAR  *work, *p;
  186.  
  187.    work=malloc(1024);
  188.    rc=0;
  189.    do
  190.    {
  191.       /* Read whatever is in the queue, and make sure it is null-terminated */
  192.       DosRead( hpipe, work, 1023, &length ); work[length]='\0';
  193.  
  194.       /* If we got something ... */
  195.       if ( length>0 )
  196.       {
  197.          /* As '\r' and '\n' both will result in a newline, we'll remove  */
  198.          /* the '\r's and leave the '\n's. Otherwise we'll have too many  */
  199.          /* blank lines in the Monitor window.                            */
  200.          while ( (p=strchr( work, '\r' ))!=NULL )
  201.             strcpy( p, p+1 );
  202.  
  203.          /* If the Client has sent a return-code, retrieve it, but dont   */
  204.          /* display it.                                                   */
  205.          if ( (p=strstr( work, CLIENTRC_IDENT ))!=NULL )
  206.          {
  207.             sscanf( p+strlen(CLIENTRC_IDENT), "%hd", &rc );
  208.             *p='\0';
  209.          }
  210.          printf( "%s", work );
  211.       }
  212.    } while ( length>0 );
  213.    free(work);
  214.  
  215.    return rc;
  216. }
  217.  
  218. /*┌──────────────────────────────────────────────────────────────────────────────┐*/
  219. /*│ main:                                                                        │*/
  220. /*│ ▀▀▀▀▀                                                                        │*/
  221. /*└──────────────────────────────────────────────────────────────────────────────┘*/
  222. int main(int argc, char* argv[] )
  223. {
  224.    UCHAR   *p, *env;
  225.    APIRET  rc;
  226.    PID     processID;
  227.    ULONG   sessionID;
  228.    ULONG   length, i, arg;
  229.    USHORT  clientrc = 0;
  230.    HPIPE   hpipe;
  231.  
  232.    /* Process arguments - we need at least one */
  233.    if ( argc<2 || *argv[1]=='?' )
  234.    {
  235.       printf( "%s"
  236.               "Server: Arguments format:\n"
  237.               "WFDOS-S {?} {/m<lvl>} {/c<path>} "
  238.               "{/o<option>...} {/v<file>...} <DOS-pgm> {<DOS-args>}",
  239.               logo );
  240.       return -1;
  241.    }
  242.  
  243.    arg=1;
  244.    p=startData.Environment=malloc(1024); *p='\0';
  245.    while ( arg<argc && *argv[arg]=='/' )
  246.    {
  247.       switch ( *(argv[arg]+1) ) {
  248.       case 'm':
  249.       case 'M':
  250.          sscanf( argv[arg]+2, "%1hd", &msglevel );
  251.          break;
  252.       case 'c':
  253.       case 'C':
  254.          strcpy( DOSClient, argv[arg]+2 );
  255.          break;
  256.       case 'o':
  257.       case 'O':
  258.          strcpy( p, argv[arg]+2 ); p+=strlen(p)+1;
  259.          break;
  260.       case 'v':
  261.       case 'V':
  262.          readVDMoverrides( argv[arg]+2, &p );
  263.          break;
  264.       default: 
  265.          printf( "%sServer: Invalid argument %s ignored.\n", logo, argv[arg] );
  266.          *logo='\0';
  267.          break;
  268.       } /* endswitch */
  269.       arg++;
  270.    } 
  271.  
  272.    /* Check if we have a default VDM option-file */
  273.    if ( DosScanEnv( ENV_VDMOPT, &env )==0 )
  274.       readVDMoverrides( env, &p );
  275.  
  276.    /* Terminate the Environment-string properly */
  277.    *(p+1)='\0';
  278.  
  279.    if ( arg==argc )
  280.    {
  281.       printf( "%sServer: "ARGS_NODOSPROGRAM_MS" - "ABORT".", logo);
  282.       return ARGS_NODOSPROGRAM_RC;
  283.    }
  284.  
  285.    if ( msglevel>0 )
  286.    {
  287.       printf("%s", logo);
  288.       *logo='\0';
  289.    }
  290.  
  291.    strcpy( work, DOSClient );
  292.  
  293.    /* Get a possible path from the environment, ie CONFIG.SYS. */
  294.    if ( DosScanEnv( "PATH", &p )==0 )
  295.    {
  296.       /* If the command-line held an override path, append a ';' before ... */
  297.       if ( *work!='\0' ) strcat(work, ";" );
  298.       /* ... appending additional paths from the environment.               */
  299.       strcat( work, p );
  300.    }
  301.  
  302.    /* Search specified path. If not found ...          */
  303.    if ( rc=DosSearchPath( 0UL, work, CLIENTNAME, DOSClient, 256 ) )
  304.    {
  305.       printf("%s"FAIL_NODOSCLIENT_MS" - "ABORT".", logo);
  306.       return FAIL_NODOSCLIENT_RC;
  307.    }
  308.  
  309.    /* Having determined the location of the client, put it in startData */
  310.    startData.PgmName=strupr(DOSClient);
  311.  
  312.    /* Setup the session-heading */
  313.    strcat( DOSTitle, strupr( argv[arg] ) );
  314.    startData.PgmTitle=DOSTitle;
  315.  
  316.    /* Create a unique pipename - this enables multiple threads using WFDOS */
  317.    i=strlen(pipeName);
  318.    _splitpath( tmpnam(NULL), work, work, pipeName+i, pipeName+i+_MAX_FNAME );
  319.    strcat( pipeName, pipeName+i+_MAX_FNAME );
  320.  
  321.    /* Pack all arguments into a string separated by blanks.                 */
  322.    p=work;
  323.    for ( i=arg; i<argc; i++)
  324.    {
  325.       memcpy( p, argv[i], strlen(argv[i]) );
  326.       p+=strlen(argv[i]);
  327.       *(p++)=' ';
  328.    };    
  329.    *p='\0';
  330.  
  331.    /* Setup arguments for the Client */
  332.    sprintf( DOSargList, SERVER_IDENT" /m%d ", msglevel );
  333.    strcat( DOSargList, pipeName );
  334.    startData.PgmInputs=DOSargList;
  335.  
  336.    if ( rc=DosCreateNPipe( pipeName, &hpipe,
  337.                            NP_INHERIT|NP_ACCESS_DUPLEX,
  338.                            NP_WAIT|NP_TYPE_BYTE|NP_READMODE_BYTE|0x01,
  339.                            PIPESIZE, PIPESIZE, 0 ) )
  340.    {
  341.       printf( "%s"FAIL_CREATEPIPE_MS" - "ABORT", rc=%lu.\n", logo, rc );
  342.       return FAIL_CREATEPIPE_RC;
  343.    }
  344.  
  345.    if ( msglevel>=MLVL_SRUNTIME )
  346.    {
  347.       printf("Server: Starting client %s ...\n", startData.PgmName );
  348.       if ( *startData.Environment^='\0' ) 
  349.          printf("Server: Overriding VDM-options:\n");
  350.       for ( p=startData.Environment; *p^='\0'; p+=strlen(p)+1)
  351.          printf("        %s\n", p);
  352.    }
  353.  
  354.    /* Start a VDM-session in the background */
  355.    if ( rc=DosStartSession( &startData, &sessionID, &processID ) )
  356.    {
  357.       printf( "%s"FAIL_STARTSESSION_MS" - "ABORT", rc=%lu.\n", logo, rc );
  358.       return FAIL_STARTSESSION_RC;
  359.    }
  360.  
  361.    /* Wait for the DOS-program to do DosOpen */
  362.    if ( rc=DosConnectNPipe( hpipe ) )
  363.    {
  364.       printf( "%s"FAIL_DOSCONNECT_MS" - "ABORT", rc=%lu.\n", logo, rc );
  365.       return FAIL_DOSCONNECT_RC;
  366.    }
  367.  
  368.    if ( rc=DosWrite( hpipe, work, strlen(work), &length ) )
  369.    {
  370.       printf( "%s"FAIL_WRITE2PIPE_MS" - "ABORT", rc=%lu.\n", logo, rc );
  371.       return FAIL_WRITE2PIPE_RC;
  372.    }
  373.  
  374.    clientrc=processVDMoutput( hpipe );
  375.  
  376.    free( startData.Environment );
  377.  
  378.    return clientrc;
  379. }   
  380.