44
44
#include <sys/resource.h>
45
45
#endif
46
46
47
+ #include <errno.h>
48
+
47
49
ZEND_DECLARE_MODULE_GLOBALS (pcntl )
48
50
static PHP_GINIT_FUNCTION (pcntl );
49
51
@@ -134,6 +136,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_setpriority, 0, 0, 1)
134
136
ZEND_ARG_INFO (0 , process_identifier )
135
137
ZEND_END_ARG_INFO ()
136
138
#endif
139
+
140
+ ZEND_BEGIN_ARG_INFO_EX (arginfo_pcntl_strerror , 0 , 0 , 1 )
141
+ ZEND_ARG_INFO (0 , errno )
142
+ ZEND_END_ARG_INFO ()
137
143
/* }}} */
138
144
139
145
const zend_function_entry pcntl_functions [] = {
@@ -150,6 +156,9 @@ const zend_function_entry pcntl_functions[] = {
150
156
PHP_FE (pcntl_wstopsig , arginfo_pcntl_wstopsig )
151
157
PHP_FE (pcntl_exec , arginfo_pcntl_exec )
152
158
PHP_FE (pcntl_alarm , arginfo_pcntl_alarm )
159
+ PHP_FE (pcntl_get_last_error , arginfo_pcntl_void )
160
+ PHP_FALIAS (pcntl_errno , pcntl_get_last_error , NULL )
161
+ PHP_FE (pcntl_strerror , arginfo_pcntl_strerror )
153
162
#ifdef HAVE_GETPRIORITY
154
163
PHP_FE (pcntl_getpriority , arginfo_pcntl_getpriority )
155
164
#endif
@@ -407,6 +416,73 @@ void php_register_signal_constants(INIT_FUNC_ARGS)
407
416
/* }}} */
408
417
}
409
418
419
+ static void php_pcntl_register_errno_constants (INIT_FUNC_ARGS )
420
+ {
421
+ #ifdef EINTR
422
+ REGISTER_PCNTL_ERRNO_CONSTANT (EINTR );
423
+ #endif
424
+ #ifdef ECHILD
425
+ REGISTER_PCNTL_ERRNO_CONSTANT (ECHILD );
426
+ #endif
427
+ #ifdef EINVAL
428
+ REGISTER_PCNTL_ERRNO_CONSTANT (EINVAL );
429
+ #endif
430
+ #ifdef EAGAIN
431
+ REGISTER_PCNTL_ERRNO_CONSTANT (EAGAIN );
432
+ #endif
433
+ #ifdef ESRCH
434
+ REGISTER_PCNTL_ERRNO_CONSTANT (ESRCH );
435
+ #endif
436
+ #ifdef EACCES
437
+ REGISTER_PCNTL_ERRNO_CONSTANT (EACCES );
438
+ #endif
439
+ #ifdef EPERM
440
+ REGISTER_PCNTL_ERRNO_CONSTANT (EPERM );
441
+ #endif
442
+ #ifdef ENOMEM
443
+ REGISTER_PCNTL_ERRNO_CONSTANT (ENOMEM );
444
+ #endif
445
+ #ifdef E2BIG
446
+ REGISTER_PCNTL_ERRNO_CONSTANT (E2BIG );
447
+ #endif
448
+ #ifdef EFAULT
449
+ REGISTER_PCNTL_ERRNO_CONSTANT (EFAULT );
450
+ #endif
451
+ #ifdef EIO
452
+ REGISTER_PCNTL_ERRNO_CONSTANT (EIO );
453
+ #endif
454
+ #ifdef EISDIR
455
+ REGISTER_PCNTL_ERRNO_CONSTANT (EISDIR );
456
+ #endif
457
+ #ifdef ELIBBAD
458
+ REGISTER_PCNTL_ERRNO_CONSTANT (ELIBBAD );
459
+ #endif
460
+ #ifdef ELOOP
461
+ REGISTER_PCNTL_ERRNO_CONSTANT (ELOOP );
462
+ #endif
463
+ #ifdef EMFILE
464
+ REGISTER_PCNTL_ERRNO_CONSTANT (EMFILE );
465
+ #endif
466
+ #ifdef ENAMETOOLONG
467
+ REGISTER_PCNTL_ERRNO_CONSTANT (ENAMETOOLONG );
468
+ #endif
469
+ #ifdef ENFILE
470
+ REGISTER_PCNTL_ERRNO_CONSTANT (ENFILE );
471
+ #endif
472
+ #ifdef ENOENT
473
+ REGISTER_PCNTL_ERRNO_CONSTANT (ENOENT );
474
+ #endif
475
+ #ifdef ENOEXEC
476
+ REGISTER_PCNTL_ERRNO_CONSTANT (ENOEXEC );
477
+ #endif
478
+ #ifdef ENOTDIR
479
+ REGISTER_PCNTL_ERRNO_CONSTANT (ENOTDIR );
480
+ #endif
481
+ #ifdef ETXTBSY
482
+ REGISTER_PCNTL_ERRNO_CONSTANT (ETXTBSY );
483
+ #endif
484
+ }
485
+
410
486
static PHP_GINIT_FUNCTION (pcntl )
411
487
{
412
488
memset (pcntl_globals , 0 , sizeof (* pcntl_globals ));
@@ -422,6 +498,7 @@ PHP_RINIT_FUNCTION(pcntl)
422
498
PHP_MINIT_FUNCTION (pcntl )
423
499
{
424
500
php_register_signal_constants (INIT_FUNC_ARGS_PASSTHRU );
501
+ php_pcntl_register_errno_constants (INIT_FUNC_ARGS_PASSTHRU );
425
502
php_add_tick_function (pcntl_signal_dispatch );
426
503
427
504
return SUCCESS ;
@@ -467,6 +544,7 @@ PHP_FUNCTION(pcntl_fork)
467
544
468
545
id = fork ();
469
546
if (id == -1 ) {
547
+ PCNTL_G (last_error ) = errno ;
470
548
php_error_docref (NULL TSRMLS_CC , E_WARNING , "Error %d" , errno );
471
549
}
472
550
@@ -505,6 +583,10 @@ PHP_FUNCTION(pcntl_waitpid)
505
583
506
584
child_id = waitpid ((pid_t ) pid , & status , options );
507
585
586
+ if (child_id < 0 ) {
587
+ PCNTL_G (last_error ) = errno ;
588
+ }
589
+
508
590
Z_LVAL_P (z_status ) = status ;
509
591
510
592
RETURN_LONG ((long ) child_id );
@@ -536,6 +618,10 @@ PHP_FUNCTION(pcntl_wait)
536
618
#else
537
619
child_id = wait (& status );
538
620
#endif
621
+ if (child_id < 0 ) {
622
+ PCNTL_G (last_error ) = errno ;
623
+ }
624
+
539
625
Z_LVAL_P (z_status ) = status ;
540
626
541
627
RETURN_LONG ((long ) child_id );
@@ -729,6 +815,7 @@ PHP_FUNCTION(pcntl_exec)
729
815
* (pair ) = NULL ;
730
816
731
817
if (execve (path , argv , envp ) == -1 ) {
818
+ PCNTL_G (last_error ) = errno ;
732
819
php_error_docref (NULL TSRMLS_CC , E_WARNING , "Error has occured: (errno %d) %s" , errno , strerror (errno ));
733
820
}
734
821
@@ -738,6 +825,7 @@ PHP_FUNCTION(pcntl_exec)
738
825
} else {
739
826
740
827
if (execv (path , argv ) == -1 ) {
828
+ PCNTL_G (last_error ) = errno ;
741
829
php_error_docref (NULL TSRMLS_CC , E_WARNING , "Error has occured: (errno %d) %s" , errno , strerror (errno ));
742
830
}
743
831
}
@@ -780,13 +868,15 @@ PHP_FUNCTION(pcntl_signal)
780
868
php_error_docref (NULL TSRMLS_CC , E_WARNING , "Invalid value for handle argument specified" );
781
869
}
782
870
if (php_signal (signo , (Sigfunc * ) Z_LVAL_P (handle ), (int ) restart_syscalls ) == SIG_ERR ) {
871
+ PCNTL_G (last_error ) = errno ;
783
872
php_error_docref (NULL TSRMLS_CC , E_WARNING , "Error assigning signal ");
784
873
RETURN_FALSE ;
785
874
}
786
875
RETURN_TRUE ;
787
876
}
788
877
789
878
if (!zend_is_callable (handle , 0 , & func_name TSRMLS_CC )) {
879
+ PCNTL_G (last_error ) = EINVAL ;
790
880
php_error_docref (NULL TSRMLS_CC , E_WARNING , "%s is not a callable function name error" , func_name );
791
881
efree (func_name );
792
882
RETURN_FALSE ;
@@ -798,6 +888,7 @@ PHP_FUNCTION(pcntl_signal)
798
888
if (dest_handle ) zval_add_ref (dest_handle );
799
889
800
890
if (php_signal (signo , pcntl_signal_handler , (int ) restart_syscalls ) == SIG_ERR ) {
891
+ PCNTL_G (last_error ) = errno ;
801
892
php_error_docref (NULL TSRMLS_CC , E_WARNING , "Error assigning signal ");
802
893
RETURN_FALSE ;
803
894
}
@@ -829,6 +920,7 @@ PHP_FUNCTION(pcntl_sigprocmask)
829
920
}
830
921
831
922
if (sigemptyset (& set ) != 0 || sigemptyset (& oldset ) != 0 ) {
923
+ PCNTL_G (last_error ) = errno ;
832
924
php_error_docref (NULL TSRMLS_CC , E_WARNING , "%s ", strerror (errno ));
833
925
RETURN_FALSE ;
834
926
}
@@ -842,13 +934,15 @@ PHP_FUNCTION(pcntl_sigprocmask)
842
934
}
843
935
signo = Z_LVAL_PP (user_signo );
844
936
if (sigaddset (& set , signo ) != 0 ) {
937
+ PCNTL_G (last_error ) = errno ;
845
938
php_error_docref (NULL TSRMLS_CC , E_WARNING , "%s ", strerror (errno ));
846
939
RETURN_FALSE ;
847
940
}
848
941
zend_hash_move_forward_ex (Z_ARRVAL_P (user_set ), & pos );
849
942
}
850
943
851
944
if (sigprocmask (how , & set , & oldset ) != 0 ) {
945
+ PCNTL_G (last_error ) = errno ;
852
946
php_error_docref (NULL TSRMLS_CC , E_WARNING , "%s ", strerror (errno ));
853
947
RETURN_FALSE ;
854
948
}
@@ -895,6 +989,7 @@ static void pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAMETERS, int timedwait) /* {{
895
989
}
896
990
897
991
if (sigemptyset (& set ) != 0 ) {
992
+ PCNTL_G (last_error ) = errno ;
898
993
php_error_docref (NULL TSRMLS_CC , E_WARNING , "%s ", strerror (errno ));
899
994
RETURN_FALSE ;
900
995
}
@@ -908,6 +1003,7 @@ static void pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAMETERS, int timedwait) /* {{
908
1003
}
909
1004
signo = Z_LVAL_PP (user_signo );
910
1005
if (sigaddset (& set , signo ) != 0 ) {
1006
+ PCNTL_G (last_error ) = errno ;
911
1007
php_error_docref (NULL TSRMLS_CC , E_WARNING , "%s ", strerror (errno ));
912
1008
RETURN_FALSE ;
913
1009
}
@@ -922,6 +1018,7 @@ static void pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAMETERS, int timedwait) /* {{
922
1018
signo = sigwaitinfo (& set , & siginfo );
923
1019
}
924
1020
if (signo == -1 && errno != EAGAIN ) {
1021
+ PCNTL_G (last_error ) = errno ;
925
1022
php_error_docref (NULL TSRMLS_CC , E_WARNING , "%s ", strerror (errno ));
926
1023
}
927
1024
@@ -1015,6 +1112,7 @@ PHP_FUNCTION(pcntl_getpriority)
1015
1112
pri = getpriority (who , pid );
1016
1113
1017
1114
if (errno ) {
1115
+ PCNTL_G (last_error ) = errno ;
1018
1116
switch (errno ) {
1019
1117
case ESRCH :
1020
1118
php_error_docref (NULL TSRMLS_CC , E_WARNING , "Error %d: No process was located using the given parameters" , errno );
@@ -1048,6 +1146,7 @@ PHP_FUNCTION(pcntl_setpriority)
1048
1146
}
1049
1147
1050
1148
if (setpriority (who , pid , pri )) {
1149
+ PCNTL_G (last_error ) = errno ;
1051
1150
switch (errno ) {
1052
1151
case ESRCH :
1053
1152
php_error_docref (NULL TSRMLS_CC , E_WARNING , "Error %d: No process was located using the given parameters" , errno );
@@ -1073,6 +1172,28 @@ PHP_FUNCTION(pcntl_setpriority)
1073
1172
/* }}} */
1074
1173
#endif
1075
1174
1175
+ /* {{{ proto int pcntl_get_last_error(void)
1176
+ Retrieve the error number set by the last pcntl function which failed. */
1177
+ PHP_FUNCTION (pcntl_get_last_error )
1178
+ {
1179
+ RETURN_LONG (PCNTL_G (last_error ));
1180
+ }
1181
+ /* }}} */
1182
+
1183
+ /* {{{ proto string pcntl_strerror(int errno)
1184
+ Retrieve the system error message associated with the given errno. */
1185
+ PHP_FUNCTION (pcntl_strerror )
1186
+ {
1187
+ long error ;
1188
+
1189
+ if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "l" , & error ) == FAILURE ) {
1190
+ RETURN_FALSE ;
1191
+ }
1192
+
1193
+ RETURN_STRING (strerror (error ), 1 );
1194
+ }
1195
+ /* }}} */
1196
+
1076
1197
/* Our custom signal handler that calls the appropriate php_function */
1077
1198
static void pcntl_signal_handler (int signo )
1078
1199
{
0 commit comments