bool HHVM_FUNCTION(pcntl_sigprocmask, int how, const Array& set, VRefParam oldset) { if (how != SIG_BLOCK && how != SIG_UNBLOCK && how != SIG_SETMASK) { goto invalid_argument; } { // Variable scope so that goto doesn't cross definitions sigset_t cset; sigset_t coldset; sigemptyset(&cset); for (ArrayIter iter(set); iter; ++iter) { auto value = iter.second().toInt64(); if (sigaddset(&cset, value) == -1) { goto invalid_argument; } } int result = pthread_sigmask(how, &cset, &coldset); if (result != 0) { return false; } Array aoldset; for (int signum = 1; signum < NSIG; ++signum) { result = sigismember(&coldset, signum); if (result == 1) { aoldset.append(signum); } else if (result == -1) { // invalid signal number break; } } oldset.assignIfRef(aoldset); return true; } invalid_argument: raise_warning("pcntl_sigprocmask(): Invalid argument"); return false; }
void HHVM_FUNCTION(passthru, const String& command, VRefParam return_var /* = null */) { ShellExecContext ctx; FILE *fp = ctx.exec(command); if (!fp) return; char buffer[1024]; while (true) { int len = read(fileno(fp), buffer, sizeof(buffer) - 1); if (len == -1 && errno == EINTR) continue; if (len <= 0) break; // break on error or EOF buffer[len] = '\0'; g_context->write(String(buffer, len, CopyString)); } int ret = ctx.exit(); if (WIFEXITED(ret)) ret = WEXITSTATUS(ret); return_var.assignIfRef(ret); }
static Variant preg_replace_callback_array_impl( const Variant& patterns_and_callbacks, const Array& subjects, int limit, VRefParam count) { Array ret = Array::Create(); auto key = 0; auto total_replacement_count = 0; for (ArrayIter s_iter(subjects); s_iter; ++s_iter) { assert(s_iter.second().isString()); auto subj = s_iter.second(); for (ArrayIter pc_iter(patterns_and_callbacks.toArray()); pc_iter; ++pc_iter) { Variant pattern(pc_iter.first()); assert(pattern.isString()); Variant callback(pc_iter.second()); subj = HHVM_FN(preg_replace_callback)(pattern, callback, subj, limit, count); // If we got an error on the replacement, the subject will be null, // and then we will return null. if (subj.isNull()) { return init_null(); } if (count.isReferenced()) { total_replacement_count += count.toInt64(); } } ret.add(key++, subj); } // If count was passed in as an explicit reference, we will assign it to our // total replacement count; otherwise, count will just remained unassigned count.assignIfRef(total_replacement_count); // If there were no replacements (i.e., matches) return original subject(s) if (ret.empty()) { return subjects; } return ret; }
bool HHVM_FUNCTION(pcntl_sigprocmask, int how, const Array& set, VRefParam oldset) { auto const invalid_argument = [&] { raise_warning("pcntl_sigprocmask(): Invalid argument"); return false; }; if (how != SIG_BLOCK && how != SIG_UNBLOCK && how != SIG_SETMASK) { return invalid_argument(); } sigset_t cset; sigset_t coldset; sigemptyset(&cset); for (ArrayIter iter(set); iter; ++iter) { auto value = iter.second().toInt64(); if (sigaddset(&cset, value) == -1) { return invalid_argument(); } } if (pthread_sigmask(how, &cset, &coldset)) { return false; } auto aoldset = Array::Create(); for (int signum = 1; signum < NSIG; ++signum) { auto const result = sigismember(&coldset, signum); if (result == 1) { aoldset.append(signum); } else if (result == -1) { // Invalid signal number. break; } } oldset.assignIfRef(aoldset); return true; }
bool HHVM_FUNCTION(msg_send, const Resource& queue, int64_t msgtype, const Variant& message, bool serialize /* = true */, bool blocking /* = true */, VRefParam errorcode /* = null */) { auto q = cast<MessageQueue>(queue); if (!q) { raise_warning("Invalid message queue was specified"); return false; } hhvm_msgbuf *buffer = nullptr; String data; if (serialize) { data = HHVM_FN(serialize)(message); } else { data = message.toString(); } int len = data.length(); buffer = (hhvm_msgbuf *)calloc(len + sizeof(hhvm_msgbuf), 1); ScopedMem deleter(buffer); buffer->mtype = msgtype; memcpy(buffer->mtext, data.c_str(), len + 1); int result = msgsnd(q->id, buffer, len, blocking ? 0 : IPC_NOWAIT); if (result < 0) { int err = errno; raise_warning("Unable to send message: %s", folly::errnoStr(err).c_str()); errorcode.assignIfRef(err); return false; } return true; }
bool HHVM_FUNCTION(getmxrr, const String& hostname, VRefParam mxhostsRef, VRefParam weightsRef /* = null */) { IOStatusHelper io("dns_get_mx", hostname.data()); int count, qdc; unsigned short type, weight; unsigned char ans[MAXPACKET]; char buf[255 + 1]; // IETF STD 13 section 3.1; 255 bytes unsigned char *cp, *end; Array mxhosts; Array weights; SCOPE_EXIT { mxhostsRef.assignIfRef(mxhosts); weightsRef.assignIfRef(weights); }; /* Go! */ struct __res_state *res; res = ResolverInit::s_res.get()->getResolver(); if (res == NULL) { return false; } int i = res_nsearch(res, hostname.data(), C_IN, DNS_T_MX, (unsigned char*)&ans, sizeof(ans)); if (i < 0) { res_nclose(res); php_dns_free_res(res); return false; } if (i > (int)sizeof(ans)) { i = sizeof(ans); } HEADER *hp = (HEADER *)&ans; cp = (unsigned char *)&ans + HFIXEDSZ; end = (unsigned char *)&ans +i; for (qdc = ntohs((unsigned short)hp->qdcount); qdc--; cp += i + QFIXEDSZ) { if ((i = dn_skipname(cp, end)) < 0 ) { res_nclose(res); php_dns_free_res(res); return false; } } count = ntohs((unsigned short)hp->ancount); while (--count >= 0 && cp < end) { if ((i = dn_skipname(cp, end)) < 0 ) { res_nclose(res); php_dns_free_res(res); return false; } cp += i; GETSHORT(type, cp); cp += INT16SZ + INT32SZ; GETSHORT(i, cp); if (type != DNS_T_MX) { cp += i; continue; } GETSHORT(weight, cp); if ((i = dn_expand(ans, end, cp, buf, sizeof(buf)-1)) < 0) { res_nclose(res); php_dns_free_res(res); return false; } cp += i; mxhosts.append(String(buf, CopyString)); weights.append(weight); } res_nclose(res); php_dns_free_res(res); return true; }
Variant HHVM_FUNCTION(dns_get_record, const String& hostname, int type /*= -1*/, VRefParam authnsRef /* = null */, VRefParam addtlRef /* = null */) { IOStatusHelper io("dns_get_record", hostname.data(), type); if (type < 0) type = PHP_DNS_ALL; if (type & ~PHP_DNS_ALL && type != PHP_DNS_ANY) { raise_warning("Type '%d' not supported", type); return false; } unsigned char *cp = NULL, *end = NULL; int qd, an, ns = 0, ar = 0; querybuf answer; /* - We emulate an or'ed type mask by querying type by type. * (Steps 0 - NUMTYPES-1 ) * If additional info is wanted we check again with DNS_T_ANY * (step NUMTYPES / NUMTYPES+1 ) * store_results is used to skip storing the results retrieved in step * NUMTYPES+1 when results were already fetched. * - In case of PHP_DNS_ANY we use the directly fetch DNS_T_ANY. * (step NUMTYPES+1 ) */ Array ret = Array::Create(); bool first_query = true; bool store_results = true; for (int t = (type == PHP_DNS_ANY ? (PHP_DNS_NUM_TYPES + 1) : 0); t < PHP_DNS_NUM_TYPES + 2 || first_query; t++) { first_query = false; int type_to_fetch; switch (t) { case 0: type_to_fetch = type & PHP_DNS_A ? DNS_T_A : 0; break; case 1: type_to_fetch = type & PHP_DNS_NS ? DNS_T_NS : 0; break; case 2: type_to_fetch = type & PHP_DNS_CNAME ? DNS_T_CNAME : 0; break; case 3: type_to_fetch = type & PHP_DNS_SOA ? DNS_T_SOA : 0; break; case 4: type_to_fetch = type & PHP_DNS_PTR ? DNS_T_PTR : 0; break; case 5: type_to_fetch = type & PHP_DNS_HINFO ? DNS_T_HINFO : 0; break; case 6: type_to_fetch = type & PHP_DNS_MX ? DNS_T_MX : 0; break; case 7: type_to_fetch = type & PHP_DNS_TXT ? DNS_T_TXT : 0; break; case 8: type_to_fetch = type & PHP_DNS_AAAA ? DNS_T_AAAA : 0; break; case 9: type_to_fetch = type & PHP_DNS_SRV ? DNS_T_SRV : 0; break; case 10: type_to_fetch = type & PHP_DNS_NAPTR ? DNS_T_NAPTR : 0; break; case 11: type_to_fetch = type & PHP_DNS_A6 ? DNS_T_A6 : 0; break; case PHP_DNS_NUM_TYPES: store_results = false; continue; default: case (PHP_DNS_NUM_TYPES + 1): type_to_fetch = DNS_T_ANY; break; } if (!type_to_fetch) continue; struct __res_state *res; res = ResolverInit::s_res.get()->getResolver(); if (res == NULL) { return false; } int n = res_nsearch(res, hostname.data(), C_IN, type_to_fetch, answer.qb2, sizeof answer); if (n < 0) { res_nclose(res); php_dns_free_res(res); continue; } HEADER *hp; cp = answer.qb2 + HFIXEDSZ; end = answer.qb2 + n; hp = (HEADER *)&answer; qd = ntohs(hp->qdcount); an = ntohs(hp->ancount); ns = ntohs(hp->nscount); ar = ntohs(hp->arcount); /* Skip QD entries, they're only used by dn_expand later on */ while (qd-- > 0) { n = dn_skipname(cp, end); if (n < 0) { raise_warning("Unable to parse DNS data received"); res_nclose(res); php_dns_free_res(res); return false; } cp += n + QFIXEDSZ; } /* YAY! Our real answers! */ while (an-- && cp && cp < end) { Array retval; cp = php_parserr(cp, end, &answer, type_to_fetch, store_results, retval); if (!retval.empty() && store_results) { ret.append(retval); } } res_nclose(res); php_dns_free_res(res); } Array authns; Array addtl; /* List of Authoritative Name Servers */ while (ns-- > 0 && cp && cp < end) { Array retval; cp = php_parserr(cp, end, &answer, DNS_T_ANY, true, retval); if (!retval.empty()) { authns.append(retval); } } /* Additional records associated with authoritative name servers */ while (ar-- > 0 && cp && cp < end) { Array retval; cp = php_parserr(cp, end, &answer, DNS_T_ANY, true, retval); if (!retval.empty()) { addtl.append(retval); } } authnsRef.assignIfRef(authns); addtlRef.assignIfRef(addtl); return ret; }
static bool HHVM_METHOD(Collator, sortWithSortKeys, VRefParam arr) { FETCH_COL(data, this_, false); data->clearError(); if (!arr.isArray()) { return true; } Array hash = arr.toArray(); if (hash.size() == 0) { return true; } // Preallocate sort keys buffer size_t sortKeysOffset = 0; size_t sortKeysLength = DEF_SORT_KEYS_BUF_SIZE; char* sortKeys = (char*)req::malloc(sortKeysLength); if (!sortKeys) { throw Exception("Out of memory"); } SCOPE_EXIT{ req::free(sortKeys); }; // Preallocate index buffer size_t sortIndexPos = 0; size_t sortIndexLength = DEF_SORT_KEYS_INDX_BUF_SIZE; auto sortIndex = (collator_sort_key_index_t*)req::malloc( sortIndexLength * sizeof(collator_sort_key_index_t)); if (!sortIndex) { throw Exception("Out of memory"); } SCOPE_EXIT{ req::free(sortIndex); }; // Translate input hash to sortable index auto pos_limit = hash->iter_end(); for (ssize_t pos = hash->iter_begin(); pos != pos_limit; pos = hash->iter_advance(pos)) { Variant val(hash->getValue(pos)); // Convert to UTF16 icu::UnicodeString strval; if (val.isString()) { UErrorCode error = U_ZERO_ERROR; strval = u16(val.toString(), error); if (U_FAILURE(error)) { return false; } } // Generate sort key int sortkey_len = ucol_getSortKey(data->collator(), strval.getBuffer(), strval.length(), (uint8_t*)(sortKeys + sortKeysOffset), sortKeysLength - sortKeysOffset); // Check for key buffer overflow if (sortkey_len > (sortKeysLength - sortKeysOffset)) { int32_t inc = (sortkey_len > DEF_SORT_KEYS_BUF_INCREMENT) ? sortkey_len : DEF_SORT_KEYS_BUF_INCREMENT; sortKeysLength += inc; sortKeys = (char*)req::realloc(sortKeys, sortKeysLength); if (!sortKeys) { throw Exception("Out of memory"); } sortkey_len = ucol_getSortKey(data->collator(), strval.getBuffer(), strval.length(), (uint8_t*)(sortKeys + sortKeysOffset), sortKeysLength - sortKeysOffset); assert(sortkey_len <= (sortKeysLength - sortKeysOffset)); } // Check for index buffer overflow if ((sortIndexPos + 1) > sortIndexLength) { sortIndexLength += DEF_SORT_KEYS_INDX_BUF_INCREMENT; sortIndex = (collator_sort_key_index_t*)req::realloc(sortIndex, sortIndexLength * sizeof(collator_sort_key_index_t)); if (!sortIndex) { throw Exception("Out of memory"); } } // Initially store offset into buffer, update later to deal with reallocs sortIndex[sortIndexPos].key = (char*)sortKeysOffset; sortKeysOffset += sortkey_len; sortIndex[sortIndexPos].valPos = pos; ++sortIndexPos; } // Update keys to location in realloc'd buffer for (int i = 0; i < sortIndexPos; ++i) { sortIndex[i].key = sortKeys + (ptrdiff_t)sortIndex[i].key; } zend_qsort(sortIndex, sortIndexPos, sizeof(collator_sort_key_index_t), collator_cmp_sort_keys, nullptr); Array ret = Array::Create(); for (int i = 0; i < sortIndexPos; ++i) { ret.append(hash->getValue(sortIndex[i].valPos)); } arr.assignIfRef(ret); return true; }