PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - standard - exec.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 192
Code covered: 79.7 % Executed lines: 153
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 6                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2009 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 289624 2009-10-14 01:32:07Z iliaa $ */
      20                 : 
      21                 : #include <stdio.h>
      22                 : #include "php.h"
      23                 : #include <ctype.h>
      24                 : #include "php_string.h"
      25                 : #include "ext/standard/head.h"
      26                 : #include "ext/standard/file.h"
      27                 : #include "basic_functions.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                 :  * Unicode command strings are encoding using filesystem_encoding, returned data is not decoded back to unicode
      60                 :  */
      61                 : PHPAPI int php_exec(int type, char *cmd, zval *array, zval *return_value TSRMLS_DC)
      62              18 : {
      63                 :         FILE *fp;
      64                 :         char *buf;
      65                 :         int l, pclose_return;
      66              18 :         char *cmd_p, *b, *d=NULL;
      67                 :         php_stream *stream;
      68              18 :         size_t buflen, bufl = 0;
      69                 : #if PHP_SIGCHILD
      70                 :         void (*sig_handler)() = NULL;
      71                 : #endif
      72                 : 
      73              18 :         cmd_p = cmd;
      74                 : 
      75                 : #if PHP_SIGCHILD
      76                 :         sig_handler = signal (SIGCHLD, SIG_DFL);
      77                 : #endif
      78                 : 
      79                 : #ifdef PHP_WIN32
      80                 :         fp = VCWD_POPEN(cmd_p, "rb");
      81                 : #else
      82              18 :         fp = VCWD_POPEN(cmd_p, "r");
      83                 : #endif
      84              18 :         if (!fp) {
      85               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to fork [%s]", cmd);
      86               0 :                 goto err;
      87                 :         }
      88                 : 
      89              18 :         stream = php_stream_fopen_from_pipe(fp, "rb");
      90                 : 
      91              18 :         buf = (char *) emalloc(EXEC_INPUT_BUF);
      92              18 :         buflen = EXEC_INPUT_BUF;
      93                 : 
      94              18 :         if (type != 3) {
      95               4 :                 b = buf;
      96                 : 
      97              30 :                 while (php_stream_get_line(stream, ZSTR(b), EXEC_INPUT_BUF, &bufl)) {
      98                 :                         /* no new line found, let's read some more */
      99              22 :                         if (b[bufl - 1] != '\n' && !php_stream_eof(stream)) {
     100               8 :                                 if (buflen < (bufl + (b - buf) + EXEC_INPUT_BUF)) {
     101               4 :                                         bufl += b - buf;
     102               4 :                                         buflen = bufl + EXEC_INPUT_BUF;
     103               4 :                                         buf = erealloc(buf, buflen);
     104               4 :                                         b = buf + bufl;
     105                 :                                 } else {
     106               4 :                                         b += bufl;
     107                 :                                 }
     108               8 :                                 continue;
     109              14 :                         } else if (b != buf) {
     110               3 :                                 bufl += b - buf;
     111                 :                         }
     112                 : 
     113              14 :                         if (type == 1) {
     114                 :                                 int ob_level;
     115               0 :                                 PHPWRITE(buf, bufl);
     116               0 :                                 if ((php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_GET_LEVEL, &ob_level TSRMLS_CC) == SUCCESS) && ob_level < 1) {
     117               0 :                                         sapi_flush(TSRMLS_C);
     118                 :                                 }
     119              14 :                         } else if (type == 2) {
     120                 :                                 /* strip trailing whitespaces */
     121              14 :                                 l = bufl;
     122              28 :                                 while (l-- && isspace(((unsigned char *)buf)[l]));
     123              14 :                                 if (l != (bufl - 1)) {
     124              14 :                                         bufl = l + 1;
     125              14 :                                         buf[bufl] = '\0';
     126                 :                                 }
     127              14 :                                 add_next_index_stringl(array, buf, bufl, 1);
     128                 :                         }
     129              14 :                         b = buf;
     130                 :                 }
     131               4 :                 if (bufl) {
     132                 :                         /* strip trailing whitespaces if we have not done so already */
     133               0 :                         if ((type == 2 && bufl && !l) || type != 2) {
     134               0 :                                 l = bufl;
     135               0 :                                 while (l-- && isspace(((unsigned char *)buf)[l]));
     136               0 :                                 if (l != (bufl - 1)) {
     137               0 :                                         bufl = l + 1;
     138               0 :                                         buf[bufl] = '\0';
     139                 :                                 }
     140               0 :                                 if (type == 2) {
     141               0 :                                         add_next_index_stringl(array, buf, bufl, 1);
     142                 :                                 }
     143                 :                         }
     144                 : 
     145                 :                         /* Return last line from the shell command */
     146               0 :                         RETVAL_STRINGL(buf, bufl, 1);
     147                 :                 } else { /* should return NULL, but for BC we return "" */
     148               4 :                         RETVAL_EMPTY_STRING();
     149                 :                 }
     150                 :         } else {
     151            8651 :                 while((bufl = php_stream_read(stream, buf, EXEC_INPUT_BUF)) > 0) {
     152            8623 :                         PHPWRITE(buf, bufl);
     153                 :                 }
     154                 :         }
     155                 : 
     156              18 :         pclose_return = php_stream_close(stream);
     157              18 :         efree(buf);
     158                 : 
     159              18 : done:
     160                 : #if PHP_SIGCHILD
     161                 :         if (sig_handler) {
     162                 :                 signal(SIGCHLD, sig_handler);
     163                 :         }
     164                 : #endif
     165              18 :         if (d) {
     166               0 :                 efree(d);
     167                 :         }
     168              18 :         return pclose_return;
     169               0 : err:
     170               0 :         pclose_return = -1;
     171               0 :         goto done;
     172                 : }
     173                 : /* }}} */
     174                 : 
     175                 : static void php_exec_ex(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
     176              18 : {
     177                 :         char *cmd;
     178                 :         int cmd_len;
     179                 :         zend_uchar cmd_type;
     180              18 :         zval *ret_code=NULL, *ret_array=NULL;
     181                 :         int ret;
     182                 : 
     183              18 :         if (mode) {
     184              14 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t|z/", &cmd, &cmd_len, &cmd_type, &ret_code) == FAILURE) {
     185               0 :                         RETURN_FALSE;
     186                 :                 }
     187                 :         } else {
     188               4 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t|z/z/", &cmd, &cmd_len, &cmd_type, &ret_array, &ret_code) == FAILURE) {
     189               0 :                         RETURN_FALSE;
     190                 :                 }
     191                 :         }
     192              18 :         if (!cmd_len) {
     193               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot execute a blank command");
     194               0 :                 RETURN_FALSE;
     195                 :         }
     196                 : 
     197              18 :         if (cmd_type == IS_UNICODE) {
     198              18 :                 if (FAILURE == php_stream_path_encode(NULL, &cmd, &cmd_len, (UChar*)cmd, cmd_len, REPORT_ERRORS, FG(default_context))) {
     199               0 :                         RETURN_FALSE;
     200                 :                 }
     201                 :         }
     202                 : 
     203              18 :         if (!ret_array) {
     204              15 :                 ret = php_exec(mode, cmd, NULL, return_value TSRMLS_CC);
     205                 :         } else {
     206               3 :                 if (Z_TYPE_P(ret_array) != IS_ARRAY) {
     207               1 :                         zval_dtor(ret_array);
     208               1 :                         array_init(ret_array);
     209                 :                 }
     210               3 :                 ret = php_exec(2, cmd, ret_array, return_value TSRMLS_CC);
     211                 :         }
     212              18 :         if (ret_code) {
     213               2 :                 zval_dtor(ret_code);
     214               2 :                 ZVAL_LONG(ret_code, ret);
     215                 :         }
     216                 : 
     217              18 :         if (cmd_type == IS_UNICODE) {
     218              18 :                 efree(cmd);
     219                 :         }
     220                 : }
     221                 : /* }}} */
     222                 : 
     223                 : /* {{{ proto string exec(string command [, array &output [, int &return_value]]) U
     224                 :    Execute an external program */
     225                 : PHP_FUNCTION(exec)
     226               4 : {
     227               4 :         php_exec_ex(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
     228               4 : }
     229                 : /* }}} */
     230                 : 
     231                 : /* {{{ proto int system(string command [, int &return_value]) U
     232                 :    Execute an external program and display output */
     233                 : PHP_FUNCTION(system)
     234               0 : {
     235               0 :         php_exec_ex(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
     236               0 : }
     237                 : /* }}} */
     238                 : 
     239                 : /* {{{ proto void passthru(string command [, int &return_value]) U
     240                 :    Execute an external program and display raw output */
     241                 : PHP_FUNCTION(passthru)
     242              14 : {
     243              14 :         php_exec_ex(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3);
     244              14 : }
     245                 : /* }}} */
     246                 : 
     247                 : /* {{{ php_escape_shell_cmd
     248                 :    Escape all chars that could possibly be used to
     249                 :    break out of a shell command
     250                 : 
     251                 :    This function emalloc's a string and returns the pointer.
     252                 :    Remember to efree it when done with it.
     253                 : 
     254                 :    *NOT* safe for binary strings
     255                 : */
     256                 : PHPAPI char *php_escape_shell_cmd(char *str)
     257              15 : {
     258              15 :         register int x, y, l = strlen(str);
     259                 :         char *cmd;
     260              15 :         char *p = NULL;
     261              15 :         size_t estimate = (2 * l) + 1;
     262                 : 
     263                 :         TSRMLS_FETCH();
     264                 : 
     265              15 :         cmd = safe_emalloc(2, l, 1);
     266                 : 
     267             495 :         for (x = 0, y = 0; x < l; x++) {
     268             480 :                 int mb_len = php_mblen(str + x, (l - x));
     269                 : 
     270                 :                 /* skip non-valid multibyte characters */
     271             480 :                 if (mb_len < 0) {
     272               0 :                         continue;
     273             480 :                 } else if (mb_len > 1) {
     274               5 :                         memcpy(cmd + y, str + x, mb_len);
     275               5 :                         y += mb_len;
     276               5 :                         x += mb_len - 1;
     277               5 :                         continue;
     278                 :                 }
     279                 : 
     280             475 :                 switch (str[x]) {
     281                 : #ifndef PHP_WIN32
     282                 :                         case '"':
     283                 :                         case '\'':
     284               2 :                                 if (!p && (p = memchr(str + x + 1, str[x], l - x - 1))) {
     285                 :                                         /* noop */
     286               2 :                                 } else if (p && *p == str[x]) {
     287               1 :                                         p = NULL;
     288                 :                                 } else {
     289               0 :                                         cmd[y++] = '\\';
     290                 :                                 }
     291               2 :                                 cmd[y++] = str[x];
     292               2 :                                 break;
     293                 : #else
     294                 :                         /* % is Windows specific for enviromental variables, ^%PATH% will 
     295                 :                                 output PATH whil ^%PATH^% not. escapeshellcmd will escape all %.
     296                 :                         */
     297                 :                         case '%':
     298                 :                                 cmd[y++] = ' ';
     299                 :                                 break;
     300                 : #endif
     301                 :                         case '#': /* This is character-set independent */
     302                 :                         case '&':
     303                 :                         case ';':
     304                 :                         case '`':
     305                 :                         case '|':
     306                 :                         case '*':
     307                 :                         case '?':
     308                 :                         case '~':
     309                 :                         case '<':
     310                 :                         case '>':
     311                 :                         case '^':
     312                 :                         case '(':
     313                 :                         case ')':
     314                 :                         case '[':
     315                 :                         case ']':
     316                 :                         case '{':
     317                 :                         case '}':
     318                 :                         case '$':
     319                 :                         case '\\':
     320                 :                         case '\x0A': /* excluding these two */
     321                 :                         case '\xFF':
     322                 : #ifdef PHP_WIN32
     323                 :                                 cmd[y++] = '^';
     324                 : #else
     325               6 :                                 cmd[y++] = '\\';
     326                 : #endif
     327                 :                                 /* fall-through */
     328                 :                         default:
     329             473 :                                 cmd[y++] = str[x];
     330                 : 
     331                 :                 }
     332                 :         }
     333              15 :         cmd[y] = '\0';
     334                 : 
     335              15 :         if ((estimate - y) > 4096) {
     336                 :                 /* realloc if the estimate was way overill
     337                 :                  * Arbitrary cutoff point of 4096 */
     338               0 :                 cmd = erealloc(cmd, y + 1);
     339                 :         }
     340                 : 
     341              15 :         return cmd;
     342                 : }
     343                 : /* }}} */
     344                 : 
     345                 : /* {{{ php_escape_shell_arg
     346                 :  */
     347                 : PHPAPI char *php_escape_shell_arg(char *str)
     348              44 : {
     349              44 :         int x, y = 0, l = strlen(str);
     350                 :         char *cmd;
     351              44 :         size_t estimate = (4 * l) + 3;
     352                 : 
     353                 :         TSRMLS_FETCH();
     354                 : 
     355              44 :         cmd = safe_emalloc(4, l, 3); /* worst case */
     356                 : 
     357                 : #ifdef PHP_WIN32
     358                 :         cmd[y++] = '"';
     359                 : #else
     360              44 :         cmd[y++] = '\'';
     361                 : #endif
     362                 : 
     363             681 :         for (x = 0; x < l; x++) {
     364             637 :                 int mb_len = php_mblen(str + x, (l - x));
     365                 : 
     366                 :                 /* skip non-valid multibyte characters */
     367             637 :                 if (mb_len < 0) {
     368               0 :                         continue;
     369             637 :                 } else if (mb_len > 1) {
     370               4 :                         memcpy(cmd + y, str + x, mb_len);
     371               4 :                         y += mb_len;
     372               4 :                         x += mb_len - 1;
     373               4 :                         continue;
     374                 :                 }
     375                 : 
     376             633 :                 switch (str[x]) {
     377                 : #ifdef PHP_WIN32
     378                 :                 case '"':
     379                 :                 case '%':
     380                 :                         cmd[y++] = ' ';
     381                 :                         break;
     382                 : #else
     383                 :                 case '\'':
     384               7 :                         cmd[y++] = '\'';
     385               7 :                         cmd[y++] = '\\';
     386               7 :                         cmd[y++] = '\'';
     387                 : #endif
     388                 :                         /* fall-through */
     389                 :                 default:
     390             633 :                         cmd[y++] = str[x];
     391                 :                 }
     392                 :         }
     393                 : #ifdef PHP_WIN32
     394                 :         cmd[y++] = '"';
     395                 : #else
     396              44 :         cmd[y++] = '\'';
     397                 : #endif
     398              44 :         cmd[y] = '\0';
     399                 : 
     400              44 :         if ((estimate - y) > 4096) {
     401                 :                 /* realloc if the estimate was way overill
     402                 :                  * Arbitrary cutoff point of 4096 */
     403               0 :                 cmd = erealloc(cmd, y + 1);
     404                 :         }
     405              44 :         return cmd;
     406                 : }
     407                 : /* }}} */
     408                 : 
     409                 : /* {{{ proto string escapeshellcmd(string command) U
     410                 :    Escape shell metacharacters */
     411                 : PHP_FUNCTION(escapeshellcmd)
     412              13 : {
     413                 :         char *command;
     414                 :         int command_len;
     415                 :         zend_uchar command_type;
     416              13 :         char *cmd = NULL;
     417                 : 
     418              13 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &command, &command_len, &command_type) == FAILURE) {
     419               0 :                 return;
     420                 :         }
     421                 : 
     422              13 :         if (command_type == IS_UNICODE) {
     423              13 :                 if (FAILURE == php_stream_path_encode(NULL, &command, &command_len, (UChar*)command, command_len, REPORT_ERRORS, FG(default_context))) {
     424               0 :                         RETURN_FALSE;
     425                 :                 }
     426                 :         }
     427                 : 
     428              13 :         if (command_len) {
     429              13 :                 cmd = php_escape_shell_cmd(command);
     430              13 :                 RETVAL_STRING(cmd, 0);
     431                 :         } else {
     432               0 :                 RETVAL_EMPTY_STRING();
     433                 :         }
     434                 : 
     435              13 :         if (command_type == IS_UNICODE) {
     436              13 :                 efree(command);
     437                 :         }
     438                 : }
     439                 : /* }}} */
     440                 : 
     441                 : /* {{{ proto string escapeshellarg(string arg) U
     442                 :    Quote and escape an argument for use in a shell command */
     443                 : PHP_FUNCTION(escapeshellarg)
     444              49 : {
     445                 :         char *argument;
     446                 :         int argument_len;
     447                 :         zend_uchar argument_type;
     448              49 :         char *cmd = NULL;
     449                 : 
     450              49 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &argument, &argument_len, &argument_type) == FAILURE) {
     451               5 :                 return;
     452                 :         }
     453                 : 
     454              44 :         if (argument_type == IS_UNICODE) {
     455              44 :                 if (FAILURE == php_stream_path_encode(NULL, &argument, &argument_len, (UChar*)argument, argument_len, REPORT_ERRORS, FG(default_context))) {
     456               0 :                         RETURN_FALSE;
     457                 :                 }
     458                 :         }
     459                 : 
     460              44 :         if (argument) {
     461              44 :                 cmd = php_escape_shell_arg(argument);
     462              44 :                 RETVAL_STRING(cmd, 0);
     463                 :         }
     464                 : 
     465              44 :         if (argument_type == IS_UNICODE) {
     466              44 :                 efree(argument);
     467                 :         }
     468                 : }
     469                 : /* }}} */
     470                 : 
     471                 : /* {{{ proto string shell_exec(string cmd) U
     472                 :    Execute command via shell and return complete output as string */
     473                 : PHP_FUNCTION(shell_exec)
     474             119 : {
     475                 :         FILE *in;
     476                 :         size_t total_readbytes;
     477                 :         char *command;
     478                 :         int command_len;
     479                 :         zend_uchar command_type;
     480                 :         char *ret;
     481                 :         php_stream *stream;
     482                 : 
     483             119 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &command, &command_len, &command_type) == FAILURE) {
     484               0 :                 return;
     485                 :         }
     486                 : 
     487             119 :         if (command_type == IS_UNICODE) {
     488             119 :                 if (FAILURE == php_stream_path_encode(NULL, &command, &command_len, (UChar*)command, command_len, REPORT_ERRORS, FG(default_context))) {
     489               0 :                         RETURN_FALSE;
     490                 :                 }
     491                 :         }
     492                 : 
     493                 : #ifdef PHP_WIN32
     494                 :         if ((in=VCWD_POPEN(command, "rt"))==NULL) {
     495                 : #else
     496             119 :         if ((in=VCWD_POPEN(command, "r"))==NULL) {
     497                 : #endif
     498               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to execute '%s'", command);
     499               0 :                 RETURN_FALSE;
     500                 :         }
     501                 : 
     502             119 :         stream = php_stream_fopen_from_pipe(in, "rb");
     503             119 :         total_readbytes = php_stream_copy_to_mem(stream, (void *)&ret, PHP_STREAM_COPY_ALL, 0);
     504             119 :         php_stream_close(stream);
     505                 : 
     506             119 :         if (total_readbytes > 0) {
     507             117 :                 RETVAL_STRINGL(ret, total_readbytes, 0);
     508                 :         }
     509                 : 
     510             119 :         if (command_type == IS_UNICODE) {
     511             119 :                 efree(command);
     512                 :         }
     513                 : }
     514                 : /* }}} */
     515                 : 
     516                 : #ifdef HAVE_NICE
     517                 : /* {{{ proto bool proc_nice(int priority) U
     518                 :    Change the priority of the current process */
     519                 : PHP_FUNCTION(proc_nice)
     520              25 : {
     521                 :         long pri;
     522                 : 
     523              25 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &pri) == FAILURE) {
     524              12 :                 RETURN_FALSE;
     525                 :         }
     526                 : 
     527              13 :         errno = 0;
     528              13 :         nice(pri);
     529              13 :         if (errno) {
     530               1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only a super user may attempt to increase the priority of a process");
     531               1 :                 RETURN_FALSE;
     532                 :         }
     533                 : 
     534              12 :         RETURN_TRUE;
     535                 : }
     536                 : /* }}} */
     537                 : #endif
     538                 : 
     539                 : /*
     540                 :  * Local variables:
     541                 :  * tab-width: 4
     542                 :  * c-basic-offset: 4
     543                 :  * End:
     544                 :  * vim600: sw=4 ts=4 fdm=marker
     545                 :  * vim<600: sw=4 ts=4
     546                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:41 +0000 (33 hours ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.