/* Set the done callback */ static void f_set_done_callback(INT32 args) { switch(args) { case 2: assign_svalue(&(THIS->args), &ARG(2)); case 1: if (Pike_sp[-args].type != T_FUNCTION) SIMPLE_BAD_ARG_ERROR("_Caudium.nbio()->set_done_callback", 1, "function"); assign_svalue(&(THIS->cb), &Pike_sp[-args]); break; case 0: free_svalue(&THIS->cb); free_svalue(&THIS->args); THIS->cb.type=T_INT; THIS->args.type=T_INT; THIS->args.u.integer = 0; return; default: Pike_error("_Caudium.nbio()->set_done_callback: Too many arguments.\n"); break; } pop_n_elems(args - 1); }
/*-------------------------------------------------------------------------*/ svalue_t * f_tls_error(svalue_t *sp) /* EFUN tls_error() * * string tls_error(int errorno) * * tls_error() returns a string describing the error behind the * error number <errorno>. */ { string_t *s; const char *text; int err = sp->u.number; text = tls_error(err); if (text) { memsafe(s = new_mstring(text), strlen(text), "tls_error()"); free_svalue(sp); put_string(sp, s); } else { free_svalue(sp); put_number(sp, 0); } return sp; } /* f_tls_error() */
/*-------------------------------------------------------------------------*/ svalue_t * f_baseof (svalue_t *sp) /* EFUN baseof() * * int baseof(struct b, struct s) * * Test if the type of struct <b> is a base of struct <s> (the values of * <b> and <s> are irrelevant). Results are: * 0: <b> is not a base of <s>, nor is <b> of equal type as <s> (though <s> * might be a base of <b>). * 1: <b> is a true base of <s> * 2: <b> and <s> are the same struct type */ { int rc; /* Get the arguments from the stack */ rc = struct_baseof(sp[-1].u.strct->type, sp[0].u.strct->type); /* Remove the arguments and push the result */ free_svalue(sp); sp--; free_svalue(sp); put_number(sp, rc); return sp; } /* f_baseof() */
/* * Check that a path to a file is valid for read or write. * This is done by functions in the master object. * The path is always treated as an absolute path, and is returned without * a leading '/'. * If the path was '/', then '.' is returned. * Otherwise, the returned path is temporarily allocated by apply(), which * means it will be deallocated at next apply(). */ const char *check_valid_path (const char * path, object_t * call_object, const char * const call_fun, int writeflg) { svalue_t *v; if(!master_ob && !call_object){ //early startup, ignore security extern svalue_t apply_ret_value; free_svalue(&apply_ret_value, "check_valid_path"); apply_ret_value.type = T_STRING; apply_ret_value.subtype = STRING_MALLOC; path = apply_ret_value.u.string = string_copy(path, "check_valid_path"); return path; } if (call_object == 0 || call_object->flags & O_DESTRUCTED) return 0; #ifdef WIN32 { char *p; for(p=path; *p; p++) if (*p == '\\') *p='/'; } #endif copy_and_push_string(path); push_object(call_object); push_constant_string(call_fun); if (writeflg) v = apply_master_ob(APPLY_VALID_WRITE, 3); else v = apply_master_ob(APPLY_VALID_READ, 3); if (v == (svalue_t *)-1) v = 0; if (v && v->type == T_NUMBER && v->u.number == 0) return 0; if (v && v->type == T_STRING) { path = v->u.string; } else { extern svalue_t apply_ret_value; free_svalue(&apply_ret_value, "check_valid_path"); apply_ret_value.type = T_STRING; apply_ret_value.subtype = STRING_MALLOC; path = apply_ret_value.u.string = string_copy(path, "check_valid_path"); } if (path[0] == '/') path++; if (path[0] == '\0') path = "."; if (legal_path(path)) return path; return 0; }
/* * Slice of an array. * It now frees the passed array */ array_t *slice_array P3(array_t *, p, int, from, int, to) { int cnt; svalue_t *sv1, *sv2; if (from < 0) from = 0; if (to >= p->size) to = p->size - 1; if (from > to) { free_array(p); return null_array(); } if (!(--p->ref)){ #ifdef PACKAGE_MUDLIB_STATS add_array_size(&p->stats, -((int)p->size)); #endif total_array_size += (to - from + 1 - p->size) * sizeof(svalue_t); if (from) { sv1 = p->item + from; cnt = from; while (cnt--) free_svalue(--sv1, "slice_array:2"); cnt = to - from + 1; sv1 = p->item; sv2 = p->item + from; while (cnt--) *sv1++ = *sv2++; } else { sv2 = p->item + to + 1; } cnt = (p->size - 1) - to; while (cnt--) free_svalue(sv2++, "slice_array:3"); p = RESIZE_ARRAY(p, to-from+1); #ifdef PACKAGE_MUDLIB_STATS if (current_object) { assign_stats(&p->stats, current_object); add_array_size(&p->stats, to - from + 1); } else null_stats(&p->stats); #endif p->size = to-from+1; p->ref = 1; return p; } else { array_t *d; d = allocate_empty_array(to - from + 1); sv1 = d->item - from; sv2 = p->item; for (cnt = from; cnt <= to; cnt++) assign_svalue_no_free(sv1 + cnt, sv2 + cnt); return d; } }
/*-------------------------------------------------------------------------*/ svalue_t * f_set_extra_wizinfo (svalue_t *sp) /* EFUN set_extra_wizinfo() * * void set_extra_wizinfo (object wiz, mixed extra) * void set_extra_wizinfo (string wiz, mixed extra) * void set_extra_wizinfo (int wiz, mixed extra) * * Set the value <extra> as the 'extra' information for the wizlist * entry of <wiz>. * * If <wiz> is an object, the entry of its creator (uid) is used. * If <wiz> is a string (a creator aka uid), it names the entry * to use. * If <wiz> is the number 0, the data is set in the default wizlist * entry. It can be used to store data for the lifetime of this * driver run, like the time of the last reboot. * * <extra> can be any value. * * The function causes a privilege violation * ("set_extra_wizinfo", this_object(), <wiz>). */ { wiz_list_t *user; short type; if ((type = sp[-1].type) == T_OBJECT) { user = sp[-1].u.ob->user; } else if (type != T_STRING || !(user = find_wiz(sp[-1].u.str))) { if (type == T_NUMBER && sp[-1].u.number == 0) user = NULL; else efun_gen_arg_error(1, sp->type, sp); } if (!privilege_violation(STR_SET_EXTRA_WIZINFO, sp-1, sp)) free_svalue(sp); else transfer_svalue(user ? &user->extra : &default_wizlist_entry.extra, sp); free_svalue(sp-1); return sp - 2; } /* f_set_extra_wizinfo() */
/*-------------------------------------------------------------------------*/ svalue_t * f_tls_query_connection_info (svalue_t *sp) /* EFUN tls_query_connection_info() * * * #include <sys/tls.h> * int *tls_query_connection_info (object ob) * * If <ob> does not have a TLS connection, or if the TLS connection is * still being set up, the efun returns 0. * * If <ob> has a TLS connection, tls_query_connection_info() returns an array * that contains some parameters of <ob>'s connection: * * int|string [TLS_CIPHER]: the cipher used * int [TLS_COMP]: the compression used * int [TLS_KX]: the key-exchange used * int [TLS_MAC]: the digest algorithm used * int|string [TLS_PROT]: the protocol used * * To translate these numbers into strings, <tls.h> offers a number of macros: * * TLS_xxx_TABLE: a literal array of strings describing the value in * question. * TLS_xxx_NAME(x): a macro translating the numeric result value into a * string. * * xxx: CIPHER, COMP, KX, MAC, PROT */ { interactive_t *ip; if (O_SET_INTERACTIVE(ip, sp->u.ob) && ip->tls_status == TLS_ACTIVE) { vector_t * rc; rc = tls_query_connection_info(ip); free_svalue(sp); put_array(sp, rc); } else { free_svalue(sp); put_number(sp, 0); } return sp; } /* tls_query_connection_info() */
/************************************************************************* * f_sql_close( int handle ) * * colses the connection with the given ID *************************************************************************/ svalue_t * f_sql_close( svalue_t * argv, int argc ) { #if ODBC_DEBUG & DEBUG_FUNC printf( "call f_sql_close( )\n" ); #endif int id; hDBC * handle; TYPE_TEST1( argv, T_NUMBER ); id = argv->u.number; if ( !(handle = get_db_connection_by_id( id )) ) { errorf( "Illegal handle for database.\n" ); return( NULL ); } id = dispose_db_connection( pop_db_connection() ); if ( !hODBCEnv->hDBCons ) { //closing the last connection, close ODBC Environment destruct_odbc_environment(); } free_svalue( argv ); put_number( argv, id ); #if ODBC_DEBUG & DEBUG_FUNC printf( "ret f_sql_close( )\n" ); #endif return( argv ); }
/************************************************************************* * f_sql_affected_rows( int handle ) * * returns the number of rows in the resultset *************************************************************************/ svalue_t * f_sql_affected_rows( svalue_t * argv, int argc ) { #if ODBC_DEBUG & DEBUG_FUNC printf( "call f_sql_affected_rows( )\n" ); #endif int id; hDBC * handle; TYPE_TEST1( argv, T_NUMBER ); id = argv->u.number; free_svalue( argv ); if ( !(handle = get_db_connection_by_id( id )) ) { errorf( "Illegal handle for database.\n" ); return( NULL ); } if ( !handle->hStmt ) { put_number( argv, 0 ); return( argv ); } put_number( argv, handle->rowcnt ); #if ODBC_DEBUG & DEBUG_FUNC printf( "ret f_sql_affected_rows( )\n" ); #endif return( argv ); }
/*-------------------------------------------------------------------------*/ svalue_t * f_intersect_alist (svalue_t *sp) /* EFUN intersect_alist() * * mixed * intersect_alist (mixed * list1, mixed * list2) * * Does a fast set intersection on alist key vectors (NOT on full * alists!). * * The result is a new sorted(!) vector with all elements, which are present * in both input vectors. * * The operator '&' does set intersection on arrays in * general. * * TODO: Maybe rename the efun. */ { vector_t *rc; rc = intersect_ordered_arr(sp[-1].u.vec, sp->u.vec); free_svalue(sp--); free_array(sp->u.vec); sp->u.vec = rc; return sp; } /* f_intersect_alist() */
/* Note that now, once the master object loads once, there is ALWAYS a * master object, so the only way this can fail is if the master object * hasn't loaded yet. In that case, we return (svalue_t *)-1, and the * calling routine should let the check succeed. 失败只可能是还没有load进master 这像是在让master调用函数? */ svalue_t *apply_master_ob(int fun, int num_arg) /* 将master应用起来? */ { if (!master_ob) { pop_n_elems(num_arg); /* 只要master还没有load进来,就将栈清空? */ return (svalue_t *)-1; } if (master_applies[fun].func) { /* 这里会调用不同的函数,函数都在里边? */ #ifdef TRACE if (TRACEP(TRACE_APPLY)) { do_trace("master apply", master_applies[fun].func->name, "\n"); } #endif DEBUG_CHECK(master_ob->flags & O_SWAPPED, "Master object swapped!\n"); call_direct(master_ob, master_applies[fun].index, ORIGIN_DRIVER, num_arg); /* 像是在调用函数? */ free_svalue(&apply_ret_value, "apply_master_ob"); apply_ret_value = *sp--; /* 从栈中取出返回值 */ return &apply_ret_value; } else { pop_n_elems(num_arg); return 0; } }
/* Free any allocated data in the struct */ static void free_nb_struct(struct object *obj) { DERR(fprintf(stderr, "Freeing storage.\n")); while(THIS->inputs != NULL) { free_input(THIS->inputs); } if(THIS->outp != NULL) { free_output(THIS->outp); THIS->outp = NULL; } free_data_buf(); free_svalue(&THIS->args); free_svalue(&THIS->cb); THIS->cb.type = T_INT; THIS->args.type = T_INT; }
int free_apairs(struct apair *p) { struct apair *next; int pairs = 0; for (;p;p = next) { free_svalue(&p->arg); free_svalue(&p->val); next = p->next; free((char *)p); total_mapping_size -= sizeof(struct apair); pairs++; } return pairs; }
void c_void_assign() { #ifdef DEBUG if (sp->type != T_LVALUE) fatal("Bad argument to F_VOID_ASSIGN\n"); #endif lval = (sp--)->u.lvalue; if (sp->type != T_INVALID) { switch(lval->type) { case T_LVALUE_BYTE: { if (sp->type != T_NUMBER) { error("Illegal rhs to char lvalue\n"); } else { *global_lvalue_byte.u.lvalue_byte = (sp--)->u.number & 0xff; } break; } case T_LVALUE_RANGE: { copy_lvalue_range(sp--); break; } default: { free_svalue(lval, "F_VOID_ASSIGN : 3"); *lval = *sp--; } } } else sp--; }
void free_vector(struct vector *p) { int i; if (!p->ref || --p->ref > 0) return; #if 0 if (p->ref < 0) { debug_message("Array reference count < 0 in free_vector.\n"); return; } #endif #if defined(DEBUG) if (p == &null_vector) { p->ref = 1; debug_message("Tried to free the zero-size shared vector.\n"); return; } #endif for (i = 0; i < p->size; i++) free_svalue(&p->item[i]); num_arrays--; total_array_size -= sizeof (struct vector) + sizeof (struct svalue) * (p->size-1); free((char *)p); }
INLINE void dealloc_mapping (mapping_t * m) { debug(mapping,("mapping.c: actual free of %p\n", m)); num_mappings--; { int j = m->table_size, c = MAP_COUNT(m); mapping_node_t *elt, *nelt, **a = m->table; total_mapping_size -= (sizeof(mapping_t) + sizeof(mapping_node_t *) * (j+1) + sizeof(mapping_node_t) * c); total_mapping_nodes -= c; #ifdef PACKAGE_MUDLIB_STATS add_array_size (&m->stats, - (c << 1)); #endif do { for (elt = a[j]; elt; elt = nelt) { nelt = elt->next; free_svalue(elt->values, "free_mapping"); free_node(m, elt); } } while (j--); debug(mapping, ("in free_mapping: before table\n")); FREE((char *)a); } debug(mapping, ("in free_mapping: after table\n")); FREE((char *) m); debug(mapping, ("in free_mapping: after m\n")); debug(mapping,("mapping.c: free_mapping end\n")); }
/*-------------------------------------------------------------------------*/ svalue_t * f_tls_deinit_connection(svalue_t *sp) /* EFUN tls_deinit_connection() * * void tls_deinit_connection(object ob) * * tls_deinit_connection() shuts down a TLS connection to the interactive * object <ob> (or this_object() if <ob> is not given) but the connection is * not closed. */ { interactive_t *ip; if (!O_SET_INTERACTIVE(ip, sp->u.ob)) errorf("Bad arg 1 to tls_deinit_connection(): " "object not interactive.\n"); /* Flush the connection */ { object_t * save_c_g = command_giver; command_giver = sp->u.ob; add_message(message_flush); command_giver = save_c_g; } tls_deinit_connection(ip); free_svalue(sp--); return sp; } /* f_tls_deinit_connection() */
/*-------------------------------------------------------------------------*/ void struct_free (struct_t *pStruct) /* Free the struct <pStruct> and all referenced data. */ { unsigned short num; struct_type_t * pSType; #ifdef DEBUG if (!pStruct) fatal("NULL pointer passed to struct_free().\n"); if (!pStruct->user) fatal("No wizlist pointer for struct in struct_free()."); if (pStruct->ref != 0) fatal("Struct with %"PRIdPINT" refs passed to struct_free().\n" , pStruct->ref); #endif for (num = struct_size(pStruct); num-- > 0; ) { free_svalue(&pStruct->member[num]); } pSType = pStruct->type; struct_free_empty(pStruct); /* needs a valid .type */ free_struct_type(pSType); } /* struct_free() */
/*-------------------------------------------------------------------------*/ svalue_t * f_tls_query_connection_state (svalue_t *sp) /* EFUN tls_query_connection_state() * * int tls_query_connection_state(object ob) * * tls_query_connection_state() returns a positive number if <ob>'s connection * is TLS secured, 0 if it's unsecured, and a negative number if the * TLS connection setup is still being set-up. * Returns 0 for non-interactive objects. */ { interactive_t *ip; Bool rc; if (!O_SET_INTERACTIVE(ip, sp->u.ob)) rc = 0; else if (ip->tls_status == TLS_HANDSHAKING) rc = -1; else if (ip->tls_status == TLS_INACTIVE) rc = 0; else rc = 1; free_svalue(sp); put_number(sp, rc); return sp; } /* f_tls_query_connection_state() */
void dealloc_class P1(array_t *, p) { int i; for (i = p->size; i--;) free_svalue(&p->item[i], "dealloc_class"); FREE((char *) p); }
void c_void_assign_local(svalue_t * var) { if (sp->type == T_INVALID) { sp--; return; } free_svalue(var, "c_void_assign_local"); *var = *sp--; }
void c_end_catch(error_context_t * econ) { free_svalue(&catch_value, "F_END_CATCH"); catch_value = const0; /* We come here when no longjmp() was executed */ pop_control_stack(); push_number(0); pop_context(econ); }
PMOD_EXPORT void convert_svalue_to_bignum(struct svalue *s) { push_svalue(s); convert_stack_top_to_bignum(); free_svalue(s); *s=sp[-1]; sp--; dmalloc_touch_svalue(sp); }
static void image_ilbm___decode(INT32 args) { unsigned char *s; ptrdiff_t len; struct pike_string *str; struct mapping *m; int n; extern void parse_iff(char *, unsigned char *, ptrdiff_t, struct mapping *, char *); get_all_args("__decode", args, "%S", &str); s = (unsigned char *)str->str; len = str->len; pop_n_elems(args-1); for(n=0; n<5; n++) push_int(0); push_mapping(m = allocate_mapping(4)); parse_iff("ILBM", s, len, m, "BODY"); mapping_index_no_free(sp-5, m, &string_[string_BMHD]); mapping_index_no_free(sp-4, m, &string_[string_CMAP]); mapping_index_no_free(sp-3, m, &string_[string_CAMG]); mapping_index_no_free(sp-2, m, &string_[string_BODY]); map_delete(m, &string_[string_BMHD]); map_delete(m, &string_[string_CMAP]); map_delete(m, &string_[string_CAMG]); map_delete(m, &string_[string_BODY]); if(sp[-5].type != T_STRING) Pike_error("Missing BMHD chunk\n"); if(sp[-2].type != T_STRING) Pike_error("Missing BODY chunk\n"); /* Extract image size from BMHD */ s = (unsigned char *)STR0(sp[-5].u.string); len = sp[-5].u.string->len; if(len<20) Pike_error("Short BMHD chunk\n"); free_svalue(sp-7); sp[-7].u.integer = (s[0]<<8)|s[1]; sp[-7].type = T_INT; sp[-7].subtype = NUMBER_NUMBER; sp[-6].u.integer = (s[2]<<8)|s[3]; sp[-6].type = T_INT; sp[-6].subtype = NUMBER_NUMBER; f_aggregate(7); }
struct vector * make_unique(struct vector *arr, struct closure *fun, struct svalue *skipnum) { struct vector *res, *ret; struct unique *head, *nxt, *nxt2; int cnt, ant, cnt2; if (arr->size < 1) return allocate_array(0); head = 0; ant = 0; INCREF(arr->ref); for(cnt = 0; cnt < arr->size; cnt++) { if (arr->item[cnt].type == T_OBJECT) { push_svalue(&arr->item[cnt]); (void)call_var(1, fun); if ((!sp) || (sp->type != skipnum->type) || !equal_svalue(sp, skipnum)) { if (sp) { ant = put_in(&head, sp, &(arr->item[cnt])); } } pop_stack(); } } DECREF(arr->ref); ret = allocate_array(ant); for (cnt = ant - 1; cnt >= 0; cnt--) /* Reverse to compensate put_in */ { ret->item[cnt].type = T_POINTER; ret->item[cnt].u.vec = res = allocate_array(head->count); nxt2 = head; head = head->next; cnt2 = 0; while (nxt2) { assign_svalue_no_free (&res->item[cnt2++], nxt2->val); free_svalue(&nxt2->mark); nxt = nxt2->same; /* tmpfree((char *) nxt2); */ nxt2 = nxt; } if (!head) break; /* It shouldn't but, to avoid skydive just in case */ } return ret; }
void dealloc_class (array_t * p) { int i; #ifdef CLASS_STATS num_classes--; total_class_size -= sizeof(array_t) + sizeof(svalue_t) * (p->size - 1); #endif for (i = p->size; i--;) free_svalue(&p->item[i], "dealloc_class"); FREE((char *) p); }
void handle_db_exec(struct request *req){ free_svalue(&req->tmp, "handle_db_exec"); int val = req->ret; if(val == -1){ copy_and_push_string(req->path); } else push_number(val); set_eval(max_cost); safe_call_efun_callback(req->fun, 1); }
/*! @decl void set_output_closed_callback(void|function(mixed, object:mixed) close_cb, @ *! void|mixed id) *! *! Set the callback function to be called when one of the outputs has *! been closed from the other side. */ static void pipe_set_output_closed_callback(INT32 args) { if (args==0) { free_svalue(&THIS->output_closed_callback); THIS->output_closed_callback.type=T_INT; return; } if (args<1 || (sp[-args].type!=T_FUNCTION && sp[-args].type!=T_ARRAY)) Pike_error("Illegal argument to set_output_closed_callback()\n"); if (args>1) { free_svalue(&THIS->id); assign_svalue_no_free(&(THIS->id),sp-args+1); } free_svalue(&THIS->output_closed_callback); assign_svalue_no_free(&(THIS->output_closed_callback),sp-args); pop_n_elems(args-1); }
void free_node (mapping_t * m, mapping_node_t * mn) { if (m->count & MAP_LOCKED) { mn->next = locked_map_nodes; locked_map_nodes = mn; mn->values[0].u.map = m; } else { free_svalue(mn->values + 1, "free_node"); mn->next = free_nodes; free_nodes = mn; } }
static void check_svalue(svalue_t * v) { register int idx; nested++; if (nested > MAX_RECURSION) { return; } switch (v->type) { case T_OBJECT: if (v->u.ob->flags & O_DESTRUCTED) { free_svalue(v, "reclaim_objects"); *v = const0u; cleaned++; } break; case T_MAPPING: gc_mapping(v->u.map); break; case T_ARRAY: case T_CLASS: for (idx = 0; idx < v->u.arr->size; idx++) check_svalue(&v->u.arr->item[idx]); break; case T_FUNCTION: { svalue_t tmp; program_t *prog; if (v->u.fp->hdr.owner && (v->u.fp->hdr.owner->flags & O_DESTRUCTED)) { if (v->u.fp->hdr.type == FP_LOCAL | FP_NOT_BINDABLE) { prog = v->u.fp->hdr.owner->prog; prog->func_ref--; debug(d_flag, ("subtr func ref /%s: now %i\n", prog->name, prog->func_ref)); if (!prog->ref && !prog->func_ref) deallocate_program(prog); } free_object(v->u.fp->hdr.owner, "reclaim_objects"); v->u.fp->hdr.owner = 0; cleaned++; } tmp.type = T_ARRAY; if ((tmp.u.arr = v->u.fp->hdr.args)) check_svalue(&tmp); break; } } nested--; return; }