/* 
 * Do system/popen with real gid, but retain 'mail' as egid afterwards
 * uses the 'native' shell for system
 */

#include <stdio.h>
#include <signal.h>

#define   tst(a,b) (*mode == 'r'? (b) : (a))
#define   RDR   0
#define   WTR   1

extern FILE *fdopen();
extern int execl(), fork(), pipe(), close(), fcntl();
static int popen_pid[20];

FILE *
mypopen(cmd,mode)
char   *cmd;
char   *mode;
{
   int p[2];
   register int myside, hisside, pid;

   if(pipe(p) < 0)
      return NULL;
   myside = tst(p[WTR], p[RDR]);
   hisside = tst(p[RDR], p[WTR]);
   if ((pid = fork()) == 0) {
      /* myside and hisside reverse roles in child */
      int   stdio;
      stdio = tst(0, 1);
      (void) close(myside);
      (void) close(stdio);
      (void) fcntl(hisside, 0, stdio);
      (void) close(hisside);
      setgid(getgid());   /* restore real group ID in child */
      execl("/bin/sh", "sh", "-c", cmd, 0);
      _exit(1);
   }
   if(pid == -1) {
      close(myside);
      close(hisside);
      return NULL;
   }
   popen_pid[myside] = pid;
   close(hisside);
   return(fdopen(myside, mode));
}

int
mypclose(ptr)
FILE   *ptr;
{
   register int f, r;
   int status, (*hstat)(), (*istat)(), (*qstat)();

   f = fileno(ptr);
   (void) fclose(ptr);
   istat = signal(SIGINT, SIG_IGN);
   qstat = signal(SIGQUIT, SIG_IGN);
   hstat = signal(SIGHUP, SIG_IGN);
   while ((r = wait(&status)) != popen_pid[f] && r != -1)
      ;
   if (r == -1)
      status = -1;
   (void) signal(SIGINT, istat);
   (void) signal(SIGQUIT, qstat);
   (void) signal(SIGHUP, hstat);
   return(status);
}

mysystem(s)
char *s;
{
   int status, pid, w;
   register int (*istat)(), (*qstat)();
   char *shell, *shellpath, *flags, *getenv(), *strrchr();

   shellpath = getenv("SHELL");
   if (shellpath == NULL || strlen(shellpath) == 0)
      shellpath = "/bin/sh";
   shell = strrchr(shellpath, '/') + 1;
   if (!strcmp(shell, "sh"))
      flags = "-c";
   else
      flags = "-fc";

   if ((pid = fork()) == 0) {
      setgid(getgid());   /* restore real group ID in child */
      execl(shellpath, shell, flags, s, 0);
      _exit(127);
   }
   istat = signal(SIGINT, SIG_IGN);
   qstat = signal(SIGQUIT, SIG_IGN);
   while ((w = wait(&status)) != pid && w != -1)
      ;
   if (w == -1)
      status = -1;
   signal(SIGINT, istat);
   signal(SIGQUIT, qstat);
   return(status);
}
