Blame pc/popen.c

Packit Service f629e6
#include <stdio.h>
Packit Service f629e6
#include <stdlib.h>
Packit Service f629e6
#include <io.h>
Packit Service f629e6
#include <string.h>
Packit Service f629e6
#include <process.h>
Packit Service f629e6
#include <errno.h>
Packit Service f629e6
#include "popen.h"
Packit Service f629e6
#undef popen
Packit Service f629e6
#undef pclose
Packit Service f629e6
#undef system
Packit Service f629e6
Packit Service f629e6
#ifndef _NFILE
Packit Service f629e6
#define _NFILE 40
Packit Service f629e6
#endif
Packit Service f629e6
Packit Service f629e6
static struct {
Packit Service f629e6
  char *command;
Packit Service f629e6
  char *name;
Packit Service f629e6
  char pmode[4];
Packit Service f629e6
} pipes[_NFILE];
Packit Service f629e6
Packit Service f629e6
Packit Service f629e6
/*
Packit Service f629e6
 * For systems where system() and popen() do not follow SHELL:
Packit Service f629e6
 *  1. Write command to temp file.  Temp filename must have slashes
Packit Service f629e6
 *     compatible with SHELL (if set) or COMSPEC.
Packit Service f629e6
 *  2. Convert slashes in SHELL (if present) to be compatible with COMSPEC.
Packit Service f629e6
 * Currently, only MSC (running under DOS) and MINGW versions are managed.
Packit Service f629e6
 */
Packit Service f629e6
Packit Service f629e6
#if defined(__MINGW32__)
Packit Service f629e6
Packit Service f629e6
#define WIN32_LEAN_AND_MEAN
Packit Service f629e6
#include <windows.h>
Packit Service f629e6
Packit Service f629e6
#if 0
Packit Service f629e6
static int
Packit Service f629e6
unixshell(char *p)
Packit Service f629e6
{
Packit Service f629e6
  static char *shell[] = {"sh", "bash", "csh", "tcsh", "sh32", "sh16", "ksh", NULL};
Packit Service f629e6
  char **shellp = shell, *s, *q;
Packit Service f629e6
Packit Service f629e6
  if (p == NULL) return (0);
Packit Service f629e6
  s = p = strdup(p);
Packit Service f629e6
  if ((q = strrchr(p, '\\')) != NULL)
Packit Service f629e6
    p = q + 1;
Packit Service f629e6
  if ((q = strrchr(p, '/')) != NULL)
Packit Service f629e6
    p = q + 1;
Packit Service f629e6
  if ((q = strchr(p, '.')) != NULL)
Packit Service f629e6
    *q = '\0';
Packit Service f629e6
  strlwr(p);
Packit Service f629e6
  do {
Packit Service f629e6
    if (strcmp(*shellp, p) == 0) break;
Packit Service f629e6
  } while (*++shellp);
Packit Service f629e6
  free(s);
Packit Service f629e6
  return(*shellp ? 1 : 0);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
static char *
Packit Service f629e6
slashify(char *p, char *s)
Packit Service f629e6
{
Packit Service f629e6
  if (unixshell(s))
Packit Service f629e6
    while (s = strchr(p, '\\')) *s = '/';
Packit Service f629e6
  else
Packit Service f629e6
    while (s = strchr(p, '/')) *s = '\\';
Packit Service f629e6
  return(p);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
static char *
Packit Service f629e6
scriptify(const char *command)
Packit Service f629e6
{
Packit Service f629e6
  FILE *fp;
Packit Service f629e6
  char *cmd, *name, *s, *p;
Packit Service f629e6
  int i;
Packit Service f629e6
Packit Service f629e6
  if((name = tempnam(".", "pip")) == NULL) return(NULL);
Packit Service f629e6
  p = getenv("COMSPEC"); s = getenv("SHELL");
Packit Service f629e6
  cmd = malloc(strlen(name) + (s ? strlen(s) : 0) + 9); *cmd = '\0';
Packit Service f629e6
  if (s) {
Packit Service f629e6
    slashify(strcpy(cmd, s), p);
Packit Service f629e6
    p = s;
Packit Service f629e6
  }
Packit Service f629e6
  slashify(name, p);
Packit Service f629e6
  if (! (i = unixshell(p))) {
Packit Service f629e6
    char *p = (char *) realloc(name, strlen(name) + 5);
Packit Service f629e6
    if (p == NULL) {
Packit Service f629e6
	free(cmd);
Packit Service f629e6
	return NULL;
Packit Service f629e6
    }
Packit Service f629e6
    name = p;
Packit Service f629e6
    strcat(name, ".bat");
Packit Service f629e6
  }
Packit Service f629e6
  if (s) sprintf(cmd + strlen(cmd), " %cc ", unixshell(s) ? '-' : '/');
Packit Service f629e6
  strcpy(p = cmd + strlen(cmd), name); free(name);
Packit Service f629e6
Packit Service f629e6
  if ((fp = fopen(p, i ? "wb" : "w")) != NULL) {
Packit Service f629e6
    if (! i) fputs("@echo off\n", fp);
Packit Service f629e6
    i = strlen(command);
Packit Service f629e6
    if ((fwrite(command, 1, i, fp) < i) || (fputc('\n', fp) == EOF)) {
Packit Service f629e6
      free(cmd);
Packit Service f629e6
      cmd = NULL;
Packit Service f629e6
    }
Packit Service f629e6
  } else {
Packit Service f629e6
    free(cmd);
Packit Service f629e6
    cmd = NULL;
Packit Service f629e6
  }
Packit Service f629e6
  if (fp) fclose(fp);
Packit Service f629e6
  return(cmd);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
static void
Packit Service f629e6
unlink_and_free(char *cmd)
Packit Service f629e6
{
Packit Service f629e6
  char *s;
Packit Service f629e6
Packit Service f629e6
  if (s = strrchr(cmd, ' '))
Packit Service f629e6
    s++;
Packit Service f629e6
  else
Packit Service f629e6
    s = cmd;
Packit Service f629e6
  unlink(s); free(cmd);
Packit Service f629e6
}
Packit Service f629e6
#endif
Packit Service f629e6
Packit Service f629e6
int
Packit Service f629e6
os_system(const char *cmd)
Packit Service f629e6
{
Packit Service f629e6
  char *cmdexe = getenv("ComSpec");
Packit Service f629e6
  char *cmd1 = quote_cmd(cmd);
Packit Service f629e6
  int i = spawnl(P_WAIT, cmdexe, "cmd.exe", "/c", cmd1, NULL);
Packit Service f629e6
Packit Service f629e6
  free(cmd1);
Packit Service f629e6
  return(i);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
#ifndef PIPES_SIMULATED
Packit Service f629e6
int
Packit Service f629e6
kill (int pid, int sig)
Packit Service f629e6
{
Packit Service f629e6
  HANDLE ph;
Packit Service f629e6
  int retval = 0;
Packit Service f629e6
Packit Service f629e6
  /* We only support SIGKILL.  */
Packit Service f629e6
  if (sig != SIGKILL)
Packit Service f629e6
    {
Packit Service f629e6
      errno = ENOSYS;
Packit Service f629e6
      return -1;
Packit Service f629e6
    }
Packit Service f629e6
Packit Service f629e6
  ph = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
Packit Service f629e6
  if (ph)
Packit Service f629e6
    {
Packit Service f629e6
      BOOL status = TerminateProcess(ph, -1);
Packit Service f629e6
Packit Service f629e6
      if (!status)
Packit Service f629e6
	{
Packit Service f629e6
	  errno = EPERM;
Packit Service f629e6
	  retval = -1;
Packit Service f629e6
	}
Packit Service f629e6
    }
Packit Service f629e6
  else
Packit Service f629e6
    {
Packit Service f629e6
      /* If we cannot open the process, it means we eaither aren't
Packit Service f629e6
	 allowed to (e.g., a process of another user), or such a
Packit Service f629e6
	 process doesn't exist.  */
Packit Service f629e6
      switch (GetLastError ())
Packit Service f629e6
	{
Packit Service f629e6
	  case ERROR_ACCESS_DENIED:
Packit Service f629e6
	    errno = EPERM;
Packit Service f629e6
	    break;
Packit Service f629e6
	  default:
Packit Service f629e6
	    errno = ESRCH;
Packit Service f629e6
	    break;
Packit Service f629e6
	}
Packit Service f629e6
      retval = -1;
Packit Service f629e6
    }
Packit Service f629e6
  CloseHandle (ph);
Packit Service f629e6
  return retval;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
char *
Packit Service f629e6
quote_cmd(const char *cmd)
Packit Service f629e6
{
Packit Service f629e6
  char *quoted;
Packit Service f629e6
Packit Service f629e6
  /* The command will be invoked via cmd.exe, whose behavior wrt
Packit Service f629e6
     quoted commands is to remove the first and the last quote
Packit Service f629e6
     characters, and leave the rest (including any quote characters
Packit Service f629e6
     inside the outer pair) intact.  */
Packit Service f629e6
  quoted = malloc(strlen (cmd) + 2 + 1);
Packit Service f629e6
  sprintf(quoted, "\"%s\"", cmd);
Packit Service f629e6
Packit Service f629e6
  return quoted;
Packit Service f629e6
}
Packit Service f629e6
#endif
Packit Service f629e6
Packit Service f629e6
#else  /* !__MINGW32__ */
Packit Service f629e6
#define os_system(cmd) system(cmd)
Packit Service f629e6
#endif
Packit Service f629e6
Packit Service f629e6
Packit Service f629e6
FILE *
Packit Service f629e6
os_popen(const char *command, const char *mode )
Packit Service f629e6
{
Packit Service f629e6
    FILE *current;
Packit Service f629e6
    char *name;
Packit Service f629e6
    int cur;
Packit Service f629e6
    char curmode[4];
Packit Service f629e6
Packit Service f629e6
    if (*mode != 'r' && *mode != 'w')
Packit Service f629e6
      return NULL;
Packit Service f629e6
    strncpy(curmode, mode, 3); curmode[3] = '\0';
Packit Service f629e6
Packit Service f629e6
#if defined(__MINGW32__)
Packit Service f629e6
    current = popen(command, mode);
Packit Service f629e6
    cur = fileno(current);
Packit Service f629e6
    strcpy(pipes[cur].pmode, curmode);
Packit Service f629e6
    return(current);
Packit Service f629e6
#endif
Packit Service f629e6
Packit Service f629e6
    /*
Packit Service f629e6
    ** get a name to use.
Packit Service f629e6
    */
Packit Service f629e6
    if((name = tempnam(".","pip"))==NULL)
Packit Service f629e6
        return NULL;
Packit Service f629e6
    /*
Packit Service f629e6
    ** If we're reading, just call system to get a file filled with
Packit Service f629e6
    ** output.
Packit Service f629e6
    */
Packit Service f629e6
    if (*curmode == 'r') {
Packit Service f629e6
        FILE *fp;
Packit Service f629e6
        if ((cur = dup(fileno(stdout))) == -1)
Packit Service f629e6
	    return NULL;
Packit Service f629e6
	*curmode = 'w';
Packit Service f629e6
        if ((current = freopen(name, curmode, stdout)) == NULL)
Packit Service f629e6
	    return NULL;
Packit Service f629e6
        os_system(command);
Packit Service f629e6
        if (dup2(cur, fileno(stdout)) == -1)
Packit Service f629e6
	    return NULL;
Packit Service f629e6
	close(cur);
Packit Service f629e6
	*curmode = 'r';
Packit Service f629e6
        if ((current = fopen(name, curmode)) == NULL)
Packit Service f629e6
            return NULL;
Packit Service f629e6
    } else {
Packit Service f629e6
        if ((current = fopen(name, curmode)) == NULL)
Packit Service f629e6
            return NULL;
Packit Service f629e6
    }
Packit Service f629e6
    cur = fileno(current);
Packit Service f629e6
    pipes[cur].name = name;
Packit Service f629e6
    strcpy(pipes[cur].pmode, curmode);
Packit Service f629e6
    pipes[cur].command = strdup(command);
Packit Service f629e6
    return current;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
int
Packit Service f629e6
os_pclose( FILE * current)
Packit Service f629e6
{
Packit Service f629e6
    int cur = fileno(current);
Packit Service f629e6
    int fd, rval;
Packit Service f629e6
Packit Service f629e6
#if defined(__MINGW32__)
Packit Service f629e6
    rval = pclose(current);
Packit Service f629e6
    *pipes[cur].pmode = '\0';
Packit Service f629e6
    return rval;
Packit Service f629e6
#endif
Packit Service f629e6
Packit Service f629e6
    /*
Packit Service f629e6
    ** check for an open file.
Packit Service f629e6
    */
Packit Service f629e6
    switch (*pipes[cur].pmode) {
Packit Service f629e6
    case 'r':
Packit Service f629e6
        /*
Packit Service f629e6
        ** input pipes are just files we're done with.
Packit Service f629e6
        */
Packit Service f629e6
        rval = fclose(current);
Packit Service f629e6
        unlink(pipes[cur].name);
Packit Service f629e6
	break;
Packit Service f629e6
    case 'w':
Packit Service f629e6
        /*
Packit Service f629e6
        ** output pipes are temporary files we have
Packit Service f629e6
        ** to cram down the throats of programs.
Packit Service f629e6
        */
Packit Service f629e6
        fclose(current);
Packit Service f629e6
	rval = -1;
Packit Service f629e6
	if ((fd = dup(fileno(stdin))) != -1) {
Packit Service f629e6
	  char *mode = pipes[cur].pmode; *mode = 'r';
Packit Service f629e6
	  if (current = freopen(pipes[cur].name, mode, stdin)) {
Packit Service f629e6
	    rval = os_system(pipes[cur].command);
Packit Service f629e6
	    fclose(current);
Packit Service f629e6
	    if (dup2(fd, fileno(stdin)) == -1) rval = -1;
Packit Service f629e6
	    close(fd);
Packit Service f629e6
	  }
Packit Service f629e6
	}
Packit Service f629e6
        unlink(pipes[cur].name);
Packit Service f629e6
	break;
Packit Service f629e6
    default:
Packit Service f629e6
      return -1;
Packit Service f629e6
    }
Packit Service f629e6
    /*
Packit Service f629e6
    ** clean up current pipe.
Packit Service f629e6
    */
Packit Service f629e6
    *pipes[cur].pmode = '\0';
Packit Service f629e6
    free(pipes[cur].name);
Packit Service f629e6
    free(pipes[cur].command);
Packit Service f629e6
    return rval;
Packit Service f629e6
}