Back to index

php5  5.3.10
Functions
exec.c File Reference
#include <stdio.h>
#include "php.h"
#include <ctype.h>
#include "php_string.h"
#include "safe_mode.h"
#include "ext/standard/head.h"
#include "ext/standard/file.h"
#include "basic_functions.h"
#include "exec.h"
#include "php_globals.h"
#include "SAPI.h"

Go to the source code of this file.

Functions

PHPAPI int php_exec (int type, char *cmd, zval *array, zval *return_value TSRMLS_DC)
static void php_exec_ex (INTERNAL_FUNCTION_PARAMETERS, int mode)
 PHP_FUNCTION (exec)
 PHP_FUNCTION (system)
 PHP_FUNCTION (passthru)
PHPAPI char * php_escape_shell_cmd (char *str)
PHPAPI char * php_escape_shell_arg (char *str)
 PHP_FUNCTION (escapeshellcmd)
 PHP_FUNCTION (escapeshellarg)
 PHP_FUNCTION (shell_exec)

Function Documentation

PHPAPI char* php_escape_shell_arg ( char *  str)

Definition at line 370 of file exec.c.

{
       int x, y = 0, l = strlen(str);
       char *cmd;
       size_t estimate = (4 * l) + 3;

       TSRMLS_FETCH();

       cmd = safe_emalloc(4, l, 3); /* worst case */

#ifdef PHP_WIN32
       cmd[y++] = '"';
#else
       cmd[y++] = '\'';
#endif

       for (x = 0; x < l; x++) {
              int mb_len = php_mblen(str + x, (l - x));

              /* skip non-valid multibyte characters */
              if (mb_len < 0) {
                     continue;
              } else if (mb_len > 1) {
                     memcpy(cmd + y, str + x, mb_len);
                     y += mb_len;
                     x += mb_len - 1;
                     continue;
              }

              switch (str[x]) {
#ifdef PHP_WIN32
              case '"':
              case '%':
                     cmd[y++] = ' ';
                     break;
#else
              case '\'':
                     cmd[y++] = '\'';
                     cmd[y++] = '\\';
                     cmd[y++] = '\'';
#endif
                     /* fall-through */
              default:
                     cmd[y++] = str[x];
              }
       }
#ifdef PHP_WIN32
       cmd[y++] = '"';
#else
       cmd[y++] = '\'';
#endif
       cmd[y] = '\0';

       if ((estimate - y) > 4096) {
              /* realloc if the estimate was way overill
               * Arbitrary cutoff point of 4096 */
              cmd = erealloc(cmd, y + 1);
       }
       return cmd;
}

Here is the caller graph for this function:

PHPAPI char* php_escape_shell_cmd ( char *  str)

Definition at line 279 of file exec.c.

{
       register int x, y, l = strlen(str);
       char *cmd;
       char *p = NULL;
       size_t estimate = (2 * l) + 1;

       TSRMLS_FETCH();

       cmd = safe_emalloc(2, l, 1);

       for (x = 0, y = 0; x < l; x++) {
              int mb_len = php_mblen(str + x, (l - x));

              /* skip non-valid multibyte characters */
              if (mb_len < 0) {
                     continue;
              } else if (mb_len > 1) {
                     memcpy(cmd + y, str + x, mb_len);
                     y += mb_len;
                     x += mb_len - 1;
                     continue;
              }

              switch (str[x]) {
#ifndef PHP_WIN32
                     case '"':
                     case '\'':
                            if (!p && (p = memchr(str + x + 1, str[x], l - x - 1))) {
                                   /* noop */
                            } else if (p && *p == str[x]) {
                                   p = NULL;
                            } else {
                                   cmd[y++] = '\\';
                            }
                            cmd[y++] = str[x];
                            break;
#else
                     /* % is Windows specific for enviromental variables, ^%PATH% will 
                            output PATH whil ^%PATH^% not. escapeshellcmd will escape all %.
                     */
                     case '%':
                     case '"':
                     case '\'':
#endif
                     case '#': /* This is character-set independent */
                     case '&':
                     case ';':
                     case '`':
                     case '|':
                     case '*':
                     case '?':
                     case '~':
                     case '<':
                     case '>':
                     case '^':
                     case '(':
                     case ')':
                     case '[':
                     case ']':
                     case '{':
                     case '}':
                     case '$':
                     case '\\':
                     case '\x0A': /* excluding these two */
                     case '\xFF':
#ifdef PHP_WIN32
                            cmd[y++] = '^';
#else
                            cmd[y++] = '\\';
#endif
                            /* fall-through */
                     default:
                            cmd[y++] = str[x];

              }
       }
       cmd[y] = '\0';

       if ((estimate - y) > 4096) {
              /* realloc if the estimate was way overill
               * Arbitrary cutoff point of 4096 */
              cmd = erealloc(cmd, y + 1);
       }

       return cmd;
}

Here is the caller graph for this function:

PHPAPI int php_exec ( int  type,
char *  cmd,
zval *  array,
zval *return_value  TSRMLS_DC 
)

Definition at line 61 of file exec.c.

{
       FILE *fp;
       char *buf, *tmp=NULL;
       int l = 0, pclose_return;
       char *cmd_p, *b, *c, *d=NULL;
       php_stream *stream;
       size_t buflen, bufl = 0;
#if PHP_SIGCHILD
       void (*sig_handler)() = NULL;
#endif

       if (PG(safe_mode)) {
              if ((c = strchr(cmd, ' '))) {
                     *c = '\0';
                     c++;
              }
              if (strstr(cmd, "..")) {
                     php_error_docref(NULL TSRMLS_CC, E_WARNING, "No '..' components allowed in path");
                     goto err;
              }
              
              b = strrchr(cmd, PHP_DIR_SEPARATOR);

#ifdef PHP_WIN32
              if (b && *b == '\\' && b == cmd) {
                     php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid absolute path.");
                     goto err;
              }
#endif

              spprintf(&d, 0, "%s%s%s%s%s", PG(safe_mode_exec_dir), (b ? "" : "/"), (b ? b : cmd), (c ? " " : ""), (c ? c : ""));
              if (c) {
                     *(c - 1) = ' ';
              }
              cmd_p = php_escape_shell_cmd(d);
              efree(d);
              d = cmd_p;
       } else {
              cmd_p = cmd;
       }

#if PHP_SIGCHILD
       sig_handler = signal (SIGCHLD, SIG_DFL);
#endif

#ifdef PHP_WIN32
       fp = VCWD_POPEN(cmd_p, "rb");
#else
       fp = VCWD_POPEN(cmd_p, "r");
#endif
       if (!fp) {
              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to fork [%s]", cmd);
              goto err;
       }

       stream = php_stream_fopen_from_pipe(fp, "rb");

       buf = (char *) emalloc(EXEC_INPUT_BUF);
       buflen = EXEC_INPUT_BUF;

       if (type != 3) {
              b = buf;
              
              while (php_stream_get_line(stream, b, EXEC_INPUT_BUF, &bufl)) {
                     /* no new line found, let's read some more */
                     if (b[bufl - 1] != '\n' && !php_stream_eof(stream)) {
                            if (buflen < (bufl + (b - buf) + EXEC_INPUT_BUF)) {
                                   bufl += b - buf;
                                   buflen = bufl + EXEC_INPUT_BUF;
                                   buf = erealloc(buf, buflen);
                                   b = buf + bufl;
                            } else {
                                   b += bufl;
                            }
                            continue;
                     } else if (b != buf) {
                            bufl += b - buf;
                     }

                     if (type == 1) {
                            PHPWRITE(buf, bufl);
                            if (OG(ob_nesting_level) < 1) {
                                   sapi_flush(TSRMLS_C);
                            }
                     } else if (type == 2) {
                            /* strip trailing whitespaces */
                            l = bufl;
                            while (l-- && isspace(((unsigned char *)buf)[l]));
                            if (l != (int)(bufl - 1)) {
                                   bufl = l + 1;
                                   buf[bufl] = '\0';
                            }
                            add_next_index_stringl(array, buf, bufl, 1);
                     }
                     b = buf;
              }
              if (bufl) {
                     /* strip trailing whitespaces if we have not done so already */
                     if ((type == 2 && buf != b) || type != 2) {
                            l = bufl;
                            while (l-- && isspace(((unsigned char *)buf)[l]));
                            if (l != (int)(bufl - 1)) {
                                   bufl = l + 1;
                                   buf[bufl] = '\0';
                            }
                            if (type == 2) {
                                   add_next_index_stringl(array, buf, bufl, 1);
                            }
                     }

                     /* Return last line from the shell command */
                     if (PG(magic_quotes_runtime)) {
                            int len;

                            tmp = php_addslashes(buf, bufl, &len, 0 TSRMLS_CC);
                            RETVAL_STRINGL(tmp, len, 0);
                     } else {
                            RETVAL_STRINGL(buf, bufl, 1);
                     }
              } else { /* should return NULL, but for BC we return "" */
                     RETVAL_EMPTY_STRING();
              }
       } else {
              while((bufl = php_stream_read(stream, buf, EXEC_INPUT_BUF)) > 0) {
                     PHPWRITE(buf, bufl);
              }
       }

       pclose_return = php_stream_close(stream);
       efree(buf);

done:
#if PHP_SIGCHILD
       if (sig_handler) {
              signal(SIGCHLD, sig_handler);
       }
#endif
       if (d) {
              efree(d);
       }
       return pclose_return;
err:
       pclose_return = -1;
       goto done;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void php_exec_ex ( INTERNAL_FUNCTION_PARAMETERS  ,
int  mode 
) [static]

Definition at line 209 of file exec.c.

{
       char *cmd;
       int cmd_len;
       zval *ret_code=NULL, *ret_array=NULL;
       int ret;

       if (mode) {
              if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z/", &cmd, &cmd_len, &ret_code) == FAILURE) {
                     RETURN_FALSE;
              }
       } else {
              if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z/z/", &cmd, &cmd_len, &ret_array, &ret_code) == FAILURE) {
                     RETURN_FALSE;
              }
       }
       if (!cmd_len) {
              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot execute a blank command");
              RETURN_FALSE;
       }

       if (!ret_array) {
              ret = php_exec(mode, cmd, NULL, return_value TSRMLS_CC);
       } else {
              if (Z_TYPE_P(ret_array) != IS_ARRAY) {
                     zval_dtor(ret_array);
                     array_init(ret_array);
              }
              ret = php_exec(2, cmd, ret_array, return_value TSRMLS_CC);
       }
       if (ret_code) {
              zval_dtor(ret_code);
              ZVAL_LONG(ret_code, ret);
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 248 of file exec.c.

Here is the call graph for this function:

PHP_FUNCTION ( system  )

Definition at line 256 of file exec.c.

Here is the call graph for this function:

Definition at line 264 of file exec.c.

Here is the call graph for this function:

PHP_FUNCTION ( escapeshellcmd  )

Definition at line 434 of file exec.c.

{
       char *command;
       int command_len;
       char *cmd = NULL;

       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &command, &command_len) == FAILURE) {
              return;
       }

       if (command_len) {
              cmd = php_escape_shell_cmd(command);
              RETVAL_STRING(cmd, 0);
       } else {
              RETVAL_EMPTY_STRING();
       }
}

Here is the call graph for this function:

PHP_FUNCTION ( escapeshellarg  )

Definition at line 455 of file exec.c.

{
       char *argument;
       int argument_len;
       char *cmd = NULL;

       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &argument, &argument_len) == FAILURE) {
              return;
       }

       if (argument) {
              cmd = php_escape_shell_arg(argument);
              RETVAL_STRING(cmd, 0);
       }
}

Here is the call graph for this function:

PHP_FUNCTION ( shell_exec  )

Definition at line 474 of file exec.c.

{
       FILE *in;
       size_t total_readbytes;
       char *command;
       int command_len;
       char *ret;
       php_stream *stream;

       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &command, &command_len) == FAILURE) {
              return;
       }

       if (PG(safe_mode)) {
              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot execute using backquotes in Safe Mode");
              RETURN_FALSE;
       }

#ifdef PHP_WIN32
       if ((in=VCWD_POPEN(command, "rt"))==NULL) {
#else
       if ((in=VCWD_POPEN(command, "r"))==NULL) {
#endif
              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to execute '%s'", command);
              RETURN_FALSE;
       }

       stream = php_stream_fopen_from_pipe(in, "rb");
       total_readbytes = php_stream_copy_to_mem(stream, &ret, PHP_STREAM_COPY_ALL, 0);
       php_stream_close(stream);

       if (total_readbytes > 0) {
              RETVAL_STRINGL(ret, total_readbytes, 0);
       }
}

Here is the call graph for this function: