static void raise_ZipError(YogEnv* env, YogVal pkg, const char* msg) { SAVE_ARG(env, pkg); YogVal eZipError = YUNDEF; YogVal e = YUNDEF; YogVal s = YUNDEF; PUSH_LOCALS3(env, eZipError, e, s); if (!IS_PTR(pkg) || (BASIC_OBJ_TYPE(pkg) != TYPE_ZIP_PKG)) { YogError_raise_TypeError(env, "package type must be TYPE_ZIP_PKG"); } eZipError = PTR_AS(Package, pkg)->eZipError; if (msg != NULL) { s = YogString_from_string(env, msg); e = YogEval_call_method1(env, eZipError, "new", s); } else { e = YogEval_call_method0(env, eZipError, "new"); } YogError_raise(env, e); /* NOTREACHED */ RETURN_VOID(env); }
static void exec_get_attr(YogEnv* env, YogVal self, ID name) { SAVE_ARG(env, self); YogVal klass = YUNDEF; YogVal attr = YUNDEF; PUSH_LOCALS2(env, klass, attr); klass = YogVal_get_class(env, self); attr = YogClass_get_attr(env, klass, name); if (!IS_UNDEF(attr)) { attr = YogVal_get_descr(env, attr, self, klass); YogScriptFrame_push_stack(env, env->frame, attr); RETURN_VOID(env); } attr = YogObj_get_attr(env, self, name); if (!IS_UNDEF(attr)) { attr = YogVal_get_descr(env, attr, YNIL, self); YogScriptFrame_push_stack(env, env->frame, attr); RETURN_VOID(env); } YogError_raise_AttributeError(env, "%C object has no attribute \"%I\"", self, name); /* NOTREACHED */ RETURN_VOID(env); }
void YogVM_remove_thread(YogEnv* env, YogVM* vm, YogVal thread) { SAVE_ARG(env, thread); YogVM_acquire_global_interp_lock(env, vm); gc(env, vm); YogVal prev = PTR_AS(YogThread, thread)->prev; YogVal next = PTR_AS(YogThread, thread)->next; if (IS_PTR(prev)) { YogGC_UPDATE_PTR(env, PTR_AS(YogThread, prev), next, next); } else { vm->running_threads = next; } if (IS_PTR(next)) { YogGC_UPDATE_PTR(env, PTR_AS(YogThread, next), prev, prev); } if (!IS_PTR(vm->running_threads)) { pthread_cond_signal(&vm->vm_finish_cond); } RESTORE_LOCALS(env); YogVM_release_global_interp_lock(env, vm); }
ID YogVM_intern2(YogEnv* env, YogVM* vm, YogVal name) { SAVE_ARG(env, name); YogVal value = YUNDEF; PUSH_LOCAL(env, value); #define FIND_SYM do { \ if (YogTable_lookup(env, vm->name2id, name, &value)) { \ release_symbols_lock(env, vm); \ RETURN(env, VAL2ID(value)); \ } \ } while (0) acquire_symbols_read_lock(env, vm); FIND_SYM; release_symbols_lock(env, vm); acquire_symbols_write_lock(env, vm); FIND_SYM; #undef FIND_SYM YogHandle* clone = VAL2HDL(env, YogString_clone(env, name)); ID id = vm->next_id; YogVal symbol = ID2VAL(id); YogTable_add_direct(env, vm->name2id, HDL2VAL(clone), symbol); YogTable_add_direct(env, vm->id2name, symbol, HDL2VAL(clone)); vm->next_id++; release_symbols_lock(env, vm); RETURN(env, id); }
void YogRegexp_define_classes(YogEnv* env, YogVal pkg) { SAVE_ARG(env, pkg); YogVal cRegexp = YUNDEF; YogVal cMatch = YUNDEF; PUSH_LOCALS2(env, cRegexp, cMatch); YogVM* vm = env->vm; cRegexp = YogClass_new(env, "Regexp", vm->cObject); #define DEFINE_METHOD(name, ...) do { \ YogClass_define_method2(env, cRegexp, pkg, (name), __VA_ARGS__); \ } while (0) DEFINE_METHOD("match", match, "s", "|", "pos", NULL); DEFINE_METHOD("search", search, "s", "|", "pos", NULL); #undef DEFINE_METHOD vm->cRegexp = cRegexp; cMatch = YogClass_new(env, "Match", vm->cObject); #define DEFINE_METHOD(name, f) do { \ YogClass_define_method(env, cMatch, pkg, (name), (f)); \ } while (0) DEFINE_METHOD("start", start); DEFINE_METHOD("end", end); #undef DEFINE_METHOD #define DEFINE_METHOD2(name, ...) do { \ YogClass_define_method2(env, cMatch, pkg, (name), __VA_ARGS__); \ } while (0) DEFINE_METHOD2("group", group, "|", "group", NULL); #undef DEFINE_METHOD2 vm->cMatch = cMatch; RETURN_VOID(env); }
static void raise_invalid_group(YogEnv* env, YogVal group) { SAVE_ARG(env, group); YogError_raise_TypeError(env, "group must be a Fixnum, String or nil, not %C", group); /* NOTREACHED */ RETURN_VOID(env); }
static void close_zip(YogEnv* env, YogVal pkg, struct zip* archive) { SAVE_ARG(env, pkg); if (zip_close(archive) != 0) { raise_ZipError(env, pkg, zip_strerror(archive)); } RETURN_VOID(env); }
YogVal YogClass_alloc(YogEnv* env, YogVal klass) { SAVE_ARG(env, klass); YogVal obj = YUNDEF; PUSH_LOCAL(env, obj); obj = ALLOC_OBJ(env, YogClass_keep_children, NULL, YogClass); YogClass_init(env, obj, TYPE_CLASS, klass); RETURN(env, obj); }
static void register_encoding(YogEnv* env, YogVM* vm, const char* name, YogVal enc) { SAVE_ARG(env, enc); YogVal s = YUNDEF; PUSH_LOCAL(env, s); s = YogString_from_string(env, name); YogDict_set(env, vm->encodings, s, enc); RETURN_VOID(env); }
void YogEnumerable_define_classes(YogEnv* env, YogVal pkg) { SAVE_ARG(env, pkg); YogVal mEnumerable = YUNDEF; PUSH_LOCAL(env, mEnumerable); YogVM* vm = env->vm; mEnumerable = YogModule_of_name(env, "Enumerable"); vm->mEnumerable = mEnumerable; RETURN_VOID(env); }
YogVal YogClass_new(YogEnv* env, const char* name, YogVal super) { SAVE_ARG(env, super); YogVal obj = YUNDEF; PUSH_LOCAL(env, obj); obj = YogClass_alloc(env, env->vm->cClass); YogGC_UPDATE_PTR(env, PTR_AS(YogClass, obj), super, super); ID id = name == NULL ? INVALID_ID : YogVM_intern(env, env->vm, name); PTR_AS(YogClass, obj)->name = id; RETURN(env, obj); }
static void wait_package(YogEnv* env, YogVal pkg) { SAVE_ARG(env, pkg); pthread_cond_t* cond = &PTR_AS(ImportingPackage, pkg)->cond; pthread_mutex_t* lock = &PTR_AS(ImportingPackage, pkg)->lock; while (!IS_PTR(PTR_AS(ImportingPackage, pkg)->pkg)) { YogGC_free_from_gc(env); pthread_cond_wait(cond, lock); YogGC_bind_to_gc(env); } RETURN_VOID(env); }
void YogEncoding_define_classes(YogEnv* env, YogVal pkg) { SAVE_ARG(env, pkg); YogVal cEncoding = YUNDEF; PUSH_LOCAL(env, cEncoding); YogVM* vm = env->vm; cEncoding = YogClass_new(env, "Encoding", vm->cObject); YogClass_define_allocator(env, cEncoding, alloc); YogClass_define_method(env, cEncoding, pkg, "create_string", create_string); vm->cEncoding = cEncoding; RETURN_VOID(env); }
void YogVM_add_thread(YogEnv* env, YogVM* vm, YogVal thread) { SAVE_ARG(env, thread); YogVM_acquire_global_interp_lock(env, vm); gc(env, vm); YogGC_UPDATE_PTR(env, PTR_AS(YogThread, vm->running_threads), prev, thread); YogGC_UPDATE_PTR(env, PTR_AS(YogThread, thread), next, vm->running_threads); vm->running_threads = thread; YogVM_release_global_interp_lock(env, vm); RETURN_VOID(env); }
void YogProperty_define_classes(YogEnv* env, YogVal pkg) { SAVE_ARG(env, pkg); YogVal cProperty = YUNDEF; PUSH_LOCAL(env, cProperty); YogVM* vm = env->vm; cProperty = YogClass_new(env, "Property", vm->cObject); YogClass_define_descr_get_executor(env, cProperty, exec_get_descr); YogClass_define_descr_get_caller(env, cProperty, call_get_descr); YogClass_define_descr_set_executor(env, cProperty, exec_set_descr); vm->cProperty = cProperty; RETURN_VOID(env); }
static void setup_classes(YogEnv* env, YogVM* vm, YogVal builtins) { SAVE_ARG(env, builtins); YogProperty_define_classes(env, builtins); YogFunction_define_classes(env, builtins); YogObj_class_init(env, vm->cObject, builtins); YogClass_class_init(env, vm->cClass, builtins); YogComparable_define_classes(env, builtins); YogEnumerable_define_classes(env, builtins); YogString_define_classes(env, builtins); YogHandle* h_builtins = YogHandle_REGISTER(env, builtins); YogArray_define_classes(env, builtins); YogBignum_define_classes(env, builtins); YogBinary_define_classes(env, builtins); YogBool_define_classes(env, builtins); YogClassMethod_define_classes(env, builtins); YogCode_define_classes(env, h_builtins); YogCoroutine_define_classes(env, builtins); YogDatetime_define_classes(env, h_builtins); YogDict_define_classes(env, builtins); YogDir_define_classes(env, h_builtins); YogEncoding_define_classes(env, builtins); YogEnv_define_classes(env, h_builtins); YogFFI_define_classes(env, builtins); YogFile_define_classes(env, builtins); YogFixnum_define_classes(env, builtins); YogFloat_define_classes(env, builtins); YogModule_define_classes(env, builtins); YogNil_define_classes(env, builtins); YogPackage_define_classes(env, builtins); YogPath_define_classes(env, h_builtins); YogProcess_define_classes(env, h_builtins); YogRegexp_define_classes(env, builtins); YogSet_define_classes(env, builtins); YogStat_define_classes(env, h_builtins); YogSymbol_define_classes(env, builtins); YogThread_define_classes(env, builtins); RETURN_VOID(env); }
static YogVal call_get_attr(YogEnv* env, YogVal self, ID name) { SAVE_ARG(env, self); YogVal klass = YUNDEF; YogVal attr = YUNDEF; PUSH_LOCALS2(env, klass, attr); klass = YogVal_get_class(env, self); attr = YogClass_get_attr(env, klass, name); if (!IS_UNDEF(attr)) { attr = YogVal_get_descr(env, attr, self, klass); RETURN(env, attr); } attr = YogObj_get_attr(env, self, name); if (!IS_UNDEF(attr)) { attr = YogVal_get_descr(env, attr, YNIL, self); RETURN(env, attr); } RETURN(env, YUNDEF); }
/* Parse a string of one of the forms: * "domain[,[any][,bltype]] * "domain[,[IPaddr[&IPmask]][,bltype]] * "domain[,[IPaddr[/xx][&IPmask]][,bltype]] * "domain[,[IPaddrLO-IPaddrHI[&IPmask]][,name|ipv4|ipv6]] * where bltype is "name", "all-names", "IPv4", or "IPv6" * * set:[no-]client client IP address checks * set:[no-]mail_host envelope mail_from checks * set:[no-]URL body URL checks * set:[no-]MX MX checks * set:[no-]NS NS checks * set:white DNS whitelist * set:black DNS blacklist * set:defaults restore defaults * set:group=X start group of lists * set:debug=X more logging * set:msg-secs=S total seconds checking blacklists/message * set:url-secs=S total seconds per host name * * set:rej-msg="rejection message" * set:progpath path of helper program * set:max_helpers=X override dccm or dccifd max_work * * set:[no-]body body URL checks * set:[no-]envelope obsolete mail host and client * * set:helper=soc,fd,X start DNS resolver process */ u_char /* 0=bad */ dcc_parse_dnsbl(DCC_EMSG emsg, const char *entry, const char *progpath) { DNSBL *dp1, **dpp; const char *tgt_ip_start; char tgt_ip_buf[INET6_ADDRSTRLEN*3+10]; DNSBL_TYPE type; int dom_len, tgt_ip_len; char *p; int val; u_char seen_dp; #ifdef HAVE_HELPERS int soc; int fd; int total_helpers; # define SAVE_ARG(arg) helper_save_arg("-B", arg) #else # define SAVE_ARG(arg) #endif if (progpath && dnsbl_progpath[0] == '\0') { const char *slash = strrchr(progpath, '/'); if (slash) ++slash; else slash = progpath; snprintf(dnsbl_progpath, sizeof(dnsbl_progpath), "%.*sdns-helper", (int)(slash-progpath), progpath); } /* handle parameter settings */ if (!CLITCMP(entry, "set:")) { const char *parm = entry+LITZ("set:"); #ifdef HAVE_HELPERS /* start running a helper process on the last, magic -B */ if (3 == sscanf(parm, HELPER_PAT, &soc, &fd, &total_helpers)) { helper_child(soc, fd, total_helpers); } #endif if (!strcasecmp(parm, "client")) { parse_tgts |= DNSBL_HIT_CLIENT; SAVE_ARG(entry); return 1; } if (!strcasecmp(parm, "no-client")) { parse_tgts &= ~DNSBL_HIT_CLIENT; SAVE_ARG(entry); return 1; } if (!strcasecmp(parm, "mail_host") || !strcasecmp(parm, "mail-host")) { parse_tgts |= DNSBL_HIT_MHOST; SAVE_ARG(entry); return 1; } if (!strcasecmp(parm, "no-mail_host") || !strcasecmp(parm, "no-mail-host")) { parse_tgts &= ~DNSBL_HIT_MHOST; SAVE_ARG(entry); return 1; } if (!strcasecmp(parm, "url")) { parse_tgts |= DNSBL_HIT_URL; SAVE_ARG(entry); return 1; } if (!strcasecmp(parm, "no-URL")) { parse_tgts &= ~DNSBL_HIT_URL; SAVE_ARG(entry); return 1; } if (!strcasecmp(parm, "mx")) { #ifdef MXNS_DNSBL parse_mx_ok = 1; SAVE_ARG(entry); return 1; #else dcc_pemsg(EX_USAGE, emsg, "MX DNS blacklist checks" " not supported on "DCC_TARGET_SYS); return 0; #endif } if (!strcasecmp(parm, "no-mx")) { parse_mx_ok = 0; SAVE_ARG(entry); return 1; } if (!strcasecmp(parm, "ns")) { #ifdef MXNS_DNSBL parse_ns_ok = 1; SAVE_ARG(entry); return 1; #else dcc_pemsg(EX_USAGE, emsg, "NS DNS blacklist checks" " not supported on "DCC_TARGET_SYS); return 0; #endif } if (!strcasecmp(parm, "no-ns")) { parse_ns_ok = 0; SAVE_ARG(entry); return 1; } if (!strcasecmp(parm, "white")) { parse_tgts |= DNSBL_HIT_WHITE; SAVE_ARG(entry); return 1; } if (!strcasecmp(parm, "black")) { parse_tgts &= ~DNSBL_HIT_WHITE; SAVE_ARG(entry); return 1; } if (!strcasecmp(parm, "defaults")) { parse_tgts = DNSBL_HIT_SRCS; parse_mx_ok = 1; parse_ns_ok = 1; parse_reply = 0; SAVE_ARG(entry); return 1; } if (!CLITCMP(parm, "rej-msg=")) { parm += LITZ("rej-msg="); if (*parm == '\0') parse_reply = 0; else parse_reply = dnsbl_parse_reply(parm); /* do not save for helpers */ return 1; } if (!CLITCMP(parm, "msg-secs=")) { parm += LITZ("msg-secs="); val = strtoul(parm, &p, 10); if (*p != '\0' || val < MIN_MSG_SECS || val > MAX_MSG_SECS) { dcc_pemsg(EX_USAGE, emsg, "bad number of seconds in \"-B %s\"", entry); return 0; } if (msg_secs != val) { msg_secs = val; SAVE_ARG(entry); } return 1; } if (!CLITCMP(parm, "url-secs=")) { parm += LITZ("url-secs="); val = strtoul(parm, &p, 10); if (*p != '\0' || val < MIN_URL_SECS || val > MAX_MSG_SECS) { dcc_pemsg(EX_USAGE, emsg, "bad number of seconds in \"-B %s\"", entry); return 0; } if (url_secs != val) { url_secs = val; SAVE_ARG(entry); } return 1; } if (1 == sscanf(parm, "group=%d", &val) && val >= 1 && val <= NUM_DNSBL_GROUPS) { parse_gnum = val-1; have_dnsbl_groups = 1; SAVE_ARG(entry); return 1; } if (!strcasecmp(parm, "debug")) { ++helper.debug; SAVE_ARG(entry); return 1; } if (1 == sscanf(parm, "debug=%d", &val)) { helper.debug = val; SAVE_ARG(entry); return 1; } if (!CLITCMP(parm, "progpath=")) { BUFCPY(dnsbl_progpath, parm+LITZ("progpath=")); return 1; } if (1 == sscanf(parm, "max_helpers=%d", &val) && val >= 1 && val < 1000) { helper.max_helpers = val; SAVE_ARG(entry); return 1; } if (!strcasecmp(parm, "body")) { /* obsolete */ parse_tgts |= DNSBL_HIT_URL; SAVE_ARG(entry); return 1; } if (!strcasecmp(parm, "no-body")) { /* obsolete */ parse_tgts &= ~DNSBL_HIT_URL; SAVE_ARG(entry); return 1; } if (!strcasecmp(parm, "envelope")) { /* obsolete */ parse_tgts |= (DNSBL_HIT_CLIENT | DNSBL_HIT_MHOST); SAVE_ARG(entry); return 1; } if (!strcasecmp(parm, "no-envelope")) { /* obsolete */ parse_tgts &= ~(DNSBL_HIT_CLIENT | DNSBL_HIT_MHOST); SAVE_ARG(entry); return 1; } dcc_pemsg(EX_USAGE, emsg, "unrecognized \"-B %s\"", entry); return 0; } /* we have a DNSDBL specification instead of an option setting */ if (!parse_dp) parse_dp = dcc_malloc(sizeof(*parse_dp)); memset(parse_dp, 0, sizeof(*parse_dp)); type = DNSBL_TYPE_IPV4; /* assume it is a simple IPv4 list */ tgt_ip_start = strchr(entry, ','); if (!tgt_ip_start) { dom_len = strlen(entry); have_ipv4_dnsbl = 1; tgt_ip_len = 0; } else { dom_len = tgt_ip_start - entry; ++tgt_ip_start; /* notice trailing ",name" or ",IPv4" */ p = strchr(tgt_ip_start, ','); if (!p) { tgt_ip_len = strlen(tgt_ip_start); have_ipv4_dnsbl = 1; } else { tgt_ip_len = p - tgt_ip_start; ++p; if (!strcasecmp(p, "name")) { type = DNSBL_TYPE_NAME; have_name_dnsbl = 1; } else if (!strcasecmp(p, "all-names") || !strcasecmp(p, "all_names")) { type = DNSBL_TYPE_ALL_NAMES; have_name_dnsbl = 1; } else if (!strcasecmp(p, "IPV4")) { type = DNSBL_TYPE_IPV4; have_ipv4_dnsbl = 1; } else if (!strcasecmp(p, "IPV6")) { type = DNSBL_TYPE_IPV6; have_ipv6_dnsbl = 1; } else { dcc_pemsg(EX_NOHOST, emsg, "unknown DNSBL type in \"%s\"", entry); return 0; } } } /* assume 127.0.0.2 if the target address is missing */ if (tgt_ip_len == 0) { BUFCPY(tgt_ip_buf, "127.0.0.2"); } else { if (tgt_ip_len > ISZ(tgt_ip_buf)-1) tgt_ip_len = ISZ(tgt_ip_buf)-1; memcpy(tgt_ip_buf, tgt_ip_start, tgt_ip_len); tgt_ip_buf[tgt_ip_len] = '\0'; } if (entry[0] == '.') { ++entry; --dom_len; } if (dom_len >= ISZ(DNSBL_DOM) - INET6_ADDRSTRLEN*2) { /* we cannot fit the list and target names or address * into a DNSBL_DOM field. We need to do DNS lookups of * names like 33.22.11.10.dnsbl.example.com or * domain.dom.bl.example.com */ dcc_pemsg(EX_NOHOST, emsg, "DNSBL name \"%s\" too long", entry); return 0; } memcpy(&parse_dp->dom.c, entry, dom_len); parse_dp->dom.c[dom_len] = '\0'; if (!parse_dnsbl_addrs(emsg, entry, tgt_ip_buf)) return 0; parse_dp->type = type; parse_tgts &= ~(DNSBL_HIT_MHOST_MX | DNSBL_HIT_URL_MX | DNSBL_HIT_MHOST_NS | DNSBL_HIT_URL_NS); #ifdef MXNS_DNSBL if (parse_mx_ok) { if (parse_tgts & DNSBL_HIT_MHOST) parse_tgts |= DNSBL_HIT_MHOST_MX; if (parse_tgts & DNSBL_HIT_URL) parse_tgts |= DNSBL_HIT_URL_MX; } if (parse_ns_ok) { if (parse_tgts & DNSBL_HIT_MHOST) parse_tgts |= DNSBL_HIT_MHOST_NS; if (parse_tgts & DNSBL_HIT_URL) parse_tgts |= DNSBL_HIT_URL_NS; } #endif parse_dp->tgt_hits = parse_tgts; parse_dp->gnum = parse_gnum; if (parse_tgts & DNSBL_HIT_WHITE) group_tgt_hits.w[parse_dp->gnum] |= parse_tgts; else group_tgt_hits.b[parse_dp->gnum] |= parse_tgts; parse_dp->reply = parse_reply; parse_dp->dom_len = dom_len+1; /* count trailing '\0' */ parse_dp->num = ++parse_dnum; /* link the lists as they were declared except that * all whitelist must precede all blacklists */ for (dpp = &dnsbls; ; dpp = &dp1->fwd) { dp1 = *dpp; if (!dp1 || ((parse_tgts & DNSBL_HIT_WHITE) && !(dp1->tgt_hits & DNSBL_HIT_WHITE))) { parse_dp->fwd = dp1; *dpp = parse_dp; break; } } /* notice lists that duplicate previous lists * and so can use previous look-up results */ seen_dp = 0; for (dp1 = dnsbls; dp1; dp1 = dp1->fwd) { if (dp1 == parse_dp) { seen_dp = 1; continue; } if (parse_dp->type == dp1->type && parse_dp->tgt_use_ipv46 == dp1->tgt_use_ipv46 && parse_dp->dom_len == dp1->dom_len && parse_dp->dom_len != 0 && !memcmp(parse_dp->dom.c, dp1->dom.c, parse_dp->dom_len)) { if (seen_dp) { dp1->tgt_hits |= DNSBL_HIT_DUP; parse_dp->dup_fwd = dp1; } else { parse_dp->tgt_hits |= DNSBL_HIT_DUP; parse_dp->dup_fwd = dp1->dup_fwd; dp1->dup_fwd = parse_dp; } break; } } parse_dp = 0; SAVE_ARG(entry); return 1; #undef SAVE_ARG }