(root)/
gawk-5.2.2/
pc/
popen.c
       1  /*
       2   * Copyright (C) 2010, 2013, 2014, 2016, the Free Software Foundation, Inc.
       3   *
       4   * This file is part of GAWK, the GNU implementation of the
       5   * AWK Programming Language.
       6   *
       7   * GAWK is free software; you can redistribute it and/or modify
       8   * it under the terms of the GNU General Public License as published by
       9   * the Free Software Foundation; either version 3 of the License, or
      10   * (at your option) any later version.
      11   *
      12   * GAWK is distributed in the hope that it will be useful,
      13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15   * GNU General Public License for more details.
      16   *
      17   * You should have received a copy of the GNU General Public License
      18   * along with this program; if not, write to the Free Software
      19   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
      20   */
      21  
      22  #include <stdio.h>
      23  #include <stdlib.h>
      24  #include <io.h>
      25  #include <string.h>
      26  #include <process.h>
      27  #include <errno.h>
      28  #include "popen.h"
      29  #undef popen
      30  #undef pclose
      31  #undef system
      32  
      33  #ifndef _NFILE
      34  #define _NFILE 40
      35  #endif
      36  
      37  static struct {
      38    char *command;
      39    char *name;
      40    char pmode[4];
      41  } pipes[_NFILE];
      42  
      43  
      44  /*
      45   * For systems where system() and popen() do not follow SHELL:
      46   *  1. Write command to temp file.  Temp filename must have slashes
      47   *     compatible with SHELL (if set) or COMSPEC.
      48   *  2. Convert slashes in SHELL (if present) to be compatible with COMSPEC.
      49   * Currently, only MSC (running under DOS) and MINGW versions are managed.
      50   */
      51  
      52  #if defined(__MINGW32__)
      53  
      54  #define WIN32_LEAN_AND_MEAN
      55  #include <windows.h>
      56  
      57  #if 0
      58  static int
      59  unixshell(char *p)
      60  {
      61    static char *shell[] = {"sh", "bash", "csh", "tcsh", "sh32", "sh16", "ksh", NULL};
      62    char **shellp = shell, *s, *q;
      63  
      64    if (p == NULL) return (0);
      65    s = p = strdup(p);
      66    if ((q = strrchr(p, '\\')) != NULL)
      67      p = q + 1;
      68    if ((q = strrchr(p, '/')) != NULL)
      69      p = q + 1;
      70    if ((q = strchr(p, '.')) != NULL)
      71      *q = '\0';
      72    strlwr(p);
      73    do {
      74      if (strcmp(*shellp, p) == 0) break;
      75    } while (*++shellp);
      76    free(s);
      77    return(*shellp ? 1 : 0);
      78  }
      79  
      80  static char *
      81  slashify(char *p, char *s)
      82  {
      83    if (unixshell(s))
      84      while (s = strchr(p, '\\')) *s = '/';
      85    else
      86      while (s = strchr(p, '/')) *s = '\\';
      87    return(p);
      88  }
      89  
      90  static char *
      91  scriptify(const char *command)
      92  {
      93    FILE *fp;
      94    char *cmd, *name, *s, *p;
      95    int i;
      96  
      97    if((name = tempnam(".", "pip")) == NULL) return(NULL);
      98    p = getenv("COMSPEC"); s = getenv("SHELL");
      99    cmd = malloc(strlen(name) + (s ? strlen(s) : 0) + 9); *cmd = '\0';
     100    if (s) {
     101      slashify(strcpy(cmd, s), p);
     102      p = s;
     103    }
     104    slashify(name, p);
     105    if (! (i = unixshell(p))) {
     106      char *p = (char *) realloc(name, strlen(name) + 5);
     107      if (p == NULL) {
     108  	free(cmd);
     109  	return NULL;
     110      }
     111      name = p;
     112      strcat(name, ".bat");
     113    }
     114    if (s) sprintf(cmd + strlen(cmd), " %cc ", unixshell(s) ? '-' : '/');
     115    strcpy(p = cmd + strlen(cmd), name); free(name);
     116  
     117    if ((fp = fopen(p, i ? "wb" : "w")) != NULL) {
     118      if (! i) fputs("@echo off\n", fp);
     119      i = strlen(command);
     120      if ((fwrite(command, 1, i, fp) < i) || (fputc('\n', fp) == EOF)) {
     121        free(cmd);
     122        cmd = NULL;
     123      }
     124    } else {
     125      free(cmd);
     126      cmd = NULL;
     127    }
     128    if (fp) fclose(fp);
     129    return(cmd);
     130  }
     131  
     132  static void
     133  unlink_and_free(char *cmd)
     134  {
     135    char *s;
     136  
     137    if (s = strrchr(cmd, ' '))
     138      s++;
     139    else
     140      s = cmd;
     141    unlink(s); free(cmd);
     142  }
     143  #endif
     144  
     145  int
     146  os_system(const char *cmd)
     147  {
     148    char *cmdexe = getenv("ComSpec");
     149    char *cmd1 = quote_cmd(cmd);
     150    int i = spawnl(P_WAIT, cmdexe, "cmd.exe", "/c", cmd1, NULL);
     151  
     152    free(cmd1);
     153    return(i);
     154  }
     155  
     156  #ifndef PIPES_SIMULATED
     157  int
     158  kill (int pid, int sig)
     159  {
     160    HANDLE ph;
     161    int retval = 0;
     162  
     163    /* We only support SIGKILL.  */
     164    if (sig != SIGKILL)
     165      {
     166        errno = ENOSYS;
     167        return -1;
     168      }
     169  
     170    ph = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
     171    if (ph)
     172      {
     173        BOOL status = TerminateProcess(ph, -1);
     174  
     175        if (!status)
     176  	{
     177  	  errno = EPERM;
     178  	  retval = -1;
     179  	}
     180      }
     181    else
     182      {
     183        /* If we cannot open the process, it means we eaither aren't
     184  	 allowed to (e.g., a process of another user), or such a
     185  	 process doesn't exist.  */
     186        switch (GetLastError ())
     187  	{
     188  	  case ERROR_ACCESS_DENIED:
     189  	    errno = EPERM;
     190  	    break;
     191  	  default:
     192  	    errno = ESRCH;
     193  	    break;
     194  	}
     195        retval = -1;
     196      }
     197    CloseHandle (ph);
     198    return retval;
     199  }
     200  
     201  char *
     202  quote_cmd(const char *cmd)
     203  {
     204    char *quoted;
     205  
     206    /* The command will be invoked via cmd.exe, whose behavior wrt
     207       quoted commands is to remove the first and the last quote
     208       characters, and leave the rest (including any quote characters
     209       inside the outer pair) intact.  */
     210    quoted = malloc(strlen (cmd) + 2 + 1);
     211    sprintf(quoted, "\"%s\"", cmd);
     212  
     213    return quoted;
     214  }
     215  #endif
     216  
     217  #else  /* !__MINGW32__ */
     218  #define os_system(cmd) system(cmd)
     219  #endif
     220  
     221  
     222  FILE *
     223  os_popen(const char *command, const char *mode )
     224  {
     225      FILE *current;
     226      char *name;
     227      int cur;
     228      char curmode[4];
     229  
     230      if (*mode != 'r' && *mode != 'w')
     231        return NULL;
     232      strncpy(curmode, mode, 3); curmode[3] = '\0';
     233  
     234  #if defined(__MINGW32__)
     235      current = popen(command, mode);
     236      cur = fileno(current);
     237      strcpy(pipes[cur].pmode, curmode);
     238      return(current);
     239  #endif
     240  
     241      /*
     242      ** get a name to use.
     243      */
     244      if((name = tempnam(".","pip"))==NULL)
     245          return NULL;
     246      /*
     247      ** If we're reading, just call system to get a file filled with
     248      ** output.
     249      */
     250      if (*curmode == 'r') {
     251          FILE *fp;
     252          if ((cur = dup(fileno(stdout))) == -1)
     253  	    return NULL;
     254  	*curmode = 'w';
     255          if ((current = freopen(name, curmode, stdout)) == NULL)
     256  	    return NULL;
     257          os_system(command);
     258          if (dup2(cur, fileno(stdout)) == -1)
     259  	    return NULL;
     260  	close(cur);
     261  	*curmode = 'r';
     262          if ((current = fopen(name, curmode)) == NULL)
     263              return NULL;
     264      } else {
     265          if ((current = fopen(name, curmode)) == NULL)
     266              return NULL;
     267      }
     268      cur = fileno(current);
     269      pipes[cur].name = name;
     270      strcpy(pipes[cur].pmode, curmode);
     271      pipes[cur].command = strdup(command);
     272      return current;
     273  }
     274  
     275  int
     276  os_pclose( FILE * current)
     277  {
     278      int cur = fileno(current);
     279      int fd, rval;
     280  
     281  #if defined(__MINGW32__)
     282      rval = pclose(current);
     283      *pipes[cur].pmode = '\0';
     284      return rval;
     285  #endif
     286  
     287      /*
     288      ** check for an open file.
     289      */
     290      switch (*pipes[cur].pmode) {
     291      case 'r':
     292          /*
     293          ** input pipes are just files we're done with.
     294          */
     295          rval = fclose(current);
     296          unlink(pipes[cur].name);
     297  	break;
     298      case 'w':
     299          /*
     300          ** output pipes are temporary files we have
     301          ** to cram down the throats of programs.
     302          */
     303          fclose(current);
     304  	rval = -1;
     305  	if ((fd = dup(fileno(stdin))) != -1) {
     306  	  char *mode = pipes[cur].pmode; *mode = 'r';
     307  	  if (current = freopen(pipes[cur].name, mode, stdin)) {
     308  	    rval = os_system(pipes[cur].command);
     309  	    fclose(current);
     310  	    if (dup2(fd, fileno(stdin)) == -1) rval = -1;
     311  	    close(fd);
     312  	  }
     313  	}
     314          unlink(pipes[cur].name);
     315  	break;
     316      default:
     317        return -1;
     318      }
     319      /*
     320      ** clean up current pipe.
     321      */
     322      *pipes[cur].pmode = '\0';
     323      free(pipes[cur].name);
     324      free(pipes[cur].command);
     325      return rval;
     326  }