The code is
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <conio.h>
#include <windows.h>
#include <process.h>
#include <sys/stat.h>
#if _MSC_VER < 1900
#define CONSTEXPR const
#else
#define CONSTEXPR constexpr
#endif
#if _DEBUG
#define NULL_OP stdout
#else
#define NULL_OP NULL
#endif
typedef short Cc;
#define OK 0
#define nullptr (0)
#define PATHCHR ';'
#define DIRSEPCHAR '\'
#define NFILEN 256
#define in_range(a,b,c) ((unsigned)((a)-(b)) <= (unsigned)((c)-(b)) && ((signed)c)-(b) >= 0)
char * concat(char * tgt, ...)
{
va_list ap;
va_start(ap, tgt);
{ char * s;
tgt[0] = 0;
while ((s = va_arg(ap, char *)) != nullptr)
strcat(tgt, s);
return tgt;
}}
/* at most n chars including the 0 */
char * strpcpypfx(char * t_, const char * s_, int n_, char term)
{ short n;
char ch;
const char * s = s_;
char * t = t_;
for (n = -1; ++n < n_ && (ch = s[n]) != 0 && ch != term;
)
t[n] = ch;
t[n] = 0;
return t_;
}
/* at most n chars including the 0 */
char * strpcpy(char * t_, const char * s_, int n_)
#if 0
{ register short n = n_;
register char * s = s_;
register char * t = t_;
if (t != null)
{ while (--n > 0 && (*t++ = *s++) != 0)
;
if (n == 0)
*t = 0;
}
return t_;
}
#else
{ return strpcpypfx(t_, s_, n_-1, 0);
}
#endif
/* ################# string match routines ##################### */
char bad_strmatch;
const char * com_match(const char * t_, const char * s_, int mask)
{ register int tix = 0;
register const char * s = s_;
register char ch;
#if CHARCODE != ASCII
if (mask == 0x20)
for (; *s != 0 && (ch = t_[tix]) != 0 && toupper(ch) == toupper(*s); ++s)
++tix;
else
#endif
for (; *s != 0 && (ch = t_[tix]) != 0 && (ch | mask) == (*s | mask); ++s)
++tix;
bad_strmatch = *s;
return &t_[tix];
}
/* replace the last entry in dir by file */
/* t can equal dir */
char * pathcat(char * t, int bufsz, const char * dir, const char * file)
{ register int tix;
if (dir[0] == '.' && dir[1] == '/' && dir[2] == '.' && dir[3] == '.' && dir[4] == '/')
dir += 2;
if (file[0] == '/' || file[0] == '\')
strpcpy(t, file, bufsz);
else
{ for (tix = -1; ++tix < bufsz - 1 && dir[tix] != 0; )
t[tix] = dir[tix];
t[tix] = 0;
while (1)
{ while (--tix >= 0 && t[tix] != '/' && t[tix] != '\') /* strip back to / */
;
if (tix > 0)
{ if (t[tix-1] != '.' &&
file[0] == '.' && file[1] == '.' && file[2] == '/')
{ for (file = &file[2]; *++file == '/';) /* strip forward to non / */
;
continue;
}
}
break;
}
{ int six = 0;
for (; ++tix < bufsz - 1 && file[six] != 0; ++six)
t[tix] = file[six];
t[tix] = 0;
}}
return t;
}
int name_mode(const char * s)
{ struct stat fstat_;
if (stat(s, &fstat_) != OK)
return 0;
return fstat_.st_mode;
}
#define fexist(fn) name_mode(fn)
static char fspec[256+2]; /* full path spec to search */
bool fex_path(const char * dir, const char * file)
{ if (dir != nullptr)
{ char * pc = pathcat(&fspec[0], sizeof(fspec), dir, file);
if (fexist(pc))
return true;
}
return false;
}
#define INTWIDTH (sizeof(int) * 3)
char * int_asc(int i)
/* integer to translate to a string */
{
static char result[INTWIDTH+2];
memset(&result, ' ', INTWIDTH);
{ char *sp = &result[INTWIDTH+1];
int v = i; /* sign of resulting number */
if (v < 0)
v = -v;
*sp = 0;
do
{ *(--sp) = '0' + v % 10; /* and install the new digit */
v = v / 10;
} while (v);
if (i < 0)
*(--sp) = '-'; /* and install the minus sign */
return sp;
}}
char * g_invokenm;
void flook_init(char * cmd)
{ g_invokenm = _strdup(cmd);
if (g_invokenm[0] == '"')
{ ++g_invokenm;
g_invokenm[strlen(g_invokenm)-1] = 0;
}
{ char * sp;
for (sp = g_invokenm; *sp != 0 && *sp != ' '; ++sp)
if (*sp == '\')
*sp = '/';
if (*sp != 0)
*sp = 0;
}}
/* wh == I =>
Look up the existence of a file in the current working directory ||
along the include path in the INCLDIRS environment variable.
wh == E =>
Look up the existence of a file in the current working directory ||
along the normal $PATH
else
if wh is in uppercase then look first in the $HOME directory
always look up a file along the normal $PATH.
*/
const char * flook(char wh, const char * fname)
{ char uwh = toupper(wh);
register char *path; /* environmental PATH variable */
// char buf[100];
if (fexist(fname))
return fname;
/* if we have an absolute path check only there! */
if (*fname == '\' || *fname == '/' ||
*fname != 0 && fname[1] == ':')
return nullptr;
//loglog1("not so far %s", fname);
if (fname != g_invokenm)
{ if (fex_path(flook('E', g_invokenm), fname))
return fspec;
}
path = getenv("PATH");
if (path != nullptr)
for (; *path != 0; ++path)
{ int ix;
if (path[0] == '-' && path[1] == 'I'
|| path[0] == '.' && path[1] == '/')
path += 2;
/* fspec[0] = 0;
if (inclmod != nullptr && path[0] != '/')
strcpy(&fspec[0], inclmod);
*/
for (ix = -1; ix < (int)sizeof(fspec)-2 &&
*path != 0
&& *path != PATHCHR
; )
fspec[++ix] = *path++;
if (path[-1] != DIRSEPCHAR)
fspec[++ix] = '/';
fspec[ix+1] = 0;
/* { char buf[200];
strcat(strcat((buf, "PATHE "),fspec);
MessageBox(nullptr, buf, "pe",MB_YESNO|MB_ICONQUESTION);
} */
if (fex_path(fspec, fname))
return fspec;
if (*path == 0)
break;
}
return nullptr; /* no such luck */
}
char * mkTempName (/*out*/char *buf, const char *name)
{
#ifdef _CONVDIR_CHAR
#define DIRY_CHAR _CONVDIR_CHAR
#else
#define DIRY_CHAR DIRSEPCHAR
#endif
static const char *tmpDir = NULL ;
char c2[2];
const char * td = tmpDir != NULL ? tmpDir : (char *)getenv("TEMP");
c2[0] = c2[1] = 0;
if (td == NULL)
#if (defined _DOS) || (defined _WIN32)
/* the C drive : better than ./ as ./ could be on a CD-Rom etc */
td = "c:\" ;
#else
td = "./" ;
#endif
else
if (td[strlen(td)-1] != DIRY_CHAR)
c2[0] = DIRY_CHAR;
tmpDir = td;
concat(buf,td,c2,"me",int_asc(_getpid()),name,0);
return &buf[strlen(buf)];
}
#define DUMMY_STDIN_FILE "stdin.~~~"
HANDLE CreateF(char * filenm)
{ int gen = GENERIC_WRITE;
int share = FILE_SHARE_WRITE;
int cmd = CREATE_ALWAYS;
HANDLE Hdl;
int ct = 2;
(void)mkTempName(filenm, DUMMY_STDIN_FILE);
for (; ;)
{ Hdl = CreateFile(filenm,gen,share,NULL,
cmd,FILE_ATTRIBUTE_NORMAL,NULL);
if (--ct == 0)
break;
if (Hdl >= 0) /* VALID_HANDLE_VALUE */
CloseHandle(Hdl);
gen = GENERIC_READ;
share = FILE_SHARE_READ;
cmd = OPEN_ALWAYS;
}
return Hdl;
}
bool v_opt = false;
void mbwrite(const char * msg)
{ if (v_opt)
printf("%s
", msg);
}
void flagerr(const char * fmt)
{ DWORD ec = GetLastError();
fprintf(stderr, fmt, ec);
}
void ErrorMessage(const char *str) //display detailed error info
{ LPVOID msg;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &msg,
0,
NULL
);
fprintf(stderr, "%s: %s
",str, (const char*)msg);
LocalFree(msg);
}
void setMyConsoleIP()
{ HANDLE ConsIn = GetStdHandle( STD_INPUT_HANDLE );
if (ConsIn < 0) /* INVALID_HANDLE_VALUE */
flagerr("Piperr %d");
/* SetStdHandle( STD_INPUT_HANDLE, g_ConsIn ); */
if (0 == SetConsoleMode(ConsIn, ENABLE_WINDOW_INPUT))
flagerr("PipeC %d");
}
class Pipe
{ public:
enum Modes { WL_IHAND = 1,
WL_SHELL = 2,
WL_AWAIT_PROMPT = 4,
WL_HOLD = 8,
WL_CNC = CREATE_NEW_CONSOLE,
WL_CNPG = CREATE_NEW_PROCESS_GROUP,
WL_SPAWN = 0x1000,
WL_SHOWW = 0x2000,
WL_NOIHAND = 0x4000 };
typedef unsigned int CmdMode;
static int menu[4];
#if _MSC_VER >= 1900
static_assert(WL_CNC > WL_HOLD && WL_CNPG > WL_HOLD);
#endif
static
Cc WinLaunch(Cc & sysRet, CmdMode flags,
const char *app = nullptr, const char * ca = nullptr,
const char * in_data = nullptr,
HANDLE ip = 0, const char *outfile = 0); // char *outErr,
};
Cc Pipe::WinLaunch(Cc & sysRet, CmdMode flags,
const char *app, const char * ca,
const char * in_data,
HANDLE ip, const char *outfile) // char *outErr,
{ char buff[1024]; //i/o buffer
const char * fapp = app == nullptr ? nullptr : flook('P', app);
if (fapp != nullptr) // never use comspec
app = fapp;
else if (flags & WL_SHELL)
{ const char * comSpecName = (char*)getenv("COMSPEC");
if (comSpecName == nullptr)
comSpecName = "cmd.exe";
if (ca == nullptr)
{ app = nullptr;
ca = comSpecName;
}
else /* Create the command line */
{ int len = strlen(concat(buff," /c "", app == nullptr ? "" : app,0));
char * dd = buff+len;
char ch;
char prev = 'A';
const char * ss = ca;
if (len+strlen(ss) >= sizeof(buff))
return -1;
for (; (ch = *ss++); prev = ch)
{ if (ch == '/' && // &&!(flags & LAUNCH_LEAVENAMES)
(in_range(toupper(prev), 'A','Z')
|| in_range(prev, '0', '9')
|| prev == '_' || prev == ' '))
ch = '\';
if (ch == '"')
*dd++ = '\';
*dd++ = ch;
}
*dd = '"';
dd[1] = 0;
ca = buff;
app = comSpecName;
}