home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CICA 1995 May
/
cica_0595_4.zip
/
cica_0595_4
/
UTIL
/
MEWS11
/
MSWEXEC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-12
|
15KB
|
484 lines
/* The routines in this file provide support for external program
execution under the Microsoft Windows environment on an IBM-PC or
compatible computer.
Must be compiled with Borland C++ 2.0 or MSC 6.0 or later versions
It should not be compiled if the WINDOW_MSWIN symbol is not set */
#include "estruct.h"
#include <stdio.h>
#include "eproto.h"
#include "edef.h"
#include "elang.h"
#include "mswin.h"
#define CMDLENGTH 256+NFILEN
/* local data */
#if WINDOW_MSWIN32
static STARTUPINFO suInfo = { 0 };
static char suTitle [] = PROGNAME "'s subshell";
static PROCESS_INFORMATION pInfo = { 0 };
#else
static HWND hPrgWnd; /* window handle of the external program task */
#endif
/* HandleTimer: checks the existence of the external program window */
/* =========== */
static void PASCAL HandleTimer (HWND hDlg)
/* This function uses a 200ms timeout to check the existence of the window
indicated by hPrgWnd. When that window handle becomes invalid, it is
assumed that the external program has exited and the WAITFORPRG
dialog box is terminated with a TRUE result. If there is a problem
setting the timer, the dialog box is terminated with a FALSE result
after a message box announcing the problem has been displayed. */
{
#if WINDOW_MSWIN32
/* check for process completion */
if (WaitForSingleObject(pInfo.hProcess, 0) == WAIT_TIMEOUT) {
#else
/* look for the program window */
if (IsWindow (hPrgWnd)) {
#endif
while (!SetTimer (hDlg, 1, 200, NULL)) {
/* bad: problem setting the timer */
if (MessageBox (hDlg, TEXT337, NULL, MB_RETRYCANCEL) == IDCANCEL) {
/* "cannot monitor external program" */
EndDialog (hDlg, FALSE); /* give up! */
return;
}
/* else: attempt a retry */
}
}
else {
EndDialog (hDlg, TRUE);
}
} /* HandleTimer */
/* WAITFORPRGDlgProc: dialog proc for WAITFORPRG dialog box */
/* ================= */
int EXPORT FAR PASCAL WAITFORPRGDlgProc (HWND hDlg, UINT wMsg,
UINT wParam, LONG lParam)
{
switch (wMsg) {
case WM_INITDIALOG:
SetWindowText (hDlg, PROGNAME);
HandleTimer (hDlg);
return TRUE;
case WM_TIMER:
HandleTimer (hDlg);
break;
case WM_COMMAND:
if (LOWORD(wParam) == 2) { /* Cancel */
KillTimer (hDlg, 1);
EndDialog (hDlg, FALSE);
}
break;
default:
return FALSE;
}
return FALSE;
} /* WAITFORPRGDlgProc */
/* LaunchPrgEnumProc: used by LaunchPrg */
/* ================= */
BOOL EXPORT FAR PASCAL LaunchPrgEnumProc (HWND hWnd, LONG lParam)
/* this function sets hPrgWnd when it finds a window that matches the
module instance handle passed in lParam */
{
#if !WINDOW_MSWIN32
if (GetWindowWord (hWnd, GWW_HINSTANCE) == LOWORD(lParam)) {
hPrgWnd = hWnd;
return FALSE; /* found it, stop enumerating */
}
#endif
return TRUE;
} /* LaunchPrgEnumProc */
/* LaunchPrg: launches and monitors an external program */
/* ========= */
static BOOL PASCAL LaunchPrg (char *Cmd, BOOL DOSApp,
char *InFile, char *OutFile)
/* Returns TRUE if all went well, FALSE if wait cancelled and FAILED if
failed to launch.
Cmd is the command string to launch.
DOSApp is TRUE if the external program is a DOS program to be run
under a DOS shell. If DOSApp is FALSE, the program is launched
directly as a Windows application. In that case, the InFile parameter
is ignored, and the value of the OutFile parameter is used only to
determine if the program should be monitored. the text of the string
referenced by OutFile is irrelevant.
InFile is the name of the file to pipe into stdin (if NULL, nothing
is piped in)
OutFile is the name of the file where stdout is expected to be
redirected. If it is NULL or an empty string, stdout is not redirected
If Outfile is NULL, LaunchPrg returns immediately after starting the
DOS box.
If OutFile is not NULL, the external program is monitored.
LaunchPrg returns only when the external program has terminated or
the user has cancelled the wait (in which case LaunchPrg returns
FALSE). */
{
char FullCmd [CMDLENGTH];
HANDLE hModule;
int nCmdShow;
BOOL Synchronize;
#if !WINDOW_MSWIN32
FARPROC ProcInstance;
#endif
if (OutFile) {
Synchronize = TRUE;
if (*OutFile == '\0') OutFile = NULL; /* stop worrying about that
empty string */
}
else Synchronize = FALSE;
if (SetWorkingDir () != 0) {
mlwrite (TEXT334); /* "[No such directory]" */
return FALSE;
}
if (DOSApp) {
#if WINDOW_MSWIN32
GetProfileString (ProgName, "Shell", "cmd.exe", FullCmd, CMDLENGTH);
/* the Shell profile string should contain the name of the shell
to be used for pipe-command, filter buffer, shell-command and
i-shell. The ShellExecOption profile string should contain
the option flags that cause the execution under that shell of
a single command (the text of which is appended to the profile
string) so that the shell terminates with that command. */
if (Cmd) {
char ExecOption [10];
GetProfileString (ProgName, "ShellExecOption", " /c ",
ExecOption, 10);
if ((strlen (FullCmd) + strlen (ExecOption) + strlen (Cmd)) >=
CMDLENGTH) return FALSE;
strcat (FullCmd, ExecOption);
strcat (FullCmd, Cmd);
}
#else
if (Synchronize || !Cmd) {
GetProfileString (ProgName, "DOSExec", "",
FullCmd, CMDLENGTH);
if (FullCmd[0] == '\0') { /* try to find it on the "path" */
char *s;
if ((s = flook ("DOSEXEC.PIF", TRUE)) != NULL) {
strcpy (FullCmd, s);
}
}
}
else FullCmd[0] = '\0';
if (FullCmd[0] == '\0') {
GetProfileString (ProgName, "DOSBox", "",
FullCmd, CMDLENGTH);
if (FullCmd[0] == '\0') { /* try to find it on the "path" */
char *s;
if ((s = flook ("DOSBOX.PIF", TRUE)) != NULL) {
strcpy (FullCmd, s);
}
else strcpy (FullCmd, "command.com");
}
}
/* the DOSBox profileString should be the name of a PIF file for
command.com that specifies no arguments and no starting dir.
The DOSExec should be similar but specify "Close window on
exit" so that synchronization can work */
if (Cmd) {
if ((strlen (FullCmd) + strlen (Cmd) + 4) >=
CMDLENGTH) return FALSE;
strcat (FullCmd, " /c ");
strcat (FullCmd, Cmd);
}
#endif
if (InFile) {
if ((strlen (FullCmd) + strlen (InFile) + 2) >=
CMDLENGTH) return FALSE;
strcat (FullCmd, " <");
strcat (FullCmd, InFile);
}
if (OutFile) {
if ((strlen (FullCmd) + strlen (OutFile) + 2) >=
CMDLENGTH) return FALSE;
strcat (FullCmd, " >");
strcat (FullCmd, OutFile);
}
}
#if WINDOW_MSWIN32
/* set the startup window size */
suInfo.cb = sizeof(STARTUPINFO);
if (DOSApp && Cmd) suInfo.lpTitle = suTitle;
suInfo.wShowWindow = (DOSApp && Synchronize) ? SW_SHOWMINIMIZED :
SW_SHOWNORMAL;
suInfo.dwFlags = STARTF_USESHOWWINDOW;
/* start the process and get a handle on it */
if (CreateProcess (NULL, DOSApp ? FullCmd : Cmd, NULL, NULL,
DETACHED_PROCESS,
FALSE, NULL, NULL, &suInfo, &pInfo)) {
int Result;
if (Synchronize) {
/* put up a dialog box to wait for termination */
Result = DialogBox (hEmacsInstance, "WAITFORPRG",
hFrameWnd, WAITFORPRGDlgProc);
}
else {
/* no need to synchronize */
Result = TRUE;
}
CloseHandle(pInfo.hThread);
CloseHandle(pInfo.hProcess);
return Result;
} else return FALSE;
#else
if (Win386Enhanced) {
if (DOSApp && Synchronize) nCmdShow = SW_SHOWMINIMIZED;
else nCmdShow = SW_SHOWNORMAL;
}
else nCmdShow = SW_SHOWNORMAL;
hModule = WinExec (DOSApp ? FullCmd : Cmd, nCmdShow);
/* here we GOoooo */
if (hModule < 32) {
mlwrite (TEXT3); /* "[Execution failed]" */
return FAILED;
}
if (!Synchronize) return TRUE; /* no synchronization */
hPrgWnd = 0;
ProcInstance = MakeProcInstance ((FARPROC)LaunchPrgEnumProc,
hEmacsInstance);
EnumWindows (ProcInstance, (DWORD)hModule);
FreeProcInstance (ProcInstance);
if (hPrgWnd != 0) {
/*-put up a dialog box to wait for the external program termination */
int Result;
ProcInstance = MakeProcInstance ((FARPROC)WAITFORPRGDlgProc,
hEmacsInstance);
Result = DialogBox (hEmacsInstance, "WAITFORPRG",
hFrameWnd, ProcInstance);
FreeProcInstance (ProcInstance);
return Result;
}
else return TRUE; /* we assume it has zipped past us! */
#endif
} /* LaunchPrg */
/* spawncli: launch DOS shell. Bound to ^X-C */
/* ======== */
PASCAL spawncli (int f, int n)
{
/*-don't allow this command if restricted */
if (restflag) return resterr();
return LaunchPrg (NULL, TRUE, NULL, NULL);
} /* spawncli */
/* spawn: run a one-liner in a DOS box. Bound to ^X-! */
/* ===== */
PASCAL spawn (int f, int n)
{
char Line[NLINE];
int Result;
char *SynchOption;
static char empty[] = "";
/*-don't allow this command if restricted */
if (restflag) return resterr();
if ((Result = mlreply ("!", Line, NLINE)) != TRUE) return Result;
if (f) SynchOption = &empty[0];
else SynchOption = NULL;
return LaunchPrg (Line, TRUE, NULL, SynchOption);
} /* spawn */
/* execprg: run another program with arguments. Bound to ^X-$ */
/* ======= */
PASCAL execprg (int f, int n)
{
char Line[NLINE];
int Result;
char *SynchOption;
/*-don't allow this command if restricted */
if (restflag) return resterr();
/*-get the program command line */
if (mlreply ("$", Line, NLINE) != TRUE) return FALSE;
if (f) SynchOption = &Line[0]; /* any not NULL will do */
else SynchOption = NULL;
Result = LaunchPrg (Line, FALSE, NULL, SynchOption);
if (Result == FAILED) {
mlwrite (TEXT3); /* "[Execution failed]" */
}
return Result;
} /* execprg */
/* pipecmd: pipe a one-liner into a window. Bound to ^X-@ */
/* ======= */
PASCAL pipecmd (int f, int n)
/* this function fills a buffer named "command" with the output of the
DOS one-liner. If the command buffer already exist, it is overwritten
only if it has not been changed */
{
char Line[NLINE];
char OutFile[NFILEN];
static char bname[] = "command";
BUFFER *bp;
WINDOW *wp;
int Result;
int bmode;
char bflag;
#if WINDOW_MSWIN32
char TempDir[NFILEN] = "\\";
#endif
/*-don't allow this command if restricted */
if (restflag) return resterr();
/*-get the command to pipe-in */
if (mlreply ("@", Line, NLINE) != TRUE) return FALSE;
/*-find the "command" buffer */
if ((bp = bfind (bname, FALSE, 0)) != NULL) {
/*-make sure the contents can safely be blown away */
if (bp->b_flag & BFCHG) {
if (mlyesno (TEXT32) != TRUE) return FALSE;
/* discard changes */
}
}
else if ((bp = bfind (bname, TRUE, 0)) == NULL) {
mlwrite (TEXT137);
/* cannot create buffer */
return FALSE;
}
#if WINDOW_MSWIN32
GetTempPath (NFILEN, TempDir);
GetTempFileName (TempDir, "UE", 0, OutFile);
#else
GetTempFileName (0, "UE", 0, OutFile);
#endif
Result = LaunchPrg (Line, TRUE, NULL, OutFile);
if (Result == FAILED) {
mlwrite (TEXT3);
/* [execution failed] */
unlink (OutFile);
}
else {
if (Result == TRUE) {
BUFFER *temp_bp;
temp_bp = curbp;
swbuffer (bp); /* make this buffer the current one */
bmode = bp->b_mode;
bp->b_mode &= ~MDVIEW;
bflag = bp->b_flag;
bp->b_flag &= ~BFCHG;
Result = readin (OutFile, FALSE);
bp->b_fname[0] = '\0'; /* clear file name */
if (Result == TRUE) {
bp->b_mode |= MDVIEW; /* force VIEW mode */
lchange (WFMODE); /* update all relevant mode lines */
bp->b_flag &= ~BFCHG; /* remove by-product BFCHG flag */
}
else {
bp->b_mode = bmode; /* restore mode */
bp->b_flag = bflag;
swbuffer (temp_bp);
}
unlink (OutFile);
/* note that the file is not deleted if the wait was cancelled */
}
}
return Result;
} /* pipecmd */
/* filter: filter a buffer through a DOS box. Bound to ^X-# */
/* ====== */
PASCAL filter (int f, int n)
{
char Line[NLINE];
char InFile[NFILEN];
char OutFile[NFILEN];
char fname[NFILEN];
BUFFER *bp;
WINDOW *wp;
int Result;
#if WINDOW_MSWIN32
char TempDir[NFILEN] = "\\";
#endif
/*-don't allow this command if restricted */
if (restflag) return resterr();
/*-get the filter command line */
if (mlreply ("#", Line, NLINE) != TRUE) return FALSE;
bp = curbp;
strcpy (fname, bp->b_fname);
#if WINDOW_MSWIN32
GetTempPath (NFILEN, TempDir);
GetTempFileName (TempDir, "UE", 0, InFile);
#else
GetTempFileName (0, "UE", 0, InFile);
#endif
Result = writeout (InFile, "w");
if (Result != TRUE) {
mlwrite (TEXT2);
/* cannot write filter file */
}
else {
#if WINDOW_MSWIN32
GetTempFileName (TempDir, "UE", 0, OutFile);
#else
GetTempFileName (0, "UE", 0, OutFile);
#endif
Result = LaunchPrg (Line, TRUE, InFile, OutFile);
if (Result == FAILED) {
mlwrite (TEXT3);
/* [execution failed] */
unlink (OutFile);
unlink (InFile);
}
else {
if (Result == TRUE) {
Result = readin (OutFile, FALSE);
unlink (OutFile);
unlink (InFile);
}
/* note that he files are not deleted if the wait was cancelled */
if (Result == TRUE) {
lchange (WFMODE); /* update all relevant mode lines */
}
}
}
strcpy (bp->b_fname, fname); /* restore original file name */
return Result;
} /* filter */