#define DIAGNOSTIC 0
#include <process.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <string.h>
#include <fcntl.h>
#include "config.h"
#include "os2inc.h"
#define LL_VAL ULONG
#define LL_KEY PID
#define STDIN 0
#define STDOUT 1
#define STDERR 2
struct pid_list
{
HFILE pid;
ULONG term_code;
struct pid_list *next;
};
static struct pid_list *pid_ll = (struct pid_list *) NULL;
void
ll_insert (HFILE key, ULONG val)
{
struct pid_list *new;
new = (struct pid_list *) xmalloc (sizeof (*new));
new->pid = key;
new->term_code = val;
new->next = pid_ll;
pid_ll = new;
}
void
ll_delete (int key)
{
struct pid_list *this, *last;
this = pid_ll;
last = (struct pid_list *) NULL;
while (this)
{
if (this->pid == key)
{
if (last)
last->next = this->next;
else
pid_ll = this->next;
free (this);
return;
}
last = this;
this = this->next;
}
}
ULONG
ll_lookup (HFILE key)
{
struct pid_list *this = pid_ll;
while (this)
{
if (this->pid == key)
return this->term_code;
this = this->next;
}
return 0;
}
#if DIAGNOSTIC
ULONG
ll_length ()
{
struct pid_list *this = pid_ll;
unsigned long int len;
for (len = 0; this; len++)
this = this->next;
return len;
}
ULONG
ll_print ()
{
struct pid_list *this = pid_ll;
unsigned long int i;
for (i = 0; this; i++)
{
printf ("pid_ll[%d] == (%5d --> %5d)\n",
i, this->pid, this->term_code);
this = this->next;
}
if (i == 0)
printf ("No entries.\n");
return i;
}
#endif
FILE *
popen (const char *Command, const char *Mode)
{
HFILE End1, End2, Std, Old1, Old2, Tmp;
FILE *File;
char Fail[256],
*Args,
CmdLine[256],
*CmdExe;
RESULTCODES
Result;
int Rc;
if (DosCreatePipe (&End1, &End2, 4096))
return NULL;
Std = (*Mode == 'w') ? STDIN : STDOUT ;
if (Std == STDIN)
{
Tmp = End1; End1 = End2; End2 = Tmp;
}
Old1 = -1;
DosDupHandle (Std, &Old1);
DosSetFHState (Old1, OPEN_FLAGS_NOINHERIT);
Tmp = Std;
DosDupHandle (End2, &Tmp);
if (Std == 1)
{
Old2 = -1;
DosDupHandle (STDERR, &Old2);
DosSetFHState (Old2, OPEN_FLAGS_NOINHERIT);
Tmp = STDERR;
DosDupHandle (End2, &Tmp);
}
DosClose (End2);
DosSetFHState (End1, OPEN_FLAGS_NOINHERIT);
if ((CmdExe = getenv ("COMSPEC")) == NULL )
CmdExe = "cmd.exe";
strcpy (CmdLine, CmdExe);
Args = CmdLine + strlen (CmdLine) + 1;
strcpy (Args, "/c ");
strcat (Args, Command);
Args[strlen (Args) + 1] = '\0';
Rc = DosExecPgm (Fail, sizeof (Fail), EXEC_ASYNCRESULT,
(unsigned char *) CmdLine, 0, &Result,
(unsigned char *) CmdExe);
Tmp = Std;
DosDupHandle (Old1, &Tmp);
DosClose (Old1);
if (Std == STDOUT)
{
Tmp = STDERR;
DosDupHandle (Old2, &Tmp);
DosClose (Old2);
}
if (Rc)
{
DosClose (End1);
return NULL;
}
#ifdef __WATCOMC__
File = fdopen (_hdopen (End1, *Mode == 'w'? O_WRONLY : O_RDONLY), Mode);
#else
File = fdopen (End1, Mode);
#endif
ll_insert ((LL_KEY) End1, (LL_VAL) Result.codeTerminate);
return File;
}
int
popenRW (const char **argv, int *pipes)
{
HFILE Out1, Out2, In1, In2;
HFILE Old0 = -1, Old1 = -1, Old2 = -1, Tmp;
int pid;
if (DosCreatePipe (&Out2, &Out1, 4096))
return FALSE;
if (DosCreatePipe (&In1, &In2, 4096))
{
DosClose (Out1);
DosClose (Out2);
return FALSE;
}
DosDupHandle (STDIN, &Old0);
DosSetFHState (Old1, OPEN_FLAGS_NOINHERIT);
DosDupHandle (STDOUT, &Old1);
DosSetFHState (Old2, OPEN_FLAGS_NOINHERIT);
DosDupHandle (STDERR, &Old2);
DosSetFHState (Old2, OPEN_FLAGS_NOINHERIT);
Tmp = STDIN;
DosDupHandle (In1, &Tmp);
Tmp = STDOUT;
DosDupHandle (Out1, &Tmp);
Tmp = STDERR;
DosDupHandle (Out1, &Tmp);
DosClose (In1);
DosClose (Out1);
DosSetFHState (In2, OPEN_FLAGS_NOINHERIT);
DosSetFHState (Out2, OPEN_FLAGS_NOINHERIT);
pid = spawnvp (P_NOWAIT, argv[0], argv);
Tmp = STDIN;
DosDupHandle (Old0, &Tmp);
DosClose (Old0);
Tmp = STDOUT;
DosDupHandle (Old1, &Tmp);
DosClose (Old1);
Tmp = STDERR;
DosDupHandle (Old2, &Tmp);
DosClose (Old2);
if(pid < 0)
{
DosClose (In2);
DosClose (Out2);
return -1;
}
pipes[0] = In2;
_setmode (pipes[0], O_BINARY);
pipes[1] = Out2;
_setmode (pipes[1], O_BINARY);
ll_insert ((LL_KEY) In2, (LL_VAL) pid);
return pid;
}
int
pclose (FILE *Pipe)
{
RESULTCODES rc;
PID pid, pid1;
int Handle = fileno (Pipe);
fclose (Pipe);
rc.codeTerminate = -1;
pid1 = (PID) ll_lookup ((LL_KEY) Handle);
if (pid1 != 0)
{
DosWaitChild (DCWA_PROCESSTREE, DCWW_WAIT, &rc, &pid, pid1);
ll_delete ((LL_KEY) Handle);
}
return rc.codeTerminate == 0 ? rc.codeResult : -1;
}
#if DIAGNOSTIC
void
main ()
{
FILE *fp1, *fp2, *fp3;
int c;
ll_print ();
fp1 = popen ("gcc --version", "r");
ll_print ();
fp2 = popen ("link386 /?", "r");
ll_print ();
fp3 = popen ("dir", "r");
ll_print ();
while ((c = getc (fp1)) != EOF)
printf ("%c", c);
while ((c = getc (fp2)) != EOF)
printf ("%c", c);
while ((c = getc (fp3)) != EOF)
printf ("%c", c);
pclose (fp1);
ll_print ();
pclose (fp2);
ll_print ();
pclose (fp3);
ll_print ();
return;
}
#endif