/* 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); }
int m_restore_object(struct object *ob, struct mapping *map) { int p; int i; struct apair *j; if (ob->flags & O_DESTRUCTED) return 0; for (i = 0; i < map->size; i++) { for (j = map->pairs[i]; j ; j = j->next) { if (j->arg.type != T_STRING) continue; if ((p = find_status(ob->prog, j->arg.u.string, TYPE_MOD_STATIC)) == -1) continue; assign_svalue(&ob->variables[p], &j->val); } } return 1; }
void c_prepare_catch(error_context_t * econ) { if (!save_context(econ)) error("Can't catch too deep recursion error.\n"); push_control_stack(FRAME_CATCH); #if defined(DEBUG) || defined(TRACE_CODE) csp->num_local_variables = (csp - 1)->num_local_variables; /* marion */ #endif assign_svalue(&catch_value, &const1); }
int c_next_foreach (void) { if ((sp-1)->type == T_LVALUE) { /* mapping */ if ((sp-2)->subtype--) { svalue_t *key = (sp-2)->u.lvalue++; svalue_t *value = find_in_mapping((sp-4)->u.map, key); assign_svalue((sp-1)->u.lvalue, key); if (sp->type == T_REF) { if (value == &const0u) sp->u.ref->lvalue = 0; else sp->u.ref->lvalue = value; } else assign_svalue(sp->u.lvalue, value); return 1; } } else { /* array or string */ if ((sp-1)->subtype--) { if ((sp-2)->type == T_STRING) { if (sp->type == T_REF) { sp->u.ref->lvalue = &global_lvalue_byte; global_lvalue_byte.u.lvalue_byte = (unsigned char *)((sp-1)->u.lvalue_byte++); } else { free_svalue(sp->u.lvalue, "string foreach"); sp->u.lvalue->type = T_NUMBER; sp->u.lvalue->subtype = 0; sp->u.lvalue->u.number = *((sp-1)->u.lvalue_byte)++; } } else { if (sp->type == T_REF) sp->u.ref->lvalue = (sp-1)->u.lvalue++; else assign_svalue(sp->u.lvalue, (sp-1)->u.lvalue++); } return 1; } } c_exit_foreach(); return 0; }
/*-------------------------------------------------------------------------*/ void check_wizlist_for_destr (void) /* Check the 'extra' info in all wizinfo and remove destructed objects * and closures. */ { wiz_list_t *wl; for (wl = &default_wizlist_entry; wl; ) { size_t num; svalue_t *item; if (wl->extra.type == T_POINTER) { num = VEC_SIZE(wl->extra.u.vec); item = &(wl->extra.u.vec->item[0]); } else { num = 1; item = &(wl->extra); } for ( ; num != 0 ; item++, num--) { switch(item->type) { case T_POINTER: check_for_destr(item->u.vec); break; case T_MAPPING: check_map_for_destr(item->u.map); break; case T_OBJECT: case T_CLOSURE: if (destructed_object_ref(item)) assign_svalue(item, &const0); break; default: NOOP; break; } } if (wl == &default_wizlist_entry) wl = all_wiz; else wl = wl->next; } } /* check_wizlist_for_destr() */
INLINE struct vector * union_array(struct vector *arr1, struct vector *arr2) { int i, size; struct mapping *mp; struct vector *arr3; char *set; if (arr1->size == 0) { INCREF(arr2->ref); return arr2; } if (arr2->size == 0) { INCREF(arr1->ref); return arr1; } mp = allocate_map(arr1->size); for (i = 0; i < arr1->size; i++) assign_svalue(get_map_lvalue(mp, &arr1->item[i], 1), &const1); set = alloca((size_t)arr2->size); for (i = size = 0; i < arr2->size; i++) { if (get_map_lvalue(mp, &arr2->item[i], 0) == &const0) set[i] = 1, size++; else set[i] = 0; } free_mapping(mp); arr3 = allocate_array(arr1->size + size); for (i = 0; i < arr1->size; i++) assign_svalue_no_free(&arr3->item[i], &arr1->item[i]); size = arr1->size; for (i = 0; i < arr2->size; i++) if (set[i]) assign_svalue_no_free(&arr3->item[size++], &arr2->item[i]); return arr3; }
void f_store_class_member() { int pos = ( sp - 1 )->u.number; array_t *arr; if( ( sp - 2 )->type != T_CLASS ) error( "Argument to store_class_member() not a class.\n" ); arr = ( sp - 2 )->u.arr; if( pos < 0 || pos >= arr->size ) error( "Class index out of bounds.\n" ); assign_svalue(&arr->item[pos], sp); pop_2_elems(); }
static void assign_accept_cb (struct port *p, struct svalue *cb) { assign_svalue(& p->accept_callback, cb); if (UNSAFE_IS_ZERO (cb)) { if (p->box.backend) set_fd_callback_events (&p->box, 0, 0); set_nonblocking(p->box.fd,0); } else { if (!p->box.backend) INIT_FD_CALLBACK_BOX (&p->box, default_backend, p->box.ref_obj, p->box.fd, PIKE_BIT_FD_READ, got_port_event, 0); else set_fd_callback_events (&p->box, PIKE_BIT_FD_READ, 0); set_nonblocking(p->box.fd,1); } }
/*-------------------------------------------------------------------------*/ svalue_t * f_get_extra_wizinfo (svalue_t *sp) /* EFUN get_extra_wizinfo() * * mixed get_extra_wizinfo (object wiz) * mixed get_extra_wizinfo (string wiz) * mixed get_extra_wizinfo (int wiz) * * Returns the 'extra' information that was set for the given * wizard <wiz> in the wizlist. * * 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 get from the default wizlist * entry. * * The function causes a privilege violation * ("get_extra_wizinfo", this_object(), <wiz>). */ { wiz_list_t *user; short type; if ((type = sp->type) == T_OBJECT) { user = sp->u.ob->user; } else if (type != T_STRING || !(user = find_wiz(sp->u.str))) { if (type == T_NUMBER && sp->u.number == 0) user = NULL; else errorf("Bad arg 1 to get_extra_wizinfo(): no valid uid given.\n"); } if (!privilege_violation(STR_GET_EXTRA_WIZINFO, sp, sp)) errorf("Error in get_extra_wizinfo(): privilege violation.\n"); assign_svalue(sp, user ? &user->extra : &default_wizlist_entry.extra); return sp; } /* get_extra_wizlist_info() */
/* * Save an object to a mapping. */ struct mapping * m_save_object(struct object *ob) { int i, j; struct mapping *ret; struct svalue s = const0; if (ob->flags & O_DESTRUCTED) return allocate_map(0); /* XXX is this right /LA */ ret = allocate_map((short)(ob->prog->num_variables + ob->prog->inherit[ob->prog->num_inherited - 1]. variable_index_offset)); for (j = 0; j < (int)ob->prog->num_inherited; j++) { struct program *prog = ob->prog->inherit[j].prog; if (ob->prog->inherit[j].type & TYPE_MOD_SECOND || prog->num_variables == 0) continue; for (i = 0; i < (int)prog->num_variables; i++) { struct svalue *v = &ob->variables[i + ob->prog->inherit[j]. variable_index_offset]; if (prog->variable_names[i].type & TYPE_MOD_STATIC) continue; free_svalue(&s); s.type = T_STRING; s.string_type = STRING_MSTRING; s.u.string = make_mstring(prog->variable_names[i].name); assign_svalue(get_map_lvalue(ret, &s, 1), v); } } free_svalue(&s); return ret; }
void c_assign() { #ifdef DEBUG if (sp->type != T_LVALUE) fatal("Bad argument to F_ASSIGN\n"); #endif switch(sp->u.lvalue->type) { case T_LVALUE_BYTE: if ((sp - 1)->type != T_NUMBER) { error("Illegal rhs to char lvalue\n"); } else { *global_lvalue_byte.u.lvalue_byte = ((sp - 1)->u.number & 0xff); } break; default: assign_svalue(sp->u.lvalue, sp - 1); break; case T_LVALUE_RANGE: assign_lvalue_range(sp - 1); break; } sp--; /* ignore lvalue */ /* rvalue is already in the correct place */ }
int copy_file (const char * from, const char * to) { char buf[128]; int from_fd, to_fd; int num_read, num_written; char *write_ptr; extern svalue_t apply_ret_value; from = check_valid_path(from, current_object, "move_file", 0); assign_svalue(&from_sv, &apply_ret_value); to = check_valid_path(to, current_object, "move_file", 1); assign_svalue(&to_sv, &apply_ret_value); if (from == 0) return -1; if (to == 0) return -2; if (lstat(from, &from_stats) != 0) { error("/%s: lstat failed\n", from); return 1; } if (lstat(to, &to_stats) == 0) { #ifdef WIN32 if (!strcmp(from, to)) #else if (from_stats.st_dev == to_stats.st_dev && from_stats.st_ino == to_stats.st_ino) #endif { error("`/%s' and `/%s' are the same file", from, to); return 1; } } else if (errno != ENOENT) { error("/%s: unknown error\n", to); return 1; } from_fd = open(from, OPEN_READ); if (from_fd < 0) return -1; if (file_size(to) == -2) { /* Target is a directory; build full target filename. */ const char *cp; char newto[MAX_FNAME_SIZE + MAX_PATH_LEN + 2]; cp = strrchr(from, '/'); if (cp) cp++; else cp = from; sprintf(newto, "%s/%s", to, cp); close(from_fd); return copy_file(from, newto); } to_fd = open(to, OPEN_WRITE | O_CREAT | O_TRUNC, 0666); if (to_fd < 0) { close(from_fd); return -2; } while ((num_read = read(from_fd, buf, 128)) != 0) { if (num_read < 0) { debug_perror("copy_file: read", from); close(from_fd); close(to_fd); return -3; } write_ptr = buf; while (write_ptr != (buf + num_read)) { num_written = write(to_fd, write_ptr, num_read); if (num_written < 0) { debug_perror("copy_file: write", to); close(from_fd); close(to_fd); return -3; } write_ptr += num_written; } } close(from_fd); close(to_fd); return 1; }
void c_not() { if (sp->type == T_NUMBER) sp->u.number = !sp->u.number; else assign_svalue(sp, &const0); }
void c_index() { int i; switch (sp->type) { case T_MAPPING: { svalue_t *v; mapping_t *m; v = find_in_mapping(m = sp->u.map, sp - 1); assign_svalue(--sp, v); /* v will always have a * value */ free_mapping(m); break; } #ifndef NO_BUFFER_TYPE case T_BUFFER: { if ((sp-1)->type != T_NUMBER) error("Indexing a buffer with an illegal type.\n"); i = (sp - 1)->u.number; if ((i > sp->u.buf->size) || (i < 0)) error("Buffer index out of bounds.\n"); i = sp->u.buf->item[i]; free_buffer(sp->u.buf); (--sp)->u.number = i; break; } #endif case T_STRING: { if ((sp-1)->type != T_NUMBER) { error("Indexing a string with an illegal type.\n"); } i = (sp - 1)->u.number; if ((i > SVALUE_STRLEN(sp)) || (i < 0)) error("String index out of bounds.\n"); i = (unsigned char) sp->u.string[i]; free_string_svalue(sp); (--sp)->u.number = i; break; } case T_ARRAY: { array_t *arr; if ((sp-1)->type != T_NUMBER) error("Indexing an array with an illegal type\n"); i = (sp - 1)->u.number; if (i<0) error("Negative index passed to array.\n"); arr = sp->u.arr; if (i >= arr->size) error("Array index out of bounds.\n"); assign_svalue_no_free(--sp, &arr->item[i]); free_array(arr); break; } default: error("Indexing on illegal type.\n"); } /* * Fetch value of a variable. It is possible that it is a * variable that points to a destructed object. In that case, * it has to be replaced by 0. */ if (sp->type == T_OBJECT && (sp->u.ob->flags & O_DESTRUCTED)) { free_object(sp->u.ob, "F_INDEX"); *sp = const0u; } }
/*! @decl mixed set_id(mixed id) *! *! This function sets the id used for accept_callback by this port. *! The default id is @[this_object()]. *! *! @seealso *! @[query_id] */ static void port_set_id(INT32 args) { check_all_args(NULL, args, BIT_MIXED, 0); assign_svalue(& THIS->id, Pike_sp-args); pop_n_elems(args-1); }
int do_rename (const char * fr, const char * t, int flag) { const char *from; const char *to; char newfrom[MAX_FNAME_SIZE + MAX_PATH_LEN + 2]; int flen; extern svalue_t apply_ret_value; /* * important that the same write access checks are done for link() as are * done for rename(). Otherwise all kinds of security problems would * arise (e.g. creating links to files in protected directories and then * modifying the protected file by modifying the linked file). The idea * is prevent linking to a file unless the person doing the linking has * permission to move the file. */ from = check_valid_path(fr, current_object, "rename", 1); if (!from) return 1; assign_svalue(&from_sv, &apply_ret_value); to = check_valid_path(t, current_object, "rename", 1); if (!to) return 1; assign_svalue(&to_sv, &apply_ret_value); if (!strlen(to) && !strcmp(t, "/")) { to = "./"; } /* Strip trailing slashes */ flen = strlen(from); if (flen > 1 && from[flen - 1] == '/') { const char *p = from + flen - 2; int n; while (*p == '/' && (p > from)) p--; n = p - from + 1; memcpy(newfrom, from, n); newfrom[n] = 0; from = newfrom; } if (file_size(to) == -2) { /* Target is a directory; build full target filename. */ const char *cp; char newto[MAX_FNAME_SIZE + MAX_PATH_LEN + 2]; cp = strrchr(from, '/'); if (cp) cp++; else cp = from; sprintf(newto, "%s/%s", to, cp); return do_move(from, newto, flag); } else return do_move(from, to, flag); }
/*-------------------------------------------------------------------------*/ svalue_t * x_map_struct (svalue_t *sp, int num_arg) /* EFUN map() on structs * * mixed * map(struct arg, string func, string|object ob, mixed extra...) * mixed * map(struct arg, closure cl, mixed extra...) * mixed * map(struct arr, mapping map [, int col]) * * Map the elements of <arr> through a filter defined by the other * arguments, and return an array of the elements returned by the filter. * * The filter can be a function call: * * <obj>-><fun>(elem, <extra>...) * * or a mapping query: * * <map>[elem[,idx]] * * In the mapping case, if <map>[elem[,idx]] does not exist, the original * value is returned in the result. * [Note: argument type and range checking for idx is done in v_map()] * * <obj> can both be an object reference or a filename. If <ob> is * omitted, or neither an object nor a string, then this_object() is used. * * As a bonus, all references to destructed objects in <arr> are replaced * by proper 0es. */ { struct_t *st; struct_t *res; svalue_t *arg; svalue_t *v, *w, *x; mp_int cnt; inter_sp = sp; arg = sp - num_arg + 1; st = arg->u.strct; cnt = (mp_int)struct_size(st); if (arg[1].type == T_MAPPING) { /* --- Map through mapping --- */ mapping_t *m; p_int column = 0; /* mapping column to use */ m = arg[1].u.map; if (num_arg > 2) column = arg[2].u.number; res = struct_new(st->type); if (!res) errorf("(map_struct) Out of memory: struct[%"PRIdMPINT"] for result\n", cnt); push_struct(inter_sp, res); /* In case of errors */ for (w = st->member, x = res->member; --cnt >= 0; w++, x++) { if (destructed_object_ref(w)) assign_svalue(w, &const0); v = get_map_value(m, w); if (v == &const0) assign_svalue_no_free(x, w); else assign_svalue_no_free(x, v + column); } if (num_arg > 2) free_svalue(arg+2); free_svalue(arg+1); /* the mapping */ sp = arg; } else { /* --- Map through function call --- */ callback_t cb; int error_index; error_index = setup_efun_callback(&cb, arg+1, num_arg-1); if (error_index >= 0) { vefun_bad_arg(error_index+2, arg); /* NOTREACHED */ return arg; } inter_sp = sp = arg+1; put_callback(sp, &cb); num_arg = 2; res = struct_new(st->type); if (!res) errorf("(map_struct) Out of memory: struct[%"PRIdMPINT"] for result\n", cnt); push_struct(inter_sp, res); /* In case of errors */ /* Loop through arr and res, mapping the values from arr */ for (w = st->member, x = res->member; --cnt >= 0; w++, x++) { if (current_object->flags & O_DESTRUCTED) continue; if (destructed_object_ref(w)) assign_svalue(w, &const0); if (!callback_object(&cb)) errorf("object used by map_array destructed"); push_svalue(w); v = apply_callback(&cb, 1); if (v) { transfer_svalue_no_free(x, v); v->type = T_INVALID; } } free_callback(&cb); } /* The arguments have been removed already, now just replace * the struct on the stack with the result. */ free_struct(st); arg->u.strct = res; /* Keep svalue type T_STRUCT */ return arg; } /* x_map_struct () */
/*-------------------------------------------------------------------------*/ static svalue_t * insert_alist (svalue_t *key, svalue_t * /* TODO: bool */ key_data, vector_t *list) /* Implementation of efun insert_alist() * * The function can be used in two ways: * * 1. Insert/replace a (new) <key>:<keydata> tuple into the alist <list>. * <key> and <key_data> have to point to an array of svalues. The first * element is the key value, the following values the associated * data values. The function will read as many elements from the * array as necessary to fill the alist <list>. * Result is a fresh copy of the modified alist. * * 2. Lookup a <key> in the alist <list> and return its index. If the key * is not found, return the position at which it would be inserted. * <key_data> must be NULL, <key> points to the svalue to be looked * up, and <list> points to an alist with at least the key vector. * * If <list> is no alist, the result can be wrong (case 2.) or not * an alist either (case 1.). * * If the <key> is a string, it is made shared. * * TODO: Make the hidden flag 'key_data' a real flag. */ { static svalue_t stmp; /* Result value */ mp_int i,j,ix; mp_int keynum, list_size; /* Number of keys, number of alist vectors */ int new_member; /* Flag if a new tuple is given */ /* If key is a string, make it shared */ if (key->type == T_STRING && !mstr_tabled(key->u.str)) { key->u.str = make_tabled(key->u.str); } keynum = (mp_int)VEC_SIZE(list->item[0].u.vec); /* Locate the key */ ix = lookup_key(key, list->item[0].u.vec); /* If its just a lookup: return the result. */ if (key_data == NULL) { put_number(&stmp, ix < 0 ? -ix-1 : ix); return &stmp; } /* Prepare the result alist vector */ put_array(&stmp, allocate_array(list_size = (mp_int)VEC_SIZE(list))); new_member = ix < 0; if (new_member) ix = -ix-1; /* Loop over all key/data vectors in <list>, insert/replace the * new value and put the new vector into <stmp>. */ for (i = 0; i < list_size; i++) { vector_t *vtmp; if (new_member) { svalue_t *pstmp = list->item[i].u.vec->item; vtmp = allocate_array(keynum+1); for (j=0; j < ix; j++) { assign_svalue_no_free(&vtmp->item[j], pstmp++); } assign_svalue_no_free(&vtmp->item[ix], i ? &key_data[i] : key ); for (j = ix+1; j <= keynum; j++) { assign_svalue_no_free(&vtmp->item[j], pstmp++); } } else { vtmp = slice_array(list->item[i].u.vec, 0, keynum-1); if (i) assign_svalue(&vtmp->item[ix], &key_data[i]); /* No need to assign the key value: it's already there. */ } stmp.u.vec->item[i].type=T_POINTER; stmp.u.vec->item[i].u.vec=vtmp; } /* Done */ return &stmp; } /* insert_alist() */
/*-------------------------------------------------------------------------*/ svalue_t * v_assoc (svalue_t *sp, int num_arg) /* EFUN assoc() * * int assoc (mixed key, mixed *keys) * mixed assoc (mixed key, mixed *alist [, mixed fail] ) * mixed assoc (mixed key, mixed *keys, mixed *data [, mixed fail]) * * Search for <key> in the <alist> resp. in the <keys>. * * When the key list of an alist contains destructed objects * it is better not to free them till the next reordering by * order_alist to retain the alist property. */ { svalue_t *args; vector_t *keys,*data; svalue_t *fail_val; int ix; args = sp -num_arg +1; /* Analyse the arguments */ if ( !VEC_SIZE(args[1].u.vec) || args[1].u.vec->item[0].type != T_POINTER ) { keys = args[1].u.vec; if (num_arg == 2) { data = NULL; } else { if (args[2].type != T_POINTER || VEC_SIZE(args[2].u.vec) != VEC_SIZE(keys)) { errorf("Number of values in key and data arrays differ.\n"); /* NOTREACHED */ return sp; } data = args[2].u.vec; } if (num_arg == 4) { fail_val = &args[3]; } else { fail_val = &const0; } } else { keys = args[1].u.vec->item[0].u.vec; if (VEC_SIZE(args[1].u.vec) > 1) { if (args[1].u.vec->item[1].type != T_POINTER || VEC_SIZE(args[1].u.vec->item[1].u.vec) != VEC_SIZE(keys)) { errorf("Number of values in key and data arrays differ.\n"); /* NOTREACHED */ return sp; } data = args[1].u.vec->item[1].u.vec; } else { data = NULL; } if (num_arg == 3) fail_val = &args[2]; else if (num_arg == 2) fail_val = &const0; else { errorf("too many args to efun assoc\n"); /* NOTREACHED */ return sp; } } /* Call lookup_key() and push the result */ ix = lookup_key(&args[0],keys); if (data == NULL) { sp = pop_n_elems(num_arg, sp); push_number(sp, ix < 0 ? -1 : ix); } else { assign_svalue(args , ix < 0 ? fail_val : (destructed_object_ref(&data->item[ix]) ? &const0 : &data->item[ix]) ); sp = pop_n_elems(num_arg-1, sp); } return sp; } /* v_assoc() */