home *** CD-ROM | disk | FTP | other *** search
- /*
- * STARTD: A simple program to start a DOS session under OS/2 2.0.
- * This program can be run from an OS/2 command prompt
- *
- * Last Modfied: 07/07/92
- *
- * Author: Norm Ross
- * Jim Sauber
- *
- * Using the example code for BOOTA.C found in IBM DOCUMENT GBOF-2254
- *
- * This was written mainly to provide access to DOS SETTINGS for
- * VDM sessions. Since I have disabled the WPS to free up the space,
- * I can't specify DOS settings for my favorite DOS apps.
- * STARTD is not meant to replace START but it does many of
- * the same things...
- *
- * If you change this program and re-distribute it please leave this
- * header intact and send the readme file with it.
- *
- * MODIFICATION HISTORY
- *
- * 07-Jul-1992 Norm Ross, npross@undergrad.uwaterloo.ca
- * 1.00 : Initial version
- * 25-Feb-1993 Jim Sauber
- * 2.00 : Handles the creation of asynchronous DOS sessions
- * 2.10 : Binds the parent to the child and handles icon started apps
- * 06-Jun-1993 Jim Sauber
- * 2.20 : Increased size of Environment to 4K and resolved OS/2 2.1 problems
- */
-
- #define INCL_DOSSESMGR
- #define INCL_DOSMISC
- #define INCL_DOSPROCESS
- #define INCL_WIN
- #define INCL_DOSMEMMGR
- #define INCL_WINSWITCHLIST
- #include <os2.h>
- #include <stdio.h>
- #include <io.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include "pidinfo.h"
- #define PID_BUFFER_SIZE 0x8000
- #define DOS_PROGRAM_IDENT "SYSINIT" // Identifies a DOS program
- #define WAIT_HOLD_TIME 5000 // Amount of time between checking for
- // child process existence
-
- PBYTE readEnv(PSZ pFileName);
- void ChildProcess (PID) ;
-
- PSZ pBootFailure = "Session could not be started.\r\n";
- char szPgmInputs[512];
- char szDosPgmInputs[512];
-
- STARTDATA startd; /* Session start information */
- ULONG ChildSessionID; /* Session and Process ID for new session*/
- PID pidChildPid;
- char fDebug ; /* flag whether to dump debug info */
-
-
- void main(int argc, char *argv[])
- {
- USHORT rc, i ;
- USHORT flagWin = 0, flagFs = 0, flagKeep = 0, flagNoCmd = 0;
-
- fDebug = FALSE ;
-
- /* ---- init startd struct defaults */
- startd.Length = sizeof(STARTDATA);
- startd.Related = SSF_RELATED_INDEPENDENT;
- startd.FgBg = SSF_FGBG_FORE;
- startd.TraceOpt = SSF_TRACEOPT_NONE;
- startd.PgmTitle = NULL;
- startd.PgmName = NULL;
- startd.PgmInputs = NULL;
- startd.TermQ = NULL;
- startd.Environment = NULL;
- startd.InheritOpt = SSF_INHERTOPT_PARENT;
- startd.SessionType = SSF_TYPE_DEFAULT;
- startd.PgmControl = SSF_CONTROL_VISIBLE;
-
- /* ------ Process args */
- while(--argc > 0)
- {
- char *arg;
-
- switch(**++argv)
- {
- case '\"':
- startd.PgmTitle = strtok(*argv, "\"");
- break;
- case '-':
- case '/':
- arg = (*argv)+1;
- if (strlen(arg) == 1)
- {
- switch(*arg)
- {
- case 'n':
- case 'N': flagNoCmd = 1; break;
- case 'k':
- case 'K': flagKeep = 1; break;
- case 'c':
- case 'C': break;
- case 'f':
- case 'F': startd.FgBg = SSF_FGBG_FORE; break;
- case 'B':
- case 'b': startd.FgBg = SSF_FGBG_BACK; break;
- case 'i':
- case 'I': startd.InheritOpt = SSF_INHERTOPT_SHELL; break;
- case '?': usage(); break;
- default:
- fprintf(stderr, "Unrecognized option: %s\n", arg);
- usage();
- break;
- }
- }
- else if (stricmp(arg, "DOS") == 0)
- startd.SessionType = SSF_TYPE_VDM;
- else if (stricmp(arg, "WIN") == 0)
- flagWin = 1;
- else if (stricmp(arg, "WAIT") == 0)
- startd.Related = SSF_RELATED_CHILD;
- else if (stricmp(arg, "FS") == 0)
- flagFs = 1;
- else if (stricmp(arg, "FG") == 0)
- startd.FgBg = SSF_FGBG_FORE;
- else if (stricmp(arg, "BG") == 0)
- startd.FgBg = SSF_FGBG_BACK;
- else if (stricmp(arg, "MAX") == 0)
- startd.PgmControl |= SSF_CONTROL_MAXIMIZE;
- else if (stricmp(arg, "MIN") == 0)
- startd.PgmControl |= SSF_CONTROL_MINIMIZE;
- else if (stricmp(arg, "INV") == 0)
- startd.PgmControl |= SSF_CONTROL_INVISIBLE;
- else if (stricmp(arg, "PM") == 0)
- startd.SessionType = SSF_TYPE_PM;
- else if (strnicmp(arg, "pos", 3) == 0)
- {
- char *s = strtok(arg, "=");
-
- /* ---- I really should check strtok's return... */
- startd.PgmControl |= SSF_CONTROL_SETPOS;
- startd.InitXPos = atoi(strtok(NULL, ","));
- startd.InitYPos = atoi(strtok(NULL, ","));
- startd.InitXSize = atoi(strtok(NULL, ","));
- startd.InitYSize = atoi(strtok(NULL, ""));
- }
- else if (stricmp(arg, "PGM") == 0)
- {
- char *p = szPgmInputs;
- /* ---- strip quotes from name if there are any */
- startd.PgmName = strtok(*argv, "\"");
-
- /* ---- cat the rest of the args together to pass to pgm */
- while (argc > 1)
- {
- argc--;
- argv++;
- strcpy(p, *argv);
- p += strlen(*argv);
- *p++ = ' '; /* put spaces between the args */
- }
- *p = '\0';
- startd.PgmInputs = szPgmInputs;
- break;
- }
- else if (stricmp(arg, "ICON") == 0)
- {
- startd.IconFile = *++argv;
- argc--;
- }
- else if (stricmp(arg, "SF") == 0)
- {
- char *fname = *++argv;
- argc--;
- // if (access(fname, 0))
- // fprintf(stderr, "Session File %s not found\n", fname);
- startd.Environment = readEnv(fname);
- }
- else if (stricmp(arg, "DEBUG") == 0)
- fDebug = TRUE ;
- else
- {
- printf("Unrecognized option: %s\n", arg);
- usage();
- }
- break;
-
- default:
- {
- char *p = szPgmInputs;
- startd.PgmName = *argv;
- /* ---- cat the rest of the args together to pass to pgm */
- while (argc > 1)
- {
- argc--;
- argv++;
- strcpy(p, *argv);
- p += strlen(*argv);
- *p++ = ' '; /* put spaces between the args */
- }
- *p = '\0';
- startd.PgmInputs = szPgmInputs;
- break;
- }
- } /* switch */
- } /* while */
-
- /* ------ Start thru Command processor */
- if ((startd.PgmName!=NULL)&&(startd.SessionType!=SSF_TYPE_PM)&&(!flagNoCmd))
- {
- if (flagKeep)
- strcpy(szDosPgmInputs, "/k ");
- else
- strcpy(szDosPgmInputs, "/c ");
- strcat(szDosPgmInputs, startd.PgmName);
- strcat(szDosPgmInputs, " ");
- strcat(szDosPgmInputs, startd.PgmInputs);
- startd.PgmInputs = szDosPgmInputs;
- startd.PgmName = NULL;
- }
-
- /* ------ Set the correct session type */
- if (flagWin)
- {
- switch(startd.SessionType)
- {
- case SSF_TYPE_DEFAULT:
- startd.SessionType = SSF_TYPE_WINDOWABLEVIO;
- break;
- case SSF_TYPE_VDM:
- startd.SessionType = SSF_TYPE_WINDOWEDVDM;
- break;
- case SSF_TYPE_PM:
- break;
- } /* switch */
- } /* if */
- else if (flagFs)
- {
- switch(startd.SessionType)
- {
- case SSF_TYPE_DEFAULT: startd.SessionType = SSF_TYPE_FULLSCREEN; break;
- case SSF_TYPE_VDM: break;
- case SSF_TYPE_PM: break;
- } /* switch */
- } /* elseif */
-
- /* if debug is set, then dump all settings */
- if (fDebug)
- {
- printf ("Related = %d\n", startd.Related) ;
- printf ("FgBg = %d\n", startd.FgBg) ;
- printf ("TraceOpt = %d\n", startd.TraceOpt) ;
- printf ("PgmTitle = ") ;
- if (startd.PgmTitle != NULL)
- for (i = 0; startd.PgmTitle[i] != 0; ++i)
- printf ("%c", startd.PgmTitle[i]) ;
- printf ("\n") ;
- printf ("PgmName =") ;
- if (startd.PgmName != NULL)
- for (i = 0; startd.PgmName[i] != 0; ++i)
- printf ("%c", startd.PgmName[i]) ;
- printf ("\n") ;
- printf ("PgmInputs =") ;
- if (startd.PgmInputs != NULL)
- for (i = 0; startd.PgmInputs[i] != 0; ++i)
- printf ("%c", startd.PgmInputs[i]) ;
- printf ("\n") ;
- printf ("TermQ =") ;
- if (startd.TermQ != NULL)
- for (i = 0; startd.TermQ[i] != 0; ++i)
- printf ("%c", startd.TermQ[i]) ;
- printf ("\n") ;
- printf ("Environment= ") ;
- if (startd.Environment != NULL)
- for (i = 0; startd.Environment[i] != 10; ++i)
- printf ("%c", startd.Environment[i]) ;
- printf ("\n") ;
- printf ("InheritOpt = %d\n", startd.InheritOpt) ;
- printf ("SessionType= %d\n", startd.SessionType) ;
- printf ("PgmControl = %d\n", startd.PgmControl) ;
- }
-
- /* ------ Start the Session */
- rc = DosStartSession( &startd, &ChildSessionID, &pidChildPid );
-
- if(rc)
- /* ------ Print out failure message */
- DosPutMessage(1,strlen(pBootFailure),pBootFailure);
- else if (startd.Related == SSF_RELATED_CHILD)
- ChildProcess (pidChildPid) ;
- return;
- }
-
- #define MAXENV 4096
- /************************************************************************/
- // Read the DOS environment file and create the environment string
- /************************************************************************/
- PBYTE readEnv(PSZ fname)
- {
- FILE *fptr;
- PBYTE env = (PBYTE)malloc(MAXENV);
- PBYTE p = env;
- char *i ;
-
- fptr = fopen(fname, "rb");
- if (fptr == (FILE *)NULL)
- {
- fprintf(stderr, "\nFile %s cannot be found\n");
- exit(-1);
- }
-
- // If the env flag is DOS_VERSION, then need to concatenate all the strings
- // together to form 1 environment string. If only 0x0a terminates the input
- // then remove the NULL, concatenate the 0x0a and the string and add a
- // NULL
- while (fgets(p, 80, fptr))
- {
- p+=strlen(p);
- // if last 2 chars are crlf then remove them, if last char is lf, then
- // keep it
- if (*(p-2) == '\r' && *(p-1) == '\n')
- {
- *(p-2)='\0';
- --p ;
- } /* if */
- // *(p-1)='\0';
-
- if (p>env + 4096)
- {
- fprintf(stderr, "ERROR: too many settings\n");
- fflush(stderr);
- exit(-1);
- }
- } /* while */
- realloc(env, p-env);
- fclose (fptr) ;
- return(env);
- }
-
- /************************************************************************/
- // Display for the user the usage information
- /************************************************************************/
- usage( void )
- {
- fprintf(stderr, "STARTD VERSION 2.2 by Norm Ross & Jim Sauber Copyright (c) 1993\n\n");
- fprintf(stderr, "startd [\"program title\"] [/BG /C /DOS /F /FS /I /ICON iconfile /INV /K /MAX\n\t /MIN /PGM POS=x,y,x1,y1 /SF settingsfile /WIN] [command ...]\n\n");
- fprintf(stderr, "\t/B[G]\t start session in background\n");
- fprintf(stderr, "\t/C\t close session upon completion\n");
- fprintf(stderr, "\t/DOS\t start a dos session\n");
- fprintf(stderr, "\t/F[G]\t start session in foreground\n");
- fprintf(stderr, "\t/FS\t start a full screen session\n");
- fprintf(stderr, "\t/I\t sets SSF_INHERTOPT_SHELL\n");
- fprintf(stderr, "\t/ICON\t uses the specified icon file\n");
- fprintf(stderr, "\t/INV\t start the application invisibly\n");
- fprintf(stderr, "\t/K\t keep the session around after it is finished\n");
- fprintf(stderr, "\t/MAX\t start maximized\n");
- fprintf(stderr, "\t/MIN\t start minimized\n");
- fprintf(stderr, "\t/N\t don't start indirectly through command processor\n");
- fprintf(stderr, "\t/PGM\t the next argument is the program name\n");
- fprintf(stderr, "\t/PM\t start a PM program\n");
- fprintf(stderr, "\t/POS=x,y,x1,y1\t specify window position and size\n");
- fprintf(stderr, "\t/SF\t read the specified dos settings file\n");
- fprintf(stderr, "\t/WIN\t start a windowed session\n");
- fprintf(stderr, "\t/WAIT\t doesn't work\n");
- exit(1);
- }
-
- /************************************************************************/
- // Function: To start asynchronous process
- // The function searches the process list and switch list until it finds
- // an ancestor of the current process in the switch list. It then removes
- // that process from the switch list and if it is a window, minmizes it.
- /************************************************************************/
- void ChildProcess(PID pidChildPid)
- {
- USHORT usActiveProcesses ; /* count of active processes */
- PBUFFHEADER pbh ; /* buffer for task info */
- PPROCESSINFO ppiLocal ; /* child process info */
- BOOL fPidFound ; /* flag whether child process is found */
- PTIB pTib ; /* Tib info of current process */
- PPIB pPib ; /* Pib info of current process */
- HAB hab ; /* handle to switch list */
- HSWITCH hswitch ; /* handle to switch entry */
- ULONG cbItems, cbBuf ; /* sizeof of Process buffer */
- PBYTE pBase ; /* pointer to memory */
- PSWBLOCK pswblk ; /* pointer to allocated memory */
- PSWENTRY pSwitchEntry ; /* pointer to each switch entry in list */
- SHORT i ; /* misc counter */
- ULONG ulCurrentType ; /* current session type */
- PID pidParentPid ; /* current process' immediate parent's PID */
- PID pidCurrentPid ; /* PID of this process */
- PID pidAncestorPid ; /* PID of an ancestor in the switch list */
- HWND hwndAncestorFrame ; /* frame hwnd of the ancestor in the switch list */
- HSWITCH hAncestorSwitch ; /* switch entry handle to displayed ancestor */
- SWCNTRL swParentControl ; /* switch entry info parent */
- SWCNTRL swAncestorControl ; /* switch entry of ancestor */
- STATUSDATA sdSetSessionData ; /* DosSetSession status data */
- USHORT rc ; /* misc return code */
-
- rc = DosGetInfoBlocks (&pTib, &pPib) ;
- ulCurrentType = pPib->pib_ultype ;
- pidCurrentPid= pPib->pib_ulpid ;
- pidParentPid = pPib->pib_ulppid ;
-
- /* allocate memory for Process list */
- rc = DosAllocMem((PPVOID) &pBase, (ULONG) 40000, PAG_READ | PAG_WRITE) ;
- rc = DosSubSetMem (pBase, DOSSUB_INIT | DOSSUB_SPARSE_OBJ, 4000) ;
-
- /* get the process list */
- pbh = malloc (PID_BUFFER_SIZE) ;
- rc = DosQProcStatus (pbh, PID_BUFFER_SIZE) ;
- ppiLocal = pbh->ppi ;
-
- /* get the switch list */
- cbItems = WinQuerySwitchList (hab, NULL, 0) ;
- cbBuf = (cbItems * sizeof(SWENTRY)) + sizeof(HSWITCH) ;
- rc = DosSubAllocMem((PVOID) pBase, (PPVOID) &pswblk, (ULONG) cbBuf) ;
- do
- {
- rc = WinQuerySwitchList (hab, pswblk, cbBuf) ;
-
- /* search the switch list to find an ancestor of the current process */
- /* pidAncestorPid = -1 means no ancestor found yet */
- pidAncestorPid = -1 ;
- pSwitchEntry = &(pswblk->aswentry[0]) ;
- for (i = 0; i < cbItems && pidAncestorPid == -1; ++i, ++pSwitchEntry)
- {
- hswitch = pSwitchEntry->hswitch ;
- rc = WinQuerySwitchEntry (hswitch, &swParentControl) ;
- /* if found current pid in the switch list */
- if (pidCurrentPid == swParentControl.idProcess)
- {
- pidAncestorPid = swParentControl.idProcess ;
- hwndAncestorFrame = swParentControl.hwnd ;
- }
- /* if found parent pid in the switch list */
- if (pidParentPid == swParentControl.idProcess)
- {
- pidAncestorPid = swParentControl.idProcess ;
- hwndAncestorFrame = swParentControl.hwnd ;
- }
- }
-
- /* if ancestor not found in the switch list this time, go back */
- /* one more generation */
- if (pidAncestorPid == -1) {
- fPidFound = FALSE ;
- while(ppiLocal->ulEndIndicator != PROCESS_END_INDICATOR && !fPidFound){
- ++usActiveProcesses ;
- if (ppiLocal->pid == pidParentPid)
- {
- fPidFound = TRUE ;
- pidParentPid = ppiLocal->pidParent ;
- } /* endif */
- ppiLocal = (PPROCESSINFO) (ppiLocal->ptiFirst+ppiLocal->usThreadCount );
- }
- } else {
- } /* endif */
- } while ( pidAncestorPid == -1 && pidParentPid != 0); /* enddo */
-
- // hAncestorSwitch = WinQuerySwitchHandle (hwndAncestorFrame, 0) ;
- // rc = WinQuerySwitchEntry (hswitch, &swAncestorControl) ;
- // swAncestorControl.uchVisibility = SWL_INVISIBLE;
- // swAncestorControl.fbJump = SWL_NOTJUMPABLE;
- // WinChangeSwitchEntry (hAncestorSwitch, &swAncestorControl) ;
- /* If this is a windowed session, minimize it */
- if (ulCurrentType == 2)
- rc = WinPostMsg (hwndAncestorFrame, WM_SYSCOMMAND,
- MPFROMSHORT(SC_MINIMIZE), NULL) ;
-
- /* Set so when the parent's icon is clicked, the child shows up */
- sdSetSessionData.Length = 6 ;
- sdSetSessionData.SelectInd = 2 ;
- sdSetSessionData.BondInd = 1 ;
- DosSetSession (ChildSessionID, &sdSetSessionData) ;
-
- /* Wait for child to finish */
- do
- {
- DosSleep (WAIT_HOLD_TIME) ;
- rc = DosQProcStatus (pbh, PID_BUFFER_SIZE) ;
- ppiLocal = pbh->ppi ;
- usActiveProcesses = 0 ;
- fPidFound = FALSE ;
- while(ppiLocal->ulEndIndicator != PROCESS_END_INDICATOR && !fPidFound)
- {
- ++usActiveProcesses ;
- if (ppiLocal->pid == pidChildPid)
- fPidFound = TRUE ;
- ppiLocal = (PPROCESSINFO) (ppiLocal->ptiFirst+ppiLocal->usThreadCount );
- }
- } while (fPidFound) ;
-
- swAncestorControl.uchVisibility = SWL_VISIBLE;
- swAncestorControl.fbJump = SWL_JUMPABLE;
- WinChangeSwitchEntry (hAncestorSwitch, &swAncestorControl) ;
- if (ulCurrentType == 2)
- rc = WinPostMsg (hwndAncestorFrame, WM_SYSCOMMAND,
- MPFROMSHORT(SC_RESTORE), NULL) ;
- return ;
- }
-