LTP GCOV extension - code coverage report
Current view: directory - ext/standard - exec.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 174
Code covered: 5.7 % Executed lines: 10
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2007 The PHP Group                                |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is subject to version 3.01 of the PHP license,      |
       8                 :    | that is bundled with this package in the file LICENSE, and is        |
       9                 :    | available through the world-wide-web at the following url:           |
      10                 :    | http://www.php.net/license/3_01.txt                                  |
      11                 :    | If you did not receive a copy of the PHP license and are unable to   |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@php.net so we can mail you a copy immediately.               |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Author: Rasmus Lerdorf <rasmus@php.net>                              |
      16                 :    |         Ilia Alshanetsky <iliaa@php.net>                             |
      17                 :    +----------------------------------------------------------------------+
      18                 :  */
      19                 : /* $Id: exec.c,v 1.113.2.3.2.1 2007/01/01 09:36:08 sebastian Exp $ */
      20                 : 
      21                 : #include <stdio.h>
      22                 : #include "php.h"
      23                 : #include <ctype.h>
      24                 : #include "php_string.h"
      25                 : #include "safe_mode.h"
      26                 : #include "ext/standard/head.h"
      27                 : #include "ext/standard/file.h"
      28                 : #include "exec.h"
      29                 : #include "php_globals.h"
      30                 : #include "SAPI.h"
      31                 : 
      32                 : #if HAVE_SYS_WAIT_H
      33                 : #include <sys/wait.h>
      34                 : #endif
      35                 : #if HAVE_SIGNAL_H
      36                 : #include <signal.h>
      37                 : #endif
      38                 : 
      39                 : #if HAVE_SYS_TYPES_H
      40                 : #include <sys/types.h>
      41                 : #endif
      42                 : #if HAVE_SYS_STAT_H
      43                 : #include <sys/stat.h>
      44                 : #endif
      45                 : #if HAVE_FCNTL_H
      46                 : #include <fcntl.h>
      47                 : #endif
      48                 : 
      49                 : #if HAVE_NICE && HAVE_UNISTD_H
      50                 : #include <unistd.h>
      51                 : #endif
      52                 : 
      53                 : /* {{{ php_exec
      54                 :  * If type==0, only last line of output is returned (exec)
      55                 :  * If type==1, all lines will be printed and last lined returned (system)
      56                 :  * If type==2, all lines will be saved to given array (exec with &$array)
      57                 :  * If type==3, output will be printed binary, no lines will be saved or returned (passthru)
      58                 :  *
      59                 :  */
      60                 : int php_exec(int type, char *cmd, zval *array, zval *return_value TSRMLS_DC)
      61               0 : {
      62                 :         FILE *fp;
      63               0 :         char *buf, *tmp=NULL;
      64                 :         int l, pclose_return;
      65               0 :         char *cmd_p, *b, *c, *d=NULL;
      66                 :         php_stream *stream;
      67               0 :         size_t buflen, bufl = 0;
      68                 : #if PHP_SIGCHILD
      69                 :         void (*sig_handler)() = NULL;
      70                 : #endif
      71                 : 
      72               0 :         if (PG(safe_mode)) {
      73               0 :                 if ((c = strchr(cmd, ' '))) {
      74               0 :                         *c = '\0';
      75               0 :                         c++;
      76                 :                 }
      77               0 :                 if (strstr(cmd, "..")) {
      78               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "No '..' components allowed in path");
      79               0 :                         goto err;
      80                 :                 }
      81               0 :                 b = strrchr(cmd, PHP_DIR_SEPARATOR);
      82               0 :                 spprintf(&d, 0, "%s%s%s%s%s", PG(safe_mode_exec_dir), (b ? "" : "/"), (b ? b : cmd), (c ? " " : ""), (c ? c : ""));
      83               0 :                 if (c) {
      84               0 :                         *(c - 1) = ' ';
      85                 :                 }
      86               0 :                 cmd_p = php_escape_shell_cmd(d);
      87               0 :                 efree(d);
      88               0 :                 d = cmd_p;
      89                 :         } else {
      90               0 :                 cmd_p = cmd;
      91                 :         }
      92                 : 
      93                 : #if PHP_SIGCHILD
      94                 :         sig_handler = signal (SIGCHLD, SIG_DFL);
      95                 : #endif
      96                 : 
      97                 : #ifdef PHP_WIN32
      98                 :         fp = VCWD_POPEN(cmd_p, "rb");
      99                 : #else
     100               0 :         fp = VCWD_POPEN(cmd_p, "r");
     101                 : #endif
     102               0 :         if (!fp) {
     103               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to fork [%s]", cmd);
     104               0 :                 goto err;
     105                 :         }
     106                 : 
     107               0 :         stream = php_stream_fopen_from_pipe(fp, "rb");
     108                 : 
     109               0 :         buf = (char *) emalloc(EXEC_INPUT_BUF);
     110               0 :         buflen = EXEC_INPUT_BUF;
     111                 : 
     112               0 :         if (type != 3) {
     113               0 :                 b = buf;
     114                 :                 
     115               0 :                 while (php_stream_get_line(stream, b, EXEC_INPUT_BUF, &bufl)) {
     116                 :                         /* no new line found, let's read some more */
     117               0 :                         if (b[bufl - 1] != '\n' && !php_stream_eof(stream)) {
     118               0 :                                 if (buflen < (bufl + (b - buf) + EXEC_INPUT_BUF)) {
     119               0 :                                         bufl += b - buf;
     120               0 :                                         buflen = bufl + EXEC_INPUT_BUF;
     121               0 :                                         buf = erealloc(buf, buflen);
     122               0 :                                         b = buf + bufl;
     123                 :                                 } else {
     124               0 :                                         b += bufl;
     125                 :                                 }
     126               0 :                                 continue;
     127               0 :                         } else if (b != buf) {
     128               0 :                                 bufl += b - buf;
     129                 :                         }
     130                 : 
     131               0 :                         if (type == 1) {
     132               0 :                                 PHPWRITE(buf, bufl);
     133               0 :                                 sapi_flush(TSRMLS_C);
     134               0 :                         } else if (type == 2) {
     135                 :                                 /* strip trailing whitespaces */        
     136               0 :                                 l = bufl;
     137               0 :                                 while (l-- && isspace(((unsigned char *)buf)[l]));
     138               0 :                                 if (l != (int)(bufl - 1)) {
     139               0 :                                         bufl = l + 1;
     140               0 :                                         buf[bufl] = '\0';
     141                 :                                 }
     142               0 :                                 add_next_index_stringl(array, buf, bufl, 1);
     143                 :                         }
     144               0 :                         b = buf;
     145                 :                 }
     146               0 :                 if (bufl) {
     147                 :                         /* strip trailing whitespaces if we have not done so already */ 
     148               0 :                         if (type != 2) {
     149               0 :                                 l = bufl;
     150               0 :                                 while (l-- && isspace(((unsigned char *)buf)[l]));
     151               0 :                                 if (l != (int)(bufl - 1)) {
     152               0 :                                         bufl = l + 1;
     153               0 :                                         buf[bufl] = '\0';
     154                 :                                 }
     155                 :                         }
     156                 : 
     157                 :                         /* Return last line from the shell command */
     158               0 :                         if (PG(magic_quotes_runtime)) {
     159                 :                                 int len;
     160                 :         
     161               0 :                                 tmp = php_addslashes(buf, bufl, &len, 0 TSRMLS_CC);
     162               0 :                                 RETVAL_STRINGL(tmp, len, 0);
     163                 :                         } else {
     164               0 :                                 RETVAL_STRINGL(buf, bufl, 1);
     165                 :                         }
     166                 :                 } else { /* should return NULL, but for BC we return "" */
     167               0 :                         RETVAL_EMPTY_STRING();
     168                 :                 }
     169                 :         } else {
     170               0 :                 while((bufl = php_stream_read(stream, buf, EXEC_INPUT_BUF)) > 0) {
     171               0 :                         PHPWRITE(buf, bufl);
     172                 :                 }
     173                 :         }
     174                 : 
     175               0 :         pclose_return = php_stream_close(stream); 
     176               0 :         efree(buf);
     177                 : 
     178               0 : done:
     179                 : #if PHP_SIGCHILD
     180                 :         if (sig_handler) {
     181                 :                 signal(SIGCHLD, sig_handler);
     182                 :         }
     183                 : #endif
     184               0 :         if (d) {
     185               0 :                 efree(d);
     186                 :         }
     187               0 :         return pclose_return;
     188               0 : err:
     189               0 :         pclose_return = -1;
     190               0 :         goto done;
     191                 : }
     192                 : /* }}} */
     193                 : 
     194                 : static void php_exec_ex(INTERNAL_FUNCTION_PARAMETERS, int mode)
     195               0 : {
     196                 :         char *cmd;
     197                 :         int cmd_len;
     198               0 :         zval *ret_code=NULL, *ret_array=NULL;
     199                 :         int ret;
     200                 : 
     201               0 :         if (mode) {
     202               0 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z/", &cmd, &cmd_len, &ret_code) == FAILURE) {
     203               0 :                         RETURN_FALSE;
     204                 :                 }
     205                 :         } else {
     206               0 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z/z/", &cmd, &cmd_len, &ret_array, &ret_code) == FAILURE) {
     207               0 :                         RETURN_FALSE;
     208                 :                 }
     209                 :         }
     210               0 :         if (!cmd_len) {
     211               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot execute a blank command");
     212               0 :                 RETURN_FALSE;
     213                 :         }
     214                 : 
     215               0 :         if (!ret_array) {
     216               0 :                 ret = php_exec(mode, cmd, NULL, return_value TSRMLS_CC);
     217                 :         } else {
     218               0 :                 if (Z_TYPE_P(ret_array) != IS_ARRAY) {
     219               0 :                         zval_dtor(ret_array);
     220               0 :                         array_init(ret_array);
     221                 :                 }
     222               0 :                 ret = php_exec(2, cmd, ret_array, return_value TSRMLS_CC);
     223                 :         }
     224               0 :         if (ret_code) {
     225               0 :                 zval_dtor(ret_code);
     226               0 :                 ZVAL_LONG(ret_code, ret);
     227                 :         }
     228                 : }
     229                 : 
     230                 : /* {{{ proto string exec(string command [, array &output [, int &return_value]])
     231                 :    Execute an external program */
     232                 : PHP_FUNCTION(exec)
     233               0 : {
     234               0 :         php_exec_ex(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
     235               0 : }
     236                 : 
     237                 : /* }}} */
     238                 : 
     239                 : /* {{{ proto int system(string command [, int &return_value])
     240                 :    Execute an external program and display output */
     241                 : PHP_FUNCTION(system)
     242               0 : {
     243               0 :         php_exec_ex(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
     244               0 : }
     245                 : /* }}} */
     246                 : 
     247                 : /* {{{ proto void passthru(string command [, int &return_value])
     248                 :    Execute an external program and display raw output */
     249                 : PHP_FUNCTION(passthru)
     250               0 : {
     251               0 :         php_exec_ex(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3);
     252               0 : }
     253                 : /* }}} */
     254                 : 
     255                 : /* {{{ php_escape_shell_cmd
     256                 :    Escape all chars that could possibly be used to
     257                 :    break out of a shell command
     258                 : 
     259                 :    This function emalloc's a string and returns the pointer.
     260                 :    Remember to efree it when done with it.
     261                 : 
     262                 :    *NOT* safe for binary strings
     263                 : */
     264               0 : char *php_escape_shell_cmd(char *str) {
     265                 :         register int x, y, l;
     266                 :         char *cmd;
     267               0 :         char *p = NULL;
     268                 : 
     269               0 :         l = strlen(str);
     270               0 :         cmd = safe_emalloc(2, l, 1);
     271                 :         
     272               0 :         for (x = 0, y = 0; x < l; x++) {
     273               0 :                 switch (str[x]) {
     274                 :                         case '"':
     275                 :                         case '\'':
     276                 : #ifndef PHP_WIN32
     277               0 :                                 if (!p && (p = memchr(str + x + 1, str[x], l - x - 1))) {
     278                 :                                         /* noop */
     279               0 :                                 } else if (p && *p == str[x]) {
     280               0 :                                         p = NULL;
     281                 :                                 } else {
     282               0 :                                         cmd[y++] = '\\';
     283                 :                                 }
     284               0 :                                 cmd[y++] = str[x];
     285               0 :                                 break;
     286                 : #endif
     287                 :                         case '#': /* This is character-set independent */
     288                 :                         case '&':
     289                 :                         case ';':
     290                 :                         case '`':
     291                 :                         case '|':
     292                 :                         case '*':
     293                 :                         case '?':
     294                 :                         case '~':
     295                 :                         case '<':
     296                 :                         case '>':
     297                 :                         case '^':
     298                 :                         case '(':
     299                 :                         case ')':
     300                 :                         case '[':
     301                 :                         case ']':
     302                 :                         case '{':
     303                 :                         case '}':
     304                 :                         case '$':
     305                 :                         case '\\':
     306                 :                         case '\x0A': /* excluding these two */
     307                 :                         case '\xFF':
     308                 : #ifdef PHP_WIN32
     309                 :                         /* since Windows does not allow us to escape these chars, just remove them */
     310                 :                         case '%':
     311                 :                                 cmd[y++] = ' ';
     312                 :                                 break;
     313                 : #endif
     314               0 :                                 cmd[y++] = '\\';
     315                 :                                 /* fall-through */
     316                 :                         default:
     317               0 :                                 cmd[y++] = str[x];
     318                 : 
     319                 :                 }
     320                 :         }
     321               0 :         cmd[y] = '\0';
     322               0 :         return cmd;
     323                 : }
     324                 : /* }}} */
     325                 : 
     326                 : /* {{{ php_escape_shell_arg
     327                 :  */
     328               0 : char *php_escape_shell_arg(char *str) {
     329                 :         int x, y, l;
     330                 :         char *cmd;
     331                 : 
     332               0 :         y = 0;
     333               0 :         l = strlen(str);
     334                 :         
     335               0 :         cmd = safe_emalloc(4, l, 3); /* worst case */
     336                 :         
     337                 : #ifdef PHP_WIN32
     338                 :         cmd[y++] = '"';
     339                 : #else
     340               0 :         cmd[y++] = '\'';
     341                 : #endif
     342                 : 
     343               0 :         for (x = 0; x < l; x++) {
     344               0 :                 switch (str[x]) {
     345                 : #ifdef PHP_WIN32
     346                 :                 case '"':
     347                 :                 case '%':
     348                 :                         cmd[y++] = ' ';
     349                 :                         break;
     350                 : #else
     351                 :                 case '\'':
     352               0 :                         cmd[y++] = '\'';
     353               0 :                         cmd[y++] = '\\';
     354               0 :                         cmd[y++] = '\'';
     355                 : #endif
     356                 :                         /* fall-through */
     357                 :                 default:
     358               0 :                         cmd[y++] = str[x];
     359                 :                 }
     360                 :         }
     361                 : #ifdef PHP_WIN32
     362                 :         cmd[y++] = '"';
     363                 : #else
     364               0 :         cmd[y++] = '\'';
     365                 : #endif
     366               0 :         cmd[y] = '\0';
     367               0 :         return cmd;
     368                 : }
     369                 : /* }}} */
     370                 : 
     371                 : /* {{{ proto string escapeshellcmd(string command)
     372                 :    Escape shell metacharacters */
     373                 : PHP_FUNCTION(escapeshellcmd)
     374               0 : {
     375                 :         zval **arg1;
     376               0 :         char *cmd = NULL;
     377                 : 
     378               0 :         if (zend_get_parameters_ex(1, &arg1) == FAILURE) {
     379               0 :                 WRONG_PARAM_COUNT;
     380                 :         }
     381                 :         
     382               0 :         convert_to_string_ex(arg1);
     383               0 :         if (Z_STRLEN_PP(arg1)) {
     384               0 :                 cmd = php_escape_shell_cmd(Z_STRVAL_PP(arg1));
     385               0 :                 RETVAL_STRING(cmd, 1);
     386               0 :                 efree(cmd);
     387                 :         }
     388                 : }
     389                 : /* }}} */
     390                 : 
     391                 : /* {{{ proto string escapeshellarg(string arg)
     392                 :    Quote and escape an argument for use in a shell command */
     393                 : PHP_FUNCTION(escapeshellarg)
     394               0 : {
     395                 :         zval **arg1;
     396               0 :         char *cmd = NULL;
     397                 : 
     398               0 :         if (zend_get_parameters_ex(1, &arg1) == FAILURE) {
     399               0 :                 WRONG_PARAM_COUNT;
     400                 :         }
     401                 :         
     402               0 :         convert_to_string_ex(arg1);
     403               0 :         if (Z_STRLEN_PP(arg1)) {
     404               0 :                 cmd = php_escape_shell_arg(Z_STRVAL_PP(arg1));
     405               0 :                 RETVAL_STRING(cmd, 1);
     406               0 :                 efree(cmd);
     407                 :         }
     408                 : }
     409                 : /* }}} */
     410                 : 
     411                 : /* {{{ proto string shell_exec(string cmd)
     412                 :    Execute command via shell and return complete output as string */
     413                 : PHP_FUNCTION(shell_exec)
     414               3 : {
     415                 :         FILE *in;
     416                 :         size_t total_readbytes;
     417                 :         zval **cmd;
     418                 :         char *ret;
     419                 :         php_stream *stream;
     420                 : 
     421               3 :         if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &cmd)==FAILURE) {
     422               0 :                 WRONG_PARAM_COUNT;
     423                 :         }
     424                 :         
     425               3 :         if (PG(safe_mode)) {
     426               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot execute using backquotes in Safe Mode");
     427               0 :                 RETURN_FALSE;
     428                 :         }
     429                 : 
     430               3 :         convert_to_string_ex(cmd);
     431                 : #ifdef PHP_WIN32
     432                 :         if ((in=VCWD_POPEN(Z_STRVAL_PP(cmd), "rt"))==NULL) {
     433                 : #else
     434               3 :         if ((in=VCWD_POPEN(Z_STRVAL_PP(cmd), "r"))==NULL) {
     435                 : #endif
     436               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to execute '%s'", Z_STRVAL_PP(cmd));
     437               0 :                 RETURN_FALSE;
     438                 :         }
     439                 : 
     440               3 :         stream = php_stream_fopen_from_pipe(in, "rb");
     441               3 :         total_readbytes = php_stream_copy_to_mem(stream, &ret, PHP_STREAM_COPY_ALL, 0);
     442               3 :         php_stream_close(stream); 
     443                 :         
     444               3 :         if (total_readbytes > 0) {
     445               3 :                 RETURN_STRINGL(ret, total_readbytes, 0);
     446                 :         } else {
     447               0 :                 RETURN_NULL();  
     448                 :         }
     449                 : }
     450                 : /* }}} */
     451                 : 
     452                 : #ifdef HAVE_NICE
     453                 : /* {{{ proto bool proc_nice(int priority)
     454                 :    Change the priority of the current process */
     455                 : PHP_FUNCTION(proc_nice)
     456               0 : {
     457                 :         long pri;
     458                 : 
     459               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &pri) == FAILURE) {
     460               0 :                 RETURN_FALSE;
     461                 :         }
     462                 : 
     463               0 :         errno = 0;
     464               0 :         nice(pri);
     465               0 :         if (errno) {
     466               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only a super user may attempt to increase the priority of a process.");
     467               0 :                 RETURN_FALSE;
     468                 :         }
     469                 :         
     470               0 :         RETURN_TRUE;
     471                 : }
     472                 : /* }}} */
     473                 : #endif
     474                 : 
     475                 : /*
     476                 :  * Local variables:
     477                 :  * tab-width: 4
     478                 :  * c-basic-offset: 4
     479                 :  * End:
     480                 :  * vim600: sw=4 ts=4 fdm=marker
     481                 :  * vim<600: sw=4 ts=4
     482                 :  */

Generated by: LTP GCOV extension version 1.5