posix.c 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Copyright (c) The PHP Group |
  4. +----------------------------------------------------------------------+
  5. | This source file is subject to version 3.01 of the PHP license, |
  6. | that is bundled with this package in the file LICENSE, and is |
  7. | available through the world-wide-web at the following url: |
  8. | https://www.php.net/license/3_01.txt |
  9. | If you did not receive a copy of the PHP license and are unable to |
  10. | obtain it through the world-wide-web, please send a note to |
  11. | license@php.net so we can mail you a copy immediately. |
  12. +----------------------------------------------------------------------+
  13. | Author: Kristian Koehntopp <kris@koehntopp.de> |
  14. +----------------------------------------------------------------------+
  15. */
  16. #ifdef HAVE_CONFIG_H
  17. #include "config.h"
  18. #endif
  19. #include "php.h"
  20. #include <unistd.h>
  21. #include "ext/standard/info.h"
  22. #include "ext/standard/php_string.h"
  23. #include "php_posix.h"
  24. #include "posix_arginfo.h"
  25. #ifdef HAVE_POSIX
  26. #ifdef HAVE_SYS_TIME_H
  27. #include <sys/time.h>
  28. #endif
  29. #include <sys/resource.h>
  30. #include <sys/utsname.h>
  31. #include <sys/types.h>
  32. #include <sys/stat.h>
  33. #include <signal.h>
  34. #include <sys/times.h>
  35. #include <errno.h>
  36. #include <grp.h>
  37. #include <pwd.h>
  38. #ifdef HAVE_SYS_MKDEV_H
  39. # include <sys/mkdev.h>
  40. #endif
  41. #ifdef HAVE_SYS_SYSMACROS_H
  42. # include <sys/sysmacros.h>
  43. #endif
  44. ZEND_DECLARE_MODULE_GLOBALS(posix)
  45. static PHP_MINFO_FUNCTION(posix);
  46. /* {{{ PHP_MINFO_FUNCTION */
  47. static PHP_MINFO_FUNCTION(posix)
  48. {
  49. php_info_print_table_start();
  50. php_info_print_table_row(2, "POSIX support", "enabled");
  51. php_info_print_table_end();
  52. }
  53. /* }}} */
  54. static PHP_GINIT_FUNCTION(posix) /* {{{ */
  55. {
  56. #if defined(COMPILE_DL_POSIX) && defined(ZTS)
  57. ZEND_TSRMLS_CACHE_UPDATE();
  58. #endif
  59. posix_globals->last_error = 0;
  60. }
  61. /* }}} */
  62. /* {{{ PHP_MINIT_FUNCTION(posix) */
  63. static PHP_MINIT_FUNCTION(posix)
  64. {
  65. REGISTER_LONG_CONSTANT("POSIX_F_OK", F_OK, CONST_CS | CONST_PERSISTENT);
  66. REGISTER_LONG_CONSTANT("POSIX_X_OK", X_OK, CONST_CS | CONST_PERSISTENT);
  67. REGISTER_LONG_CONSTANT("POSIX_W_OK", W_OK, CONST_CS | CONST_PERSISTENT);
  68. REGISTER_LONG_CONSTANT("POSIX_R_OK", R_OK, CONST_CS | CONST_PERSISTENT);
  69. #ifdef S_IFREG
  70. REGISTER_LONG_CONSTANT("POSIX_S_IFREG", S_IFREG, CONST_CS | CONST_PERSISTENT);
  71. #endif
  72. #ifdef S_IFCHR
  73. REGISTER_LONG_CONSTANT("POSIX_S_IFCHR", S_IFCHR, CONST_CS | CONST_PERSISTENT);
  74. #endif
  75. #ifdef S_IFBLK
  76. REGISTER_LONG_CONSTANT("POSIX_S_IFBLK", S_IFBLK, CONST_CS | CONST_PERSISTENT);
  77. #endif
  78. #ifdef S_IFIFO
  79. REGISTER_LONG_CONSTANT("POSIX_S_IFIFO", S_IFIFO, CONST_CS | CONST_PERSISTENT);
  80. #endif
  81. #ifdef S_IFSOCK
  82. REGISTER_LONG_CONSTANT("POSIX_S_IFSOCK", S_IFSOCK, CONST_CS | CONST_PERSISTENT);
  83. #endif
  84. #ifdef RLIMIT_AS
  85. REGISTER_LONG_CONSTANT("POSIX_RLIMIT_AS", RLIMIT_AS, CONST_CS | CONST_PERSISTENT);
  86. #endif
  87. #ifdef RLIMIT_CORE
  88. REGISTER_LONG_CONSTANT("POSIX_RLIMIT_CORE", RLIMIT_CORE, CONST_CS | CONST_PERSISTENT);
  89. #endif
  90. #ifdef RLIMIT_CPU
  91. REGISTER_LONG_CONSTANT("POSIX_RLIMIT_CPU", RLIMIT_CPU, CONST_CS | CONST_PERSISTENT);
  92. #endif
  93. #ifdef RLIMIT_DATA
  94. REGISTER_LONG_CONSTANT("POSIX_RLIMIT_DATA", RLIMIT_DATA, CONST_CS | CONST_PERSISTENT);
  95. #endif
  96. #ifdef RLIMIT_FSIZE
  97. REGISTER_LONG_CONSTANT("POSIX_RLIMIT_FSIZE", RLIMIT_FSIZE, CONST_CS | CONST_PERSISTENT);
  98. #endif
  99. #ifdef RLIMIT_LOCKS
  100. REGISTER_LONG_CONSTANT("POSIX_RLIMIT_LOCKS", RLIMIT_LOCKS, CONST_CS | CONST_PERSISTENT);
  101. #endif
  102. #ifdef RLIMIT_MEMLOCK
  103. REGISTER_LONG_CONSTANT("POSIX_RLIMIT_MEMLOCK", RLIMIT_MEMLOCK, CONST_CS | CONST_PERSISTENT);
  104. #endif
  105. #ifdef RLIMIT_MSGQUEUE
  106. REGISTER_LONG_CONSTANT("POSIX_RLIMIT_MSGQUEUE", RLIMIT_MSGQUEUE, CONST_CS | CONST_PERSISTENT);
  107. #endif
  108. #ifdef RLIMIT_NICE
  109. REGISTER_LONG_CONSTANT("POSIX_RLIMIT_NICE", RLIMIT_NICE, CONST_CS | CONST_PERSISTENT);
  110. #endif
  111. #ifdef RLIMIT_NOFILE
  112. REGISTER_LONG_CONSTANT("POSIX_RLIMIT_NOFILE", RLIMIT_NOFILE, CONST_CS | CONST_PERSISTENT);
  113. #endif
  114. #ifdef RLIMIT_NPROC
  115. REGISTER_LONG_CONSTANT("POSIX_RLIMIT_NPROC", RLIMIT_NPROC, CONST_CS | CONST_PERSISTENT);
  116. #endif
  117. #ifdef RLIMIT_RSS
  118. REGISTER_LONG_CONSTANT("POSIX_RLIMIT_RSS", RLIMIT_RSS, CONST_CS | CONST_PERSISTENT);
  119. #endif
  120. #ifdef RLIMIT_RTPRIO
  121. REGISTER_LONG_CONSTANT("POSIX_RLIMIT_RTPRIO", RLIMIT_RTPRIO, CONST_CS | CONST_PERSISTENT);
  122. #endif
  123. #ifdef RLIMIT_RTTIME
  124. REGISTER_LONG_CONSTANT("POSIX_RLIMIT_RTTIME", RLIMIT_RTTIME, CONST_CS | CONST_PERSISTENT);
  125. #endif
  126. #ifdef RLIMIT_SIGPENDING
  127. REGISTER_LONG_CONSTANT("POSIX_RLIMIT_SIGPENDING", RLIMIT_SIGPENDING, CONST_CS | CONST_PERSISTENT);
  128. #endif
  129. #ifdef RLIMIT_STACK
  130. REGISTER_LONG_CONSTANT("POSIX_RLIMIT_STACK", RLIMIT_STACK, CONST_CS | CONST_PERSISTENT);
  131. #endif
  132. #ifdef RLIMIT_KQUEUES
  133. REGISTER_LONG_CONSTANT("POSIX_RLIMIT_KQUEUES", RLIMIT_KQUEUES, CONST_CS | CONST_PERSISTENT);
  134. #endif
  135. #ifdef RLIMIT_NPTS
  136. REGISTER_LONG_CONSTANT("POSIX_RLIMIT_NPTS", RLIMIT_NPTS, CONST_CS | CONST_PERSISTENT);
  137. #endif
  138. #ifdef HAVE_SETRLIMIT
  139. REGISTER_LONG_CONSTANT("POSIX_RLIMIT_INFINITY", RLIM_INFINITY, CONST_CS | CONST_PERSISTENT);
  140. #endif
  141. return SUCCESS;
  142. }
  143. /* }}} */
  144. /* {{{ posix_module_entry */
  145. zend_module_entry posix_module_entry = {
  146. STANDARD_MODULE_HEADER,
  147. "posix",
  148. ext_functions,
  149. PHP_MINIT(posix),
  150. NULL,
  151. NULL,
  152. NULL,
  153. PHP_MINFO(posix),
  154. PHP_POSIX_VERSION,
  155. PHP_MODULE_GLOBALS(posix),
  156. PHP_GINIT(posix),
  157. NULL,
  158. NULL,
  159. STANDARD_MODULE_PROPERTIES_EX
  160. };
  161. /* }}} */
  162. #ifdef COMPILE_DL_POSIX
  163. #ifdef ZTS
  164. ZEND_TSRMLS_CACHE_DEFINE()
  165. #endif
  166. ZEND_GET_MODULE(posix)
  167. #endif
  168. #define PHP_POSIX_RETURN_LONG_FUNC(func_name) \
  169. ZEND_PARSE_PARAMETERS_NONE(); \
  170. RETURN_LONG(func_name());
  171. #define PHP_POSIX_SINGLE_ARG_FUNC(func_name) \
  172. zend_long val; \
  173. ZEND_PARSE_PARAMETERS_START(1, 1) \
  174. Z_PARAM_LONG(val) \
  175. ZEND_PARSE_PARAMETERS_END(); \
  176. if (func_name(val) < 0) { \
  177. POSIX_G(last_error) = errno; \
  178. RETURN_FALSE; \
  179. } \
  180. RETURN_TRUE;
  181. /* {{{ Send a signal to a process (POSIX.1, 3.3.2) */
  182. PHP_FUNCTION(posix_kill)
  183. {
  184. zend_long pid, sig;
  185. ZEND_PARSE_PARAMETERS_START(2, 2)
  186. Z_PARAM_LONG(pid)
  187. Z_PARAM_LONG(sig)
  188. ZEND_PARSE_PARAMETERS_END();
  189. if (kill(pid, sig) < 0) {
  190. POSIX_G(last_error) = errno;
  191. RETURN_FALSE;
  192. }
  193. RETURN_TRUE;
  194. }
  195. /* }}} */
  196. /* {{{ Get the current process id (POSIX.1, 4.1.1) */
  197. PHP_FUNCTION(posix_getpid)
  198. {
  199. PHP_POSIX_RETURN_LONG_FUNC(getpid);
  200. }
  201. /* }}} */
  202. /* {{{ Get the parent process id (POSIX.1, 4.1.1) */
  203. PHP_FUNCTION(posix_getppid)
  204. {
  205. PHP_POSIX_RETURN_LONG_FUNC(getppid);
  206. }
  207. /* }}} */
  208. /* {{{ Get the current user id (POSIX.1, 4.2.1) */
  209. PHP_FUNCTION(posix_getuid)
  210. {
  211. PHP_POSIX_RETURN_LONG_FUNC(getuid);
  212. }
  213. /* }}} */
  214. /* {{{ Get the current group id (POSIX.1, 4.2.1) */
  215. PHP_FUNCTION(posix_getgid)
  216. {
  217. PHP_POSIX_RETURN_LONG_FUNC(getgid);
  218. }
  219. /* }}} */
  220. /* {{{ Get the current effective user id (POSIX.1, 4.2.1) */
  221. PHP_FUNCTION(posix_geteuid)
  222. {
  223. PHP_POSIX_RETURN_LONG_FUNC(geteuid);
  224. }
  225. /* }}} */
  226. /* {{{ Get the current effective group id (POSIX.1, 4.2.1) */
  227. PHP_FUNCTION(posix_getegid)
  228. {
  229. PHP_POSIX_RETURN_LONG_FUNC(getegid);
  230. }
  231. /* }}} */
  232. /* {{{ Set user id (POSIX.1, 4.2.2) */
  233. PHP_FUNCTION(posix_setuid)
  234. {
  235. PHP_POSIX_SINGLE_ARG_FUNC(setuid);
  236. }
  237. /* }}} */
  238. /* {{{ Set group id (POSIX.1, 4.2.2) */
  239. PHP_FUNCTION(posix_setgid)
  240. {
  241. PHP_POSIX_SINGLE_ARG_FUNC(setgid);
  242. }
  243. /* }}} */
  244. /* {{{ Set effective user id */
  245. #ifdef HAVE_SETEUID
  246. PHP_FUNCTION(posix_seteuid)
  247. {
  248. PHP_POSIX_SINGLE_ARG_FUNC(seteuid);
  249. }
  250. #endif
  251. /* }}} */
  252. /* {{{ Set effective group id */
  253. #ifdef HAVE_SETEGID
  254. PHP_FUNCTION(posix_setegid)
  255. {
  256. PHP_POSIX_SINGLE_ARG_FUNC(setegid);
  257. }
  258. #endif
  259. /* }}} */
  260. /* {{{ Get supplementary group id's (POSIX.1, 4.2.3) */
  261. #ifdef HAVE_GETGROUPS
  262. PHP_FUNCTION(posix_getgroups)
  263. {
  264. gid_t *gidlist;
  265. int result;
  266. int i;
  267. ZEND_PARSE_PARAMETERS_NONE();
  268. /* MacOS may return more than NGROUPS_MAX groups.
  269. * Fetch the actual number of groups and create an appropriate allocation. */
  270. if ((result = getgroups(0, NULL)) < 0) {
  271. POSIX_G(last_error) = errno;
  272. RETURN_FALSE;
  273. }
  274. gidlist = emalloc(sizeof(gid_t) * result);
  275. if ((result = getgroups(result, gidlist)) < 0) {
  276. POSIX_G(last_error) = errno;
  277. efree(gidlist);
  278. RETURN_FALSE;
  279. }
  280. array_init(return_value);
  281. for (i=0; i<result; i++) {
  282. add_next_index_long(return_value, gidlist[i]);
  283. }
  284. efree(gidlist);
  285. }
  286. #endif
  287. /* }}} */
  288. /* {{{ Get user name (POSIX.1, 4.2.4) */
  289. #ifdef HAVE_GETLOGIN
  290. PHP_FUNCTION(posix_getlogin)
  291. {
  292. char *p;
  293. ZEND_PARSE_PARAMETERS_NONE();
  294. if (NULL == (p = getlogin())) {
  295. POSIX_G(last_error) = errno;
  296. RETURN_FALSE;
  297. }
  298. RETURN_STRING(p);
  299. }
  300. #endif
  301. /* }}} */
  302. /* {{{ Get current process group id (POSIX.1, 4.3.1) */
  303. PHP_FUNCTION(posix_getpgrp)
  304. {
  305. PHP_POSIX_RETURN_LONG_FUNC(getpgrp);
  306. }
  307. /* }}} */
  308. /* {{{ Create session and set process group id (POSIX.1, 4.3.2) */
  309. #ifdef HAVE_SETSID
  310. PHP_FUNCTION(posix_setsid)
  311. {
  312. PHP_POSIX_RETURN_LONG_FUNC(setsid);
  313. }
  314. #endif
  315. /* }}} */
  316. /* {{{ Set process group id for job control (POSIX.1, 4.3.3) */
  317. PHP_FUNCTION(posix_setpgid)
  318. {
  319. zend_long pid, pgid;
  320. ZEND_PARSE_PARAMETERS_START(2, 2)
  321. Z_PARAM_LONG(pid)
  322. Z_PARAM_LONG(pgid)
  323. ZEND_PARSE_PARAMETERS_END();
  324. if (setpgid(pid, pgid) < 0) {
  325. POSIX_G(last_error) = errno;
  326. RETURN_FALSE;
  327. }
  328. RETURN_TRUE;
  329. }
  330. /* }}} */
  331. /* {{{ Get the process group id of the specified process (This is not a POSIX function, but a SVR4ism, so we compile conditionally) */
  332. #ifdef HAVE_GETPGID
  333. PHP_FUNCTION(posix_getpgid)
  334. {
  335. zend_long val;
  336. ZEND_PARSE_PARAMETERS_START(1, 1)
  337. Z_PARAM_LONG(val)
  338. ZEND_PARSE_PARAMETERS_END();
  339. if ((val = getpgid(val)) < 0) {
  340. POSIX_G(last_error) = errno;
  341. RETURN_FALSE;
  342. }
  343. RETURN_LONG(val);
  344. }
  345. #endif
  346. /* }}} */
  347. /* {{{ Get process group id of session leader (This is not a POSIX function, but a SVR4ism, so be compile conditionally) */
  348. #ifdef HAVE_GETSID
  349. PHP_FUNCTION(posix_getsid)
  350. {
  351. zend_long val;
  352. ZEND_PARSE_PARAMETERS_START(1, 1)
  353. Z_PARAM_LONG(val)
  354. ZEND_PARSE_PARAMETERS_END();
  355. if ((val = getsid(val)) < 0) {
  356. POSIX_G(last_error) = errno;
  357. RETURN_FALSE;
  358. }
  359. RETURN_LONG(val);
  360. }
  361. #endif
  362. /* }}} */
  363. /* {{{ Get system name (POSIX.1, 4.4.1) */
  364. PHP_FUNCTION(posix_uname)
  365. {
  366. struct utsname u;
  367. ZEND_PARSE_PARAMETERS_NONE();
  368. if (uname(&u) < 0) {
  369. POSIX_G(last_error) = errno;
  370. RETURN_FALSE;
  371. }
  372. array_init(return_value);
  373. add_assoc_string(return_value, "sysname", u.sysname);
  374. add_assoc_string(return_value, "nodename", u.nodename);
  375. add_assoc_string(return_value, "release", u.release);
  376. add_assoc_string(return_value, "version", u.version);
  377. add_assoc_string(return_value, "machine", u.machine);
  378. #if defined(_GNU_SOURCE) && !defined(DARWIN) && defined(HAVE_UTSNAME_DOMAINNAME)
  379. add_assoc_string(return_value, "domainname", u.domainname);
  380. #endif
  381. }
  382. /* }}} */
  383. /* POSIX.1, 4.5.1 time() - Get System Time
  384. already covered by PHP
  385. */
  386. /* {{{ Get process times (POSIX.1, 4.5.2) */
  387. PHP_FUNCTION(posix_times)
  388. {
  389. struct tms t;
  390. clock_t ticks;
  391. ZEND_PARSE_PARAMETERS_NONE();
  392. if ((ticks = times(&t)) == -1) {
  393. POSIX_G(last_error) = errno;
  394. RETURN_FALSE;
  395. }
  396. array_init(return_value);
  397. add_assoc_long(return_value, "ticks", ticks); /* clock ticks */
  398. add_assoc_long(return_value, "utime", t.tms_utime); /* user time */
  399. add_assoc_long(return_value, "stime", t.tms_stime); /* system time */
  400. add_assoc_long(return_value, "cutime", t.tms_cutime); /* user time of children */
  401. add_assoc_long(return_value, "cstime", t.tms_cstime); /* system time of children */
  402. }
  403. /* }}} */
  404. /* POSIX.1, 4.6.1 getenv() - Environment Access
  405. already covered by PHP
  406. */
  407. /* {{{ Generate terminal path name (POSIX.1, 4.7.1) */
  408. #ifdef HAVE_CTERMID
  409. PHP_FUNCTION(posix_ctermid)
  410. {
  411. char buffer[L_ctermid];
  412. ZEND_PARSE_PARAMETERS_NONE();
  413. if (NULL == ctermid(buffer)) {
  414. /* Found no documentation how the defined behaviour is when this
  415. * function fails
  416. */
  417. POSIX_G(last_error) = errno;
  418. RETURN_FALSE;
  419. }
  420. RETURN_STRING(buffer);
  421. }
  422. #endif
  423. /* }}} */
  424. /* Checks if the provides resource is a stream and if it provides a file descriptor */
  425. static int php_posix_stream_get_fd(zval *zfp, int *fd) /* {{{ */
  426. {
  427. php_stream *stream;
  428. php_stream_from_zval_no_verify(stream, zfp);
  429. if (stream == NULL) {
  430. return 0;
  431. }
  432. if (php_stream_can_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT) == SUCCESS) {
  433. php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT, (void*)fd, 0);
  434. } else if (php_stream_can_cast(stream, PHP_STREAM_AS_FD) == SUCCESS) {
  435. php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)fd, 0);
  436. } else {
  437. php_error_docref(NULL, E_WARNING, "Could not use stream of type '%s'",
  438. stream->ops->label);
  439. return 0;
  440. }
  441. return 1;
  442. }
  443. /* }}} */
  444. /* {{{ Determine terminal device name (POSIX.1, 4.7.2) */
  445. PHP_FUNCTION(posix_ttyname)
  446. {
  447. zval *z_fd;
  448. char *p;
  449. int fd;
  450. #if defined(ZTS) && defined(HAVE_TTYNAME_R) && defined(_SC_TTY_NAME_MAX)
  451. zend_long buflen;
  452. #endif
  453. ZEND_PARSE_PARAMETERS_START(1, 1)
  454. Z_PARAM_ZVAL(z_fd)
  455. ZEND_PARSE_PARAMETERS_END();
  456. switch (Z_TYPE_P(z_fd)) {
  457. case IS_RESOURCE:
  458. if (!php_posix_stream_get_fd(z_fd, &fd)) {
  459. RETURN_FALSE;
  460. }
  461. break;
  462. default:
  463. fd = zval_get_long(z_fd);
  464. }
  465. #if defined(ZTS) && defined(HAVE_TTYNAME_R) && defined(_SC_TTY_NAME_MAX)
  466. buflen = sysconf(_SC_TTY_NAME_MAX);
  467. if (buflen < 1) {
  468. RETURN_FALSE;
  469. }
  470. p = emalloc(buflen);
  471. if (ttyname_r(fd, p, buflen)) {
  472. POSIX_G(last_error) = errno;
  473. efree(p);
  474. RETURN_FALSE;
  475. }
  476. RETURN_STRING(p);
  477. efree(p);
  478. #else
  479. if (NULL == (p = ttyname(fd))) {
  480. POSIX_G(last_error) = errno;
  481. RETURN_FALSE;
  482. }
  483. #endif
  484. RETURN_STRING(p);
  485. }
  486. /* }}} */
  487. /* {{{ Determine if filedesc is a tty (POSIX.1, 4.7.1) */
  488. PHP_FUNCTION(posix_isatty)
  489. {
  490. zval *z_fd;
  491. int fd;
  492. ZEND_PARSE_PARAMETERS_START(1, 1)
  493. Z_PARAM_ZVAL(z_fd)
  494. ZEND_PARSE_PARAMETERS_END();
  495. switch (Z_TYPE_P(z_fd)) {
  496. case IS_RESOURCE:
  497. if (!php_posix_stream_get_fd(z_fd, &fd)) {
  498. RETURN_FALSE;
  499. }
  500. break;
  501. default:
  502. fd = zval_get_long(z_fd);
  503. }
  504. if (isatty(fd)) {
  505. RETURN_TRUE;
  506. } else {
  507. RETURN_FALSE;
  508. }
  509. }
  510. /* }}} */
  511. /*
  512. POSIX.1, 4.8.1 sysconf() - TODO
  513. POSIX.1, 5.7.1 pathconf(), fpathconf() - TODO
  514. POSIX.1, 5.1.2 opendir(), readdir(), rewinddir(), closedir()
  515. POSIX.1, 5.2.1 chdir()
  516. already supported by PHP
  517. */
  518. /* {{{ Get working directory pathname (POSIX.1, 5.2.2) */
  519. PHP_FUNCTION(posix_getcwd)
  520. {
  521. char buffer[MAXPATHLEN];
  522. char *p;
  523. ZEND_PARSE_PARAMETERS_NONE();
  524. p = VCWD_GETCWD(buffer, MAXPATHLEN);
  525. if (!p) {
  526. POSIX_G(last_error) = errno;
  527. RETURN_FALSE;
  528. }
  529. RETURN_STRING(buffer);
  530. }
  531. /* }}} */
  532. /*
  533. POSIX.1, 5.3.x open(), creat(), umask()
  534. POSIX.1, 5.4.1 link()
  535. already supported by PHP.
  536. */
  537. /* {{{ Make a FIFO special file (POSIX.1, 5.4.2) */
  538. #ifdef HAVE_MKFIFO
  539. PHP_FUNCTION(posix_mkfifo)
  540. {
  541. zend_string *path;
  542. zend_long mode;
  543. int result;
  544. ZEND_PARSE_PARAMETERS_START(2, 2)
  545. Z_PARAM_PATH_STR(path)
  546. Z_PARAM_LONG(mode)
  547. ZEND_PARSE_PARAMETERS_END();
  548. if (php_check_open_basedir_ex(ZSTR_VAL(path), 0)) {
  549. RETURN_FALSE;
  550. }
  551. result = mkfifo(ZSTR_VAL(path), mode);
  552. if (result < 0) {
  553. POSIX_G(last_error) = errno;
  554. RETURN_FALSE;
  555. }
  556. RETURN_TRUE;
  557. }
  558. #endif
  559. /* }}} */
  560. /* {{{ Make a special or ordinary file (POSIX.1) */
  561. #ifdef HAVE_MKNOD
  562. PHP_FUNCTION(posix_mknod)
  563. {
  564. zend_string *path;
  565. zend_long mode;
  566. zend_long major = 0, minor = 0;
  567. int result;
  568. dev_t php_dev = 0;
  569. ZEND_PARSE_PARAMETERS_START(2, 4)
  570. Z_PARAM_PATH_STR(path)
  571. Z_PARAM_LONG(mode)
  572. Z_PARAM_OPTIONAL
  573. Z_PARAM_LONG(major)
  574. Z_PARAM_LONG(minor)
  575. ZEND_PARSE_PARAMETERS_END();
  576. if (php_check_open_basedir_ex(ZSTR_VAL(path), 0)) {
  577. RETURN_FALSE;
  578. }
  579. if ((mode & S_IFCHR) || (mode & S_IFBLK)) {
  580. if (major == 0) {
  581. zend_argument_value_error(3, "cannot be 0 for the POSIX_S_IFCHR and POSIX_S_IFBLK modes");
  582. RETURN_THROWS();
  583. } else {
  584. #if defined(HAVE_MAKEDEV) || defined(makedev)
  585. php_dev = makedev(major, minor);
  586. #else
  587. php_error_docref(NULL, E_WARNING, "Cannot create a block or character device, creating a normal file instead");
  588. #endif
  589. }
  590. }
  591. result = mknod(ZSTR_VAL(path), mode, php_dev);
  592. if (result < 0) {
  593. POSIX_G(last_error) = errno;
  594. RETURN_FALSE;
  595. }
  596. RETURN_TRUE;
  597. }
  598. #endif
  599. /* }}} */
  600. /* Takes a pointer to posix group and a pointer to an already initialized ZVAL
  601. * array container and fills the array with the posix group member data. */
  602. int php_posix_group_to_array(struct group *g, zval *array_group) /* {{{ */
  603. {
  604. zval array_members;
  605. int count;
  606. if (NULL == g)
  607. return 0;
  608. if (array_group == NULL || Z_TYPE_P(array_group) != IS_ARRAY)
  609. return 0;
  610. array_init(&array_members);
  611. add_assoc_string(array_group, "name", g->gr_name);
  612. if (g->gr_passwd) {
  613. add_assoc_string(array_group, "passwd", g->gr_passwd);
  614. } else {
  615. add_assoc_null(array_group, "passwd");
  616. }
  617. for (count = 0;; count++) {
  618. /* gr_mem entries may be misaligned on macos. */
  619. char *gr_mem;
  620. memcpy(&gr_mem, &g->gr_mem[count], sizeof(char *));
  621. if (!gr_mem) {
  622. break;
  623. }
  624. add_next_index_string(&array_members, gr_mem);
  625. }
  626. zend_hash_str_update(Z_ARRVAL_P(array_group), "members", sizeof("members")-1, &array_members);
  627. add_assoc_long(array_group, "gid", g->gr_gid);
  628. return 1;
  629. }
  630. /* }}} */
  631. /*
  632. POSIX.1, 5.5.1 unlink()
  633. POSIX.1, 5.5.2 rmdir()
  634. POSIX.1, 5.5.3 rename()
  635. POSIX.1, 5.6.x stat(), chmod(), utime() already supported by PHP.
  636. */
  637. /* {{{ Determine accessibility of a file (POSIX.1 5.6.3) */
  638. PHP_FUNCTION(posix_access)
  639. {
  640. zend_long mode = 0;
  641. size_t filename_len, ret;
  642. char *filename, *path;
  643. ZEND_PARSE_PARAMETERS_START(1, 2)
  644. Z_PARAM_PATH(filename, filename_len)
  645. Z_PARAM_OPTIONAL
  646. Z_PARAM_LONG(mode)
  647. ZEND_PARSE_PARAMETERS_END();
  648. path = expand_filepath(filename, NULL);
  649. if (!path) {
  650. POSIX_G(last_error) = EIO;
  651. RETURN_FALSE;
  652. }
  653. if (php_check_open_basedir_ex(path, 0)) {
  654. efree(path);
  655. POSIX_G(last_error) = EPERM;
  656. RETURN_FALSE;
  657. }
  658. ret = access(path, mode);
  659. efree(path);
  660. if (ret) {
  661. POSIX_G(last_error) = errno;
  662. RETURN_FALSE;
  663. }
  664. RETURN_TRUE;
  665. }
  666. /* }}} */
  667. /*
  668. POSIX.1, 6.x most I/O functions already supported by PHP.
  669. POSIX.1, 7.x tty functions, TODO
  670. POSIX.1, 8.x interactions with other C language functions
  671. POSIX.1, 9.x system database access
  672. */
  673. /* {{{ Group database access (POSIX.1, 9.2.1) */
  674. PHP_FUNCTION(posix_getgrnam)
  675. {
  676. char *name;
  677. struct group *g;
  678. size_t name_len;
  679. #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
  680. struct group gbuf;
  681. long buflen;
  682. char *buf;
  683. #endif
  684. ZEND_PARSE_PARAMETERS_START(1, 1)
  685. Z_PARAM_STRING(name, name_len)
  686. ZEND_PARSE_PARAMETERS_END();
  687. #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
  688. buflen = sysconf(_SC_GETGR_R_SIZE_MAX);
  689. if (buflen < 1) {
  690. RETURN_FALSE;
  691. }
  692. buf = emalloc(buflen);
  693. try_again:
  694. g = &gbuf;
  695. if (getgrnam_r(name, g, buf, buflen, &g) || g == NULL) {
  696. if (errno == ERANGE) {
  697. buflen *= 2;
  698. buf = erealloc(buf, buflen);
  699. goto try_again;
  700. }
  701. POSIX_G(last_error) = errno;
  702. efree(buf);
  703. RETURN_FALSE;
  704. }
  705. #else
  706. if (NULL == (g = getgrnam(name))) {
  707. POSIX_G(last_error) = errno;
  708. RETURN_FALSE;
  709. }
  710. #endif
  711. array_init(return_value);
  712. if (!php_posix_group_to_array(g, return_value)) {
  713. zend_array_destroy(Z_ARR_P(return_value));
  714. php_error_docref(NULL, E_WARNING, "Unable to convert posix group to array");
  715. RETVAL_FALSE;
  716. }
  717. #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
  718. efree(buf);
  719. #endif
  720. }
  721. /* }}} */
  722. /* {{{ Group database access (POSIX.1, 9.2.1) */
  723. PHP_FUNCTION(posix_getgrgid)
  724. {
  725. zend_long gid;
  726. #if defined(ZTS) && defined(HAVE_GETGRGID_R) && defined(_SC_GETGR_R_SIZE_MAX)
  727. int ret;
  728. struct group _g;
  729. struct group *retgrptr = NULL;
  730. long grbuflen;
  731. char *grbuf;
  732. #endif
  733. struct group *g;
  734. ZEND_PARSE_PARAMETERS_START(1, 1)
  735. Z_PARAM_LONG(gid)
  736. ZEND_PARSE_PARAMETERS_END();
  737. #if defined(ZTS) && defined(HAVE_GETGRGID_R) && defined(_SC_GETGR_R_SIZE_MAX)
  738. grbuflen = sysconf(_SC_GETGR_R_SIZE_MAX);
  739. if (grbuflen < 1) {
  740. RETURN_FALSE;
  741. }
  742. grbuf = emalloc(grbuflen);
  743. try_again:
  744. ret = getgrgid_r(gid, &_g, grbuf, grbuflen, &retgrptr);
  745. if (ret || retgrptr == NULL) {
  746. if (errno == ERANGE) {
  747. grbuflen *= 2;
  748. grbuf = erealloc(grbuf, grbuflen);
  749. goto try_again;
  750. }
  751. POSIX_G(last_error) = ret;
  752. efree(grbuf);
  753. RETURN_FALSE;
  754. }
  755. g = &_g;
  756. #else
  757. if (NULL == (g = getgrgid(gid))) {
  758. POSIX_G(last_error) = errno;
  759. RETURN_FALSE;
  760. }
  761. #endif
  762. array_init(return_value);
  763. if (!php_posix_group_to_array(g, return_value)) {
  764. zend_array_destroy(Z_ARR_P(return_value));
  765. php_error_docref(NULL, E_WARNING, "Unable to convert posix group struct to array");
  766. RETVAL_FALSE;
  767. }
  768. #if defined(ZTS) && defined(HAVE_GETGRGID_R) && defined(_SC_GETGR_R_SIZE_MAX)
  769. efree(grbuf);
  770. #endif
  771. }
  772. /* }}} */
  773. int php_posix_passwd_to_array(struct passwd *pw, zval *return_value) /* {{{ */
  774. {
  775. if (NULL == pw)
  776. return 0;
  777. if (NULL == return_value || Z_TYPE_P(return_value) != IS_ARRAY)
  778. return 0;
  779. add_assoc_string(return_value, "name", pw->pw_name);
  780. add_assoc_string(return_value, "passwd", pw->pw_passwd);
  781. add_assoc_long (return_value, "uid", pw->pw_uid);
  782. add_assoc_long (return_value, "gid", pw->pw_gid);
  783. add_assoc_string(return_value, "gecos", pw->pw_gecos);
  784. add_assoc_string(return_value, "dir", pw->pw_dir);
  785. add_assoc_string(return_value, "shell", pw->pw_shell);
  786. return 1;
  787. }
  788. /* }}} */
  789. /* {{{ User database access (POSIX.1, 9.2.2) */
  790. PHP_FUNCTION(posix_getpwnam)
  791. {
  792. struct passwd *pw;
  793. char *name;
  794. size_t name_len;
  795. #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
  796. struct passwd pwbuf;
  797. long buflen;
  798. char *buf;
  799. #endif
  800. ZEND_PARSE_PARAMETERS_START(1, 1)
  801. Z_PARAM_STRING(name, name_len)
  802. ZEND_PARSE_PARAMETERS_END();
  803. #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
  804. buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
  805. if (buflen < 1) {
  806. RETURN_FALSE;
  807. }
  808. buf = emalloc(buflen);
  809. pw = &pwbuf;
  810. try_again:
  811. if (getpwnam_r(name, pw, buf, buflen, &pw) || pw == NULL) {
  812. if (errno == ERANGE) {
  813. buflen *= 2;
  814. buf = erealloc(buf, buflen);
  815. goto try_again;
  816. }
  817. efree(buf);
  818. POSIX_G(last_error) = errno;
  819. RETURN_FALSE;
  820. }
  821. #else
  822. if (NULL == (pw = getpwnam(name))) {
  823. POSIX_G(last_error) = errno;
  824. RETURN_FALSE;
  825. }
  826. #endif
  827. array_init(return_value);
  828. if (!php_posix_passwd_to_array(pw, return_value)) {
  829. zend_array_destroy(Z_ARR_P(return_value));
  830. php_error_docref(NULL, E_WARNING, "Unable to convert posix passwd struct to array");
  831. RETVAL_FALSE;
  832. }
  833. #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
  834. efree(buf);
  835. #endif
  836. }
  837. /* }}} */
  838. /* {{{ User database access (POSIX.1, 9.2.2) */
  839. PHP_FUNCTION(posix_getpwuid)
  840. {
  841. zend_long uid;
  842. #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R)
  843. struct passwd _pw;
  844. struct passwd *retpwptr = NULL;
  845. long pwbuflen;
  846. char *pwbuf;
  847. int ret;
  848. #endif
  849. struct passwd *pw;
  850. ZEND_PARSE_PARAMETERS_START(1, 1)
  851. Z_PARAM_LONG(uid)
  852. ZEND_PARSE_PARAMETERS_END();
  853. #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R)
  854. pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
  855. if (pwbuflen < 1) {
  856. RETURN_FALSE;
  857. }
  858. pwbuf = emalloc(pwbuflen);
  859. try_again:
  860. ret = getpwuid_r(uid, &_pw, pwbuf, pwbuflen, &retpwptr);
  861. if (ret || retpwptr == NULL) {
  862. if (errno == ERANGE) {
  863. pwbuflen *= 2;
  864. pwbuf = erealloc(pwbuf, pwbuflen);
  865. goto try_again;
  866. }
  867. POSIX_G(last_error) = ret;
  868. efree(pwbuf);
  869. RETURN_FALSE;
  870. }
  871. pw = &_pw;
  872. #else
  873. if (NULL == (pw = getpwuid(uid))) {
  874. POSIX_G(last_error) = errno;
  875. RETURN_FALSE;
  876. }
  877. #endif
  878. array_init(return_value);
  879. if (!php_posix_passwd_to_array(pw, return_value)) {
  880. zend_array_destroy(Z_ARR_P(return_value));
  881. php_error_docref(NULL, E_WARNING, "Unable to convert posix passwd struct to array");
  882. RETVAL_FALSE;
  883. }
  884. #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R)
  885. efree(pwbuf);
  886. #endif
  887. }
  888. /* }}} */
  889. #ifdef HAVE_GETRLIMIT
  890. #define UNLIMITED_STRING "unlimited"
  891. /* {{{ posix_addlimit */
  892. static int posix_addlimit(int limit, const char *name, zval *return_value) {
  893. int result;
  894. struct rlimit rl;
  895. char hard[80];
  896. char soft[80];
  897. snprintf(hard, 80, "hard %s", name);
  898. snprintf(soft, 80, "soft %s", name);
  899. result = getrlimit(limit, &rl);
  900. if (result < 0) {
  901. POSIX_G(last_error) = errno;
  902. return FAILURE;
  903. }
  904. if (rl.rlim_cur == RLIM_INFINITY) {
  905. add_assoc_stringl(return_value, soft, UNLIMITED_STRING, sizeof(UNLIMITED_STRING)-1);
  906. } else {
  907. add_assoc_long(return_value, soft, rl.rlim_cur);
  908. }
  909. if (rl.rlim_max == RLIM_INFINITY) {
  910. add_assoc_stringl(return_value, hard, UNLIMITED_STRING, sizeof(UNLIMITED_STRING)-1);
  911. } else {
  912. add_assoc_long(return_value, hard, rl.rlim_max);
  913. }
  914. return SUCCESS;
  915. }
  916. /* }}} */
  917. /* {{{ limits[] */
  918. static const struct limitlist {
  919. int limit;
  920. const char *name;
  921. } limits[] = {
  922. #ifdef RLIMIT_CORE
  923. { RLIMIT_CORE, "core" },
  924. #endif
  925. #ifdef RLIMIT_DATA
  926. { RLIMIT_DATA, "data" },
  927. #endif
  928. #ifdef RLIMIT_STACK
  929. { RLIMIT_STACK, "stack" },
  930. #endif
  931. #ifdef RLIMIT_VMEM
  932. { RLIMIT_VMEM, "virtualmem" },
  933. #endif
  934. #ifdef RLIMIT_AS
  935. { RLIMIT_AS, "totalmem" },
  936. #endif
  937. #ifdef RLIMIT_RSS
  938. { RLIMIT_RSS, "rss" },
  939. #endif
  940. #ifdef RLIMIT_NPROC
  941. { RLIMIT_NPROC, "maxproc" },
  942. #endif
  943. #ifdef RLIMIT_MEMLOCK
  944. { RLIMIT_MEMLOCK, "memlock" },
  945. #endif
  946. #ifdef RLIMIT_CPU
  947. { RLIMIT_CPU, "cpu" },
  948. #endif
  949. #ifdef RLIMIT_FSIZE
  950. { RLIMIT_FSIZE, "filesize" },
  951. #endif
  952. #ifdef RLIMIT_NOFILE
  953. { RLIMIT_NOFILE, "openfiles" },
  954. #endif
  955. #ifdef RLIMIT_OFILE
  956. { RLIMIT_OFILE, "openfiles" },
  957. #endif
  958. #ifdef RLIMIT_KQUEUES
  959. { RLIMIT_KQUEUES, "kqueues" },
  960. #endif
  961. #ifdef RLIMIT_NPTS
  962. { RLIMIT_NPTS, "npts" },
  963. #endif
  964. { 0, NULL }
  965. };
  966. /* }}} */
  967. /* {{{ Get system resource consumption limits (This is not a POSIX function, but a BSDism and a SVR4ism. We compile conditionally) */
  968. PHP_FUNCTION(posix_getrlimit)
  969. {
  970. const struct limitlist *l = NULL;
  971. ZEND_PARSE_PARAMETERS_NONE();
  972. array_init(return_value);
  973. for (l=limits; l->name; l++) {
  974. if (posix_addlimit(l->limit, l->name, return_value) == FAILURE) {
  975. zend_array_destroy(Z_ARR_P(return_value));
  976. RETURN_FALSE;
  977. }
  978. }
  979. }
  980. /* }}} */
  981. #endif /* HAVE_GETRLIMIT */
  982. #ifdef HAVE_SETRLIMIT
  983. /* {{{ Set system resource consumption limits (POSIX.1-2001) */
  984. PHP_FUNCTION(posix_setrlimit)
  985. {
  986. struct rlimit rl;
  987. zend_long res, cur, max;
  988. ZEND_PARSE_PARAMETERS_START(3, 3)
  989. Z_PARAM_LONG(res)
  990. Z_PARAM_LONG(cur)
  991. Z_PARAM_LONG(max)
  992. ZEND_PARSE_PARAMETERS_END();
  993. rl.rlim_cur = cur;
  994. rl.rlim_max = max;
  995. if (setrlimit(res, &rl) == -1) {
  996. POSIX_G(last_error) = errno;
  997. RETURN_FALSE;
  998. }
  999. RETURN_TRUE;
  1000. }
  1001. /* }}} */
  1002. #endif /* HAVE_SETRLIMIT */
  1003. /* {{{ Retrieve the error number set by the last posix function which failed. */
  1004. PHP_FUNCTION(posix_get_last_error)
  1005. {
  1006. ZEND_PARSE_PARAMETERS_NONE();
  1007. RETURN_LONG(POSIX_G(last_error));
  1008. }
  1009. /* }}} */
  1010. /* {{{ Retrieve the system error message associated with the given errno. */
  1011. PHP_FUNCTION(posix_strerror)
  1012. {
  1013. zend_long error;
  1014. ZEND_PARSE_PARAMETERS_START(1, 1)
  1015. Z_PARAM_LONG(error)
  1016. ZEND_PARSE_PARAMETERS_END();
  1017. RETURN_STRING(strerror(error));
  1018. }
  1019. /* }}} */
  1020. #endif
  1021. #ifdef HAVE_INITGROUPS
  1022. /* {{{ Calculate the group access list for the user specified in name. */
  1023. PHP_FUNCTION(posix_initgroups)
  1024. {
  1025. zend_long basegid;
  1026. char *name;
  1027. size_t name_len;
  1028. ZEND_PARSE_PARAMETERS_START(2, 2)
  1029. Z_PARAM_STRING(name, name_len)
  1030. Z_PARAM_LONG(basegid)
  1031. ZEND_PARSE_PARAMETERS_END();
  1032. if (name_len == 0) {
  1033. RETURN_FALSE;
  1034. }
  1035. RETURN_BOOL(!initgroups((const char *)name, basegid));
  1036. }
  1037. /* }}} */
  1038. #endif