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 - pcntl - pcntl.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 281
Code covered: 43.1 % Executed lines: 121
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       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: Jason Greene <jason@inetgurus.net>                           |
      16                 :    +----------------------------------------------------------------------+
      17                 :  */
      18                 : 
      19                 : /* $Id: pcntl.c 281178 2009-05-26 14:02:34Z lbarnaud $ */
      20                 : 
      21                 : #define PCNTL_DEBUG 0
      22                 : 
      23                 : #if PCNTL_DEBUG
      24                 : #define DEBUG_OUT printf("DEBUG: ");printf
      25                 : #define IF_DEBUG(z) z
      26                 : #else
      27                 : #define IF_DEBUG(z)
      28                 : #endif
      29                 : 
      30                 : #ifdef HAVE_CONFIG_H
      31                 : #include "config.h"
      32                 : #endif
      33                 : 
      34                 : #include "php.h"
      35                 : #include "php_ini.h"
      36                 : #include "ext/standard/info.h"
      37                 : #include "php_pcntl.h"
      38                 : 
      39                 : #if HAVE_GETPRIORITY || HAVE_SETPRIORITY || HAVE_WAIT3
      40                 : #include <sys/time.h>
      41                 : #include <sys/resource.h>
      42                 : #endif
      43                 : 
      44                 : ZEND_DECLARE_MODULE_GLOBALS(pcntl)
      45                 : static PHP_GINIT_FUNCTION(pcntl);
      46                 : 
      47                 : zend_function_entry pcntl_functions[] = {
      48                 :         PHP_FE(pcntl_fork,                      NULL)
      49                 :         PHP_FE(pcntl_waitpid,           second_arg_force_ref)
      50                 :         PHP_FE(pcntl_wait,              first_arg_force_ref)
      51                 :         PHP_FE(pcntl_signal,            NULL)
      52                 :         PHP_FE(pcntl_wifexited,         NULL)
      53                 :         PHP_FE(pcntl_wifstopped,        NULL)
      54                 :         PHP_FE(pcntl_wifsignaled,       NULL)
      55                 :         PHP_FE(pcntl_wexitstatus,       NULL)
      56                 :         PHP_FE(pcntl_wtermsig,          NULL)
      57                 :         PHP_FE(pcntl_wstopsig,          NULL)
      58                 :         PHP_FE(pcntl_exec,                      NULL)
      59                 :         PHP_FE(pcntl_alarm,                     NULL)
      60                 : #ifdef HAVE_GETPRIORITY
      61                 :         PHP_FE(pcntl_getpriority,       NULL)
      62                 : #endif
      63                 : #ifdef HAVE_SETPRIORITY
      64                 :         PHP_FE(pcntl_setpriority,       NULL)
      65                 : #endif
      66                 :         {NULL, NULL, NULL}      
      67                 : };
      68                 : 
      69                 : zend_module_entry pcntl_module_entry = {
      70                 :         STANDARD_MODULE_HEADER,
      71                 :         "pcntl",
      72                 :         pcntl_functions,
      73                 :         PHP_MINIT(pcntl),
      74                 :         PHP_MSHUTDOWN(pcntl),
      75                 :         PHP_RINIT(pcntl),
      76                 :         PHP_RSHUTDOWN(pcntl),
      77                 :         PHP_MINFO(pcntl),
      78                 :         NO_VERSION_YET,
      79                 :         PHP_MODULE_GLOBALS(pcntl),
      80                 :         PHP_GINIT(pcntl),
      81                 :         NULL,
      82                 :         NULL,
      83                 :         STANDARD_MODULE_PROPERTIES_EX
      84                 : };
      85                 : 
      86                 : #ifdef COMPILE_DL_PCNTL
      87                 : ZEND_GET_MODULE(pcntl)
      88                 : # ifdef PHP_WIN32
      89                 : # include "zend_arg_defs.c"
      90                 : # endif
      91                 : #endif
      92                 : 
      93                 : static void pcntl_signal_handler(int);
      94                 : static void pcntl_tick_handler();
      95                 :   
      96                 : void php_register_signal_constants(INIT_FUNC_ARGS)
      97           13565 : {
      98                 : 
      99                 :         /* Wait Constants */
     100                 : #ifdef WNOHANG
     101           13565 :         REGISTER_LONG_CONSTANT("WNOHANG",  (long) WNOHANG, CONST_CS | CONST_PERSISTENT);
     102                 : #endif
     103                 : #ifdef WUNTRACED
     104           13565 :         REGISTER_LONG_CONSTANT("WUNTRACED",  (long) WUNTRACED, CONST_CS | CONST_PERSISTENT);
     105                 : #endif
     106                 : 
     107                 :         /* Signal Constants */
     108           13565 :         REGISTER_LONG_CONSTANT("SIG_IGN",  (long) SIG_IGN, CONST_CS | CONST_PERSISTENT);
     109           13565 :         REGISTER_LONG_CONSTANT("SIG_DFL",  (long) SIG_DFL, CONST_CS | CONST_PERSISTENT);
     110           13565 :         REGISTER_LONG_CONSTANT("SIG_ERR",  (long) SIG_ERR, CONST_CS | CONST_PERSISTENT);
     111           13565 :         REGISTER_LONG_CONSTANT("SIGHUP",   (long) SIGHUP,  CONST_CS | CONST_PERSISTENT);
     112           13565 :         REGISTER_LONG_CONSTANT("SIGINT",   (long) SIGINT,  CONST_CS | CONST_PERSISTENT);
     113           13565 :         REGISTER_LONG_CONSTANT("SIGQUIT",  (long) SIGQUIT, CONST_CS | CONST_PERSISTENT);
     114           13565 :         REGISTER_LONG_CONSTANT("SIGILL",   (long) SIGILL,  CONST_CS | CONST_PERSISTENT);
     115           13565 :         REGISTER_LONG_CONSTANT("SIGTRAP",  (long) SIGTRAP, CONST_CS | CONST_PERSISTENT);
     116           13565 :         REGISTER_LONG_CONSTANT("SIGABRT",  (long) SIGABRT, CONST_CS | CONST_PERSISTENT);
     117                 : #ifdef SIGIOT
     118           13565 :         REGISTER_LONG_CONSTANT("SIGIOT",   (long) SIGIOT,  CONST_CS | CONST_PERSISTENT);
     119                 : #endif
     120           13565 :         REGISTER_LONG_CONSTANT("SIGBUS",   (long) SIGBUS,  CONST_CS | CONST_PERSISTENT);
     121           13565 :         REGISTER_LONG_CONSTANT("SIGFPE",   (long) SIGFPE,  CONST_CS | CONST_PERSISTENT);
     122           13565 :         REGISTER_LONG_CONSTANT("SIGKILL",  (long) SIGKILL, CONST_CS | CONST_PERSISTENT);
     123           13565 :         REGISTER_LONG_CONSTANT("SIGUSR1",  (long) SIGUSR1, CONST_CS | CONST_PERSISTENT);
     124           13565 :         REGISTER_LONG_CONSTANT("SIGSEGV",  (long) SIGSEGV, CONST_CS | CONST_PERSISTENT);
     125           13565 :         REGISTER_LONG_CONSTANT("SIGUSR2",  (long) SIGUSR2, CONST_CS | CONST_PERSISTENT);
     126           13565 :         REGISTER_LONG_CONSTANT("SIGPIPE",  (long) SIGPIPE, CONST_CS | CONST_PERSISTENT);
     127           13565 :         REGISTER_LONG_CONSTANT("SIGALRM",  (long) SIGALRM, CONST_CS | CONST_PERSISTENT);
     128           13565 :         REGISTER_LONG_CONSTANT("SIGTERM",  (long) SIGTERM, CONST_CS | CONST_PERSISTENT);
     129                 : #ifdef SIGSTKFLT
     130           13565 :         REGISTER_LONG_CONSTANT("SIGSTKFLT",(long) SIGSTKFLT, CONST_CS | CONST_PERSISTENT);
     131                 : #endif 
     132                 : #ifdef SIGCLD
     133           13565 :         REGISTER_LONG_CONSTANT("SIGCLD",   (long) SIGCLD, CONST_CS | CONST_PERSISTENT);
     134                 : #endif
     135                 : #ifdef SIGCHLD
     136           13565 :         REGISTER_LONG_CONSTANT("SIGCHLD",  (long) SIGCHLD, CONST_CS | CONST_PERSISTENT);
     137                 : #endif
     138           13565 :         REGISTER_LONG_CONSTANT("SIGCONT",  (long) SIGCONT, CONST_CS | CONST_PERSISTENT);
     139           13565 :         REGISTER_LONG_CONSTANT("SIGSTOP",  (long) SIGSTOP, CONST_CS | CONST_PERSISTENT);
     140           13565 :         REGISTER_LONG_CONSTANT("SIGTSTP",  (long) SIGTSTP, CONST_CS | CONST_PERSISTENT);
     141           13565 :         REGISTER_LONG_CONSTANT("SIGTTIN",  (long) SIGTTIN, CONST_CS | CONST_PERSISTENT);
     142           13565 :         REGISTER_LONG_CONSTANT("SIGTTOU",  (long) SIGTTOU, CONST_CS | CONST_PERSISTENT);
     143           13565 :         REGISTER_LONG_CONSTANT("SIGURG",   (long) SIGURG , CONST_CS | CONST_PERSISTENT);
     144           13565 :         REGISTER_LONG_CONSTANT("SIGXCPU",  (long) SIGXCPU, CONST_CS | CONST_PERSISTENT);
     145           13565 :         REGISTER_LONG_CONSTANT("SIGXFSZ",  (long) SIGXFSZ, CONST_CS | CONST_PERSISTENT);
     146           13565 :         REGISTER_LONG_CONSTANT("SIGVTALRM",(long) SIGVTALRM, CONST_CS | CONST_PERSISTENT);
     147           13565 :         REGISTER_LONG_CONSTANT("SIGPROF",  (long) SIGPROF, CONST_CS | CONST_PERSISTENT);
     148           13565 :         REGISTER_LONG_CONSTANT("SIGWINCH", (long) SIGWINCH, CONST_CS | CONST_PERSISTENT);
     149                 : #ifdef SIGPOLL
     150           13565 :         REGISTER_LONG_CONSTANT("SIGPOLL",  (long) SIGPOLL, CONST_CS | CONST_PERSISTENT);
     151                 : #endif
     152           13565 :         REGISTER_LONG_CONSTANT("SIGIO",    (long) SIGIO, CONST_CS | CONST_PERSISTENT);
     153                 : #ifdef SIGPWR
     154           13565 :         REGISTER_LONG_CONSTANT("SIGPWR",   (long) SIGPWR, CONST_CS | CONST_PERSISTENT);
     155                 : #endif
     156                 : #ifdef SIGSYS
     157           13565 :         REGISTER_LONG_CONSTANT("SIGSYS",   (long) SIGSYS, CONST_CS | CONST_PERSISTENT);
     158           13565 :         REGISTER_LONG_CONSTANT("SIGBABY",  (long) SIGSYS, CONST_CS | CONST_PERSISTENT);
     159                 : #endif
     160                 : 
     161                 : #if HAVE_GETPRIORITY || HAVE_SETPRIORITY
     162           13565 :         REGISTER_LONG_CONSTANT("PRIO_PGRP", PRIO_PGRP, CONST_CS | CONST_PERSISTENT);
     163           13565 :         REGISTER_LONG_CONSTANT("PRIO_USER", PRIO_USER, CONST_CS | CONST_PERSISTENT);
     164           13565 :         REGISTER_LONG_CONSTANT("PRIO_PROCESS", PRIO_PROCESS, CONST_CS | CONST_PERSISTENT);
     165                 : #endif
     166           13565 : }
     167                 : 
     168                 : static PHP_GINIT_FUNCTION(pcntl)
     169           13565 : { 
     170           13565 :         memset(pcntl_globals, 0, sizeof(*pcntl_globals));
     171           13565 : }
     172                 : 
     173                 : PHP_RINIT_FUNCTION(pcntl)
     174           13551 : {
     175           13551 :         zend_hash_init(&PCNTL_G(php_signal_table), 16, NULL, ZVAL_PTR_DTOR, 0);
     176           13551 :         PCNTL_G(head) = PCNTL_G(tail) = PCNTL_G(spares) = NULL;
     177           13551 :         return SUCCESS;
     178                 : }
     179                 : 
     180                 : PHP_MINIT_FUNCTION(pcntl)
     181           13565 : {
     182           13565 :         php_register_signal_constants(INIT_FUNC_ARGS_PASSTHRU);
     183           13565 :         php_add_tick_function(pcntl_tick_handler);
     184                 : 
     185           13565 :         return SUCCESS;
     186                 : }
     187                 : 
     188                 : PHP_MSHUTDOWN_FUNCTION(pcntl)
     189           13598 : {
     190           13598 :         return SUCCESS;
     191                 : }
     192                 : 
     193                 : PHP_RSHUTDOWN_FUNCTION(pcntl)
     194           13584 : {
     195                 :         struct php_pcntl_pending_signal *sig;
     196                 : 
     197                 :         /* FIXME: if a signal is delivered after this point, things will go pear shaped;
     198                 :          * need to remove signal handlers */
     199           13584 :         zend_hash_destroy(&PCNTL_G(php_signal_table));
     200           27168 :         while (PCNTL_G(head)) {
     201               0 :                 sig = PCNTL_G(head);
     202               0 :                 PCNTL_G(head) = sig->next;
     203               0 :                 efree(sig);
     204                 :         }
     205           27168 :         while (PCNTL_G(spares)) {
     206               0 :                 sig = PCNTL_G(spares);
     207               0 :                 PCNTL_G(spares) = sig->next;
     208               0 :                 efree(sig);
     209                 :         }
     210           13584 :         return SUCCESS;
     211                 : }
     212                 : 
     213                 : PHP_MINFO_FUNCTION(pcntl)
     214               6 : {
     215               6 :         php_info_print_table_start();
     216               6 :         php_info_print_table_header(2, "pcntl support", "enabled");
     217               6 :         php_info_print_table_end();
     218               6 : }
     219                 : 
     220                 : /* {{{ proto int pcntl_fork(void)
     221                 :    Forks the currently running process following the same behavior as the UNIX fork() system call*/
     222                 : PHP_FUNCTION(pcntl_fork)
     223              50 : {
     224                 :         pid_t id;
     225                 : 
     226              50 :         id = fork();
     227              86 :         if (id == -1) {
     228               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d", errno);
     229                 :         }
     230                 :         
     231              86 :         RETURN_LONG((long) id);
     232                 : }
     233                 : /* }}} */
     234                 : 
     235                 : /* {{{ proto int pcntl_alarm(int seconds)
     236                 :    Set an alarm clock for delivery of a signal*/
     237                 : PHP_FUNCTION(pcntl_alarm)
     238              13 : {
     239                 :         long seconds;
     240                 : 
     241              13 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &seconds) == FAILURE)
     242               0 :                 return;
     243                 :         
     244              13 :         RETURN_LONG ((long) alarm(seconds));
     245                 : }
     246                 : /* }}} */
     247                 : 
     248                 : /* {{{ proto int pcntl_waitpid(int pid, int &status, int options)
     249                 :    Waits on or returns the status of a forked child as defined by the waitpid() system call */
     250                 : PHP_FUNCTION(pcntl_waitpid)
     251              19 : {
     252              19 :         long pid, options = 0;
     253              19 :         zval *z_status = NULL;
     254                 :         int status;
     255                 :         pid_t child_id;
     256                 : 
     257              19 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz|l", &pid, &z_status, &options) == FAILURE)
     258               0 :                 return;
     259                 :         
     260              19 :         convert_to_long_ex(&z_status);
     261                 : 
     262              19 :         status = Z_LVAL_P(z_status);
     263                 : 
     264              19 :         child_id = waitpid((pid_t) pid, &status, options);
     265                 : 
     266              19 :         Z_LVAL_P(z_status) = status;
     267                 : 
     268              19 :         RETURN_LONG((long) child_id);
     269                 : }
     270                 : /* }}} */
     271                 : 
     272                 : /* {{{ proto int pcntl_wait(int &status)
     273                 :    Waits on or returns the status of a forked child as defined by the waitpid() system call */
     274                 : PHP_FUNCTION(pcntl_wait)
     275               3 : {
     276               3 :         long options = 0;
     277               3 :         zval *z_status = NULL;
     278                 :         int status;
     279                 :         pid_t child_id;
     280                 : 
     281               3 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &z_status, &options) == FAILURE)
     282               0 :                 return;
     283                 :         
     284               3 :         convert_to_long_ex(&z_status);
     285                 : 
     286               3 :         status = Z_LVAL_P(z_status);
     287                 : #ifdef HAVE_WAIT3
     288               3 :         if(options) {
     289               0 :                 child_id = wait3(&status, options, NULL);
     290                 :         }
     291                 :         else {
     292               3 :                 child_id = wait(&status);
     293                 :         }
     294                 : #else
     295                 :         child_id = wait(&status);
     296                 : #endif
     297               3 :         Z_LVAL_P(z_status) = status;
     298                 : 
     299               3 :         RETURN_LONG((long) child_id);
     300                 : }
     301                 : /* }}} */
     302                 : 
     303                 : /* {{{ proto bool pcntl_wifexited(int status) 
     304                 :    Returns true if the child status code represents a successful exit */
     305                 : PHP_FUNCTION(pcntl_wifexited)
     306               1 : {
     307                 : #ifdef WIFEXITED
     308                 :         zval **status;
     309                 :         int status_word;
     310                 :         
     311               1 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(ZEND_NUM_ARGS(), &status) == FAILURE) {
     312               0 :                 WRONG_PARAM_COUNT;
     313                 :         }
     314                 :         
     315               1 :         status_word = (int) Z_LVAL_PP(status);
     316                 :         
     317               1 :         if (WIFEXITED(status_word)) RETURN_TRUE;
     318                 : #endif
     319               0 :         RETURN_FALSE;
     320                 : }
     321                 : /* }}} */
     322                 : 
     323                 : /* {{{ proto bool pcntl_wifstopped(int status) 
     324                 :    Returns true if the child status code represents a stopped process (WUNTRACED must have been used with waitpid) */
     325                 : PHP_FUNCTION(pcntl_wifstopped)
     326               1 : {
     327                 : #ifdef WIFSTOPPED
     328                 :         zval **status;
     329                 :         int status_word;
     330                 :         
     331               1 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(ZEND_NUM_ARGS(), &status) == FAILURE) {
     332               0 :                 WRONG_PARAM_COUNT;
     333                 :         }
     334                 :         
     335               1 :         status_word = (int) Z_LVAL_PP(status);
     336                 :         
     337               1 :         if (WIFSTOPPED(status_word)) RETURN_TRUE;
     338                 : #endif
     339               0 :         RETURN_FALSE;
     340                 : }
     341                 : /* }}} */
     342                 : 
     343                 : /* {{{ proto bool pcntl_wifsignaled(int status) 
     344                 :    Returns true if the child status code represents a process that was terminated due to a signal */
     345                 : PHP_FUNCTION(pcntl_wifsignaled)
     346               1 : {
     347                 : #ifdef WIFSIGNALED
     348                 :         zval **status;
     349                 :         int status_word;
     350                 :         
     351               1 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(ZEND_NUM_ARGS(), &status) == FAILURE) {
     352               0 :                 WRONG_PARAM_COUNT;
     353                 :         }
     354                 :         
     355               1 :         status_word = (int) Z_LVAL_PP(status);
     356                 :         
     357               1 :         if (WIFSIGNALED(status_word)) RETURN_TRUE;
     358                 : #endif
     359               0 :         RETURN_FALSE;
     360                 : }
     361                 : /* }}} */
     362                 : 
     363                 : /* {{{ proto int pcntl_wexitstatus(int status) 
     364                 :    Returns the status code of a child's exit */
     365                 : PHP_FUNCTION(pcntl_wexitstatus)
     366               2 : {
     367                 : #ifdef WEXITSTATUS
     368                 :         zval **status;
     369                 :         int status_word;
     370                 :         
     371               2 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(ZEND_NUM_ARGS(), &status) == FAILURE) {
     372               0 :                 WRONG_PARAM_COUNT;
     373                 :         }
     374                 :         
     375               2 :         status_word = (int) Z_LVAL_PP(status);
     376                 : 
     377               2 :         RETURN_LONG(WEXITSTATUS(status_word));
     378                 : #else
     379                 :         RETURN_FALSE;
     380                 : #endif
     381                 : }
     382                 : /* }}} */
     383                 : 
     384                 : /* {{{ proto int pcntl_wtermsig(int status) 
     385                 :    Returns the number of the signal that terminated the process who's status code is passed  */
     386                 : PHP_FUNCTION(pcntl_wtermsig)
     387               1 : {
     388                 : #ifdef WTERMSIG
     389                 :         zval **status;
     390                 :         int status_word;
     391                 :         
     392               1 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(ZEND_NUM_ARGS(), &status) == FAILURE) {
     393               0 :                 WRONG_PARAM_COUNT;
     394                 :         }
     395                 :         
     396               1 :         status_word = (int) Z_LVAL_PP(status);
     397                 :         
     398               1 :         RETURN_LONG(WTERMSIG(status_word));
     399                 : #else
     400                 :         RETURN_FALSE;
     401                 : #endif
     402                 : }
     403                 : /* }}} */
     404                 : 
     405                 : /* {{{ proto int pcntl_wstopsig(int status) 
     406                 :    Returns the number of the signal that caused the process to stop who's status code is passed */
     407                 : PHP_FUNCTION(pcntl_wstopsig)
     408               1 : {
     409                 : #ifdef WSTOPSIG
     410                 :         zval **status;
     411                 :         int status_word;
     412                 :    
     413               1 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(ZEND_NUM_ARGS(), &status) == FAILURE) {
     414               0 :                 WRONG_PARAM_COUNT;
     415                 :         }
     416                 :    
     417               1 :         status_word = (int) Z_LVAL_PP(status);
     418                 : 
     419               1 :         RETURN_LONG(WSTOPSIG(status_word));
     420                 : #else
     421                 :         RETURN_FALSE;
     422                 : #endif
     423                 : }
     424                 : /* }}} */
     425                 : 
     426                 : /* {{{ proto bool pcntl_exec(string path [, array args [, array envs]])
     427                 :    Executes specified program in current process space as defined by exec(2) */
     428                 : PHP_FUNCTION(pcntl_exec)
     429               0 : {
     430                 :         zval *args, *envs;
     431                 :         zval **element;
     432                 :         HashTable *args_hash, *envs_hash;
     433               0 :         int argc = 0, argi = 0;
     434               0 :         int envc = 0, envi = 0;
     435               0 :         int return_val = 0;
     436               0 :         char **argv = NULL, **envp = NULL;
     437                 :         char **current_arg, **pair;
     438                 :         int pair_length;
     439                 :         char *key;
     440                 :         int key_length;
     441                 :         char *path;
     442                 :         int path_len;
     443                 :         long key_num;
     444                 :                 
     445               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|aa", &path, &path_len, &args, &envs) == FAILURE) {
     446               0 :                 return;
     447                 :         }
     448                 :         
     449               0 :         if (ZEND_NUM_ARGS() > 1) {
     450                 :                 /* Build argumnent list */
     451               0 :                 args_hash = HASH_OF(args);
     452               0 :                 argc = zend_hash_num_elements(args_hash);
     453                 :                 
     454               0 :                 argv = safe_emalloc((argc + 2), sizeof(char *), 0);
     455               0 :                 *argv = path;
     456               0 :                 for ( zend_hash_internal_pointer_reset(args_hash), current_arg = argv+1; 
     457               0 :                         (argi < argc && (zend_hash_get_current_data(args_hash, (void **) &element) == SUCCESS));
     458               0 :                         (argi++, current_arg++, zend_hash_move_forward(args_hash)) ) {
     459                 : 
     460               0 :                         convert_to_string_ex(element);
     461               0 :                         *current_arg = Z_STRVAL_PP(element);
     462                 :                 }
     463               0 :                 *(current_arg) = NULL;
     464                 :         } else {
     465               0 :                 argv = emalloc(2 * sizeof(char *));
     466               0 :                 *argv = path;
     467               0 :                 *(argv+1) = NULL;
     468                 :         }
     469                 : 
     470               0 :         if ( ZEND_NUM_ARGS() == 3 ) {
     471                 :                 /* Build environment pair list */
     472               0 :                 envs_hash = HASH_OF(envs);
     473               0 :                 envc = zend_hash_num_elements(envs_hash);
     474                 :                 
     475               0 :                 envp = safe_emalloc((envc + 1), sizeof(char *), 0);
     476               0 :                 for ( zend_hash_internal_pointer_reset(envs_hash), pair = envp; 
     477               0 :                         (envi < envc && (zend_hash_get_current_data(envs_hash, (void **) &element) == SUCCESS));
     478               0 :                         (envi++, pair++, zend_hash_move_forward(envs_hash)) ) {
     479               0 :                         switch (return_val = zend_hash_get_current_key_ex(envs_hash, &key, &key_length, &key_num, 0, NULL)) {
     480                 :                                 case HASH_KEY_IS_LONG:
     481               0 :                                         key = emalloc(101);
     482               0 :                                         snprintf(key, 100, "%ld", key_num);
     483               0 :                                         key_length = strlen(key);
     484               0 :                                         break;
     485                 :                                 case HASH_KEY_NON_EXISTANT:
     486               0 :                                         pair--;
     487               0 :                                         continue;
     488                 :                         }
     489                 : 
     490               0 :                         convert_to_string_ex(element);
     491                 : 
     492                 :                         /* Length of element + equal sign + length of key + null */ 
     493               0 :                         pair_length = Z_STRLEN_PP(element) + key_length + 2;
     494               0 :                         *pair = emalloc(pair_length);
     495               0 :                         strlcpy(*pair, key, key_length); 
     496               0 :                         strlcat(*pair, "=", pair_length);
     497               0 :                         strlcat(*pair, Z_STRVAL_PP(element), pair_length);
     498                 :                         
     499                 :                         /* Cleanup */
     500               0 :                         if (return_val == HASH_KEY_IS_LONG) efree(key);
     501                 :                 }
     502               0 :                 *(pair) = NULL;
     503                 :         }
     504                 :         
     505               0 :         if (execve(path, argv, envp) == -1) {
     506               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error has occured: (errno %d) %s", errno, strerror(errno));
     507                 :         }
     508                 :         
     509                 :         /* Cleanup */
     510               0 :         if (envp != NULL) {
     511               0 :                 for (pair = envp; *pair != NULL; pair++) efree(*pair);
     512               0 :                 efree(envp);
     513                 :         }
     514                 : 
     515               0 :         efree(argv);
     516                 :         
     517               0 :         RETURN_FALSE;
     518                 : }
     519                 : /* }}} */
     520                 : 
     521                 : /* {{{ proto bool pcntl_signal(int signo, callback handle [, bool restart_syscalls])
     522                 :    Assigns a system signal handler to a PHP function */
     523                 : PHP_FUNCTION(pcntl_signal)
     524               0 : {
     525               0 :         zval *handle, **dest_handle = NULL;
     526                 :         char *func_name;
     527                 :         long signo;
     528               0 :         zend_bool restart_syscalls = 1;
     529                 : 
     530               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz|b", &signo, &handle, &restart_syscalls) == FAILURE) {
     531               0 :                 return;
     532                 :         }
     533                 : 
     534               0 :         if (!PCNTL_G(spares)) {
     535                 :                 /* since calling malloc() from within a signal handler is not portable,
     536                 :                  * pre-allocate a few records for recording signals */
     537                 :                 int i;
     538               0 :                 for (i = 0; i < 32; i++) {
     539                 :                         struct php_pcntl_pending_signal *psig;
     540                 : 
     541               0 :                         psig = emalloc(sizeof(*psig));
     542               0 :                         psig->next = PCNTL_G(spares);
     543               0 :                         PCNTL_G(spares) = psig;
     544                 :                 }
     545                 :         }
     546                 : 
     547                 :         /* Special long value case for SIG_DFL and SIG_IGN */
     548               0 :         if (Z_TYPE_P(handle)==IS_LONG) {
     549               0 :                 if (Z_LVAL_P(handle)!= (long) SIG_DFL && Z_LVAL_P(handle) != (long) SIG_IGN) {
     550               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for handle argument specified");
     551                 :                 }
     552               0 :                 if (php_signal(signo, (Sigfunc *) Z_LVAL_P(handle), (int) restart_syscalls) == SIG_ERR) {
     553               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error assigning signal");
     554               0 :                         RETURN_FALSE;
     555                 :                 }
     556               0 :                 RETURN_TRUE;
     557                 :         }
     558                 :         
     559               0 :         if (!zend_is_callable(handle, 0, &func_name)) {
     560               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s is not a callable function name error", func_name);
     561               0 :                 efree(func_name);
     562               0 :                 RETURN_FALSE;
     563                 :         }
     564               0 :         efree(func_name);
     565                 :         
     566                 :         /* Add the function name to our signal table */
     567               0 :         zend_hash_index_update(&PCNTL_G(php_signal_table), signo, (void **) &handle, sizeof(zval *), (void **) &dest_handle);
     568               0 :         if (dest_handle) zval_add_ref(dest_handle);
     569                 :         
     570               0 :         if (php_signal(signo, pcntl_signal_handler, (int) restart_syscalls) == SIG_ERR) {
     571               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error assigning signal");
     572               0 :                 RETURN_FALSE;
     573                 :         }
     574               0 :         RETURN_TRUE;
     575                 : }
     576                 : /* }}} */
     577                 : 
     578                 : #ifdef HAVE_GETPRIORITY
     579                 : /* {{{ proto int pcntl_getpriority([int pid [, int process_identifier]])
     580                 :    Get the priority of any process */
     581                 : PHP_FUNCTION(pcntl_getpriority)
     582               0 : {
     583               0 :         long who = PRIO_PROCESS;
     584               0 :         long pid = getpid();
     585                 :         int pri;
     586                 :         
     587               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &pid, &who) == FAILURE) {
     588               0 :                 RETURN_FALSE;
     589                 :         }
     590                 : 
     591                 :         /* needs to be cleared, since any returned value is valid */ 
     592               0 :         errno = 0;
     593                 : 
     594               0 :         pri = getpriority(who, pid);
     595                 : 
     596               0 :         if (errno) {
     597               0 :                 switch (errno) {
     598                 :                         case ESRCH:
     599               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: No process was located using the given parameters", errno);
     600               0 :                                 break;
     601                 :                         case EINVAL:
     602               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: Invalid identifier flag", errno);
     603               0 :                                 break;
     604                 :                         default:
     605               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error %d has occured", errno);
     606                 :                                 break;
     607                 :                 }
     608               0 :                 RETURN_FALSE;
     609                 :         }
     610                 : 
     611               0 :         RETURN_LONG(pri);
     612                 : }
     613                 : /* }}} */
     614                 : #endif
     615                 : 
     616                 : #ifdef HAVE_SETPRIORITY
     617                 : /* {{{ proto bool pcntl_setpriority(int priority [, int pid [, int process_identifier]])
     618                 :    Change the priority of any process */
     619                 : PHP_FUNCTION(pcntl_setpriority)
     620               0 : {
     621               0 :         long who = PRIO_PROCESS;
     622               0 :         long pid = getpid();
     623                 :         long pri;
     624                 : 
     625               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|ll", &pri, &pid, &who) == FAILURE) {
     626               0 :                 RETURN_FALSE;
     627                 :         }
     628                 : 
     629               0 :         if (setpriority(who, pid, pri)) {
     630               0 :                 switch (errno) {
     631                 :                         case ESRCH:
     632               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: No process was located using the given parameters", errno);
     633               0 :                                 break;
     634                 :                         case EINVAL:
     635               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: Invalid identifier flag", errno);
     636               0 :                                 break;
     637                 :                         case EPERM:
     638               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: A process was located, but neither its effective nor real user ID matched the effective user ID of the caller", errno);
     639               0 :                                 break;
     640                 :                         case EACCES:
     641               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: Only a super user may attempt to increase the process priority", errno);
     642               0 :                                 break;
     643                 :                         default:
     644               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error %d has occured", errno);
     645                 :                                 break;
     646                 :                 }
     647               0 :                 RETURN_FALSE;
     648                 :         }
     649                 :         
     650               0 :         RETURN_TRUE;
     651                 : }
     652                 : /* }}} */
     653                 : #endif
     654                 : 
     655                 : /* Our custom signal handler that calls the appropriate php_function */
     656                 : static void pcntl_signal_handler(int signo)
     657               0 : {
     658                 :         struct php_pcntl_pending_signal *psig;
     659                 :         TSRMLS_FETCH();
     660                 :         
     661               0 :         psig = PCNTL_G(spares);
     662               0 :         if (!psig) {
     663                 :                 /* oops, too many signals for us to track, so we'll forget about this one */
     664               0 :                 return;
     665                 :         }
     666               0 :         PCNTL_G(spares) = psig->next;
     667                 : 
     668               0 :         psig->signo = signo;
     669               0 :         psig->next = NULL;
     670                 : 
     671                 :         /* the head check is important, as the tick handler cannot atomically clear both
     672                 :          * the head and tail */
     673               0 :         if (PCNTL_G(head) && PCNTL_G(tail)) {
     674               0 :                 PCNTL_G(tail)->next = psig;
     675                 :         } else {
     676               0 :                 PCNTL_G(head) = psig;
     677                 :         }
     678               0 :         PCNTL_G(tail) = psig;
     679                 : }
     680                 : 
     681                 : void pcntl_tick_handler()
     682               5 : {
     683                 :         zval *param, **handle, *retval;
     684                 :         struct php_pcntl_pending_signal *queue, *next;
     685                 :         TSRMLS_FETCH();
     686                 : 
     687                 :         /* Bail if the queue is empty or if we are already playing the queue*/
     688               5 :         if (! PCNTL_G(head) || PCNTL_G(processing_signal_queue))
     689               5 :                 return;
     690                 : 
     691                 :         /* Prevent reentrant handler calls */
     692               0 :         PCNTL_G(processing_signal_queue) = 1;
     693                 : 
     694               0 :         queue = PCNTL_G(head);
     695               0 :         PCNTL_G(head) = NULL; /* simple stores are atomic */
     696                 :         
     697                 :         /* Allocate */
     698                 : 
     699               0 :         while (queue) {
     700               0 :                 if (zend_hash_index_find(&PCNTL_G(php_signal_table), queue->signo, (void **) &handle)==SUCCESS) {
     701               0 :                         MAKE_STD_ZVAL(retval);
     702               0 :                         MAKE_STD_ZVAL(param);
     703               0 :                         ZVAL_NULL(retval);
     704               0 :                         ZVAL_LONG(param, queue->signo);
     705                 : 
     706                 :                         /* Call php signal handler - Note that we do not report errors, and we ignore the return value */
     707                 :                         /* FIXME: this is probably broken when multiple signals are handled in this while loop (retval) */
     708               0 :                         call_user_function(EG(function_table), NULL, *handle, retval, 1, &param TSRMLS_CC);
     709               0 :                         zval_ptr_dtor(&param);
     710               0 :                         zval_ptr_dtor(&retval);
     711                 :                 }
     712                 : 
     713               0 :                 next = queue->next;
     714               0 :                 queue->next = PCNTL_G(spares);
     715               0 :                 PCNTL_G(spares) = queue;
     716               0 :                 queue = next;
     717                 :         }
     718                 : 
     719                 :         /* Re-enable queue */
     720               0 :         PCNTL_G(processing_signal_queue) = 0;
     721                 : }
     722                 : 
     723                 : 
     724                 : 
     725                 : /*
     726                 :  * Local variables:
     727                 :  * tab-width: 4
     728                 :  * c-basic-offset: 4
     729                 :  * indent-tabs-mode: t
     730                 :  * End:
     731                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:14 +0000 (5 days ago)

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