/* **| method: string dn2ufn ( string dn ); **| Convert the given DN to an user friendly form thereof. This will **| strip the type names from the passed dn. See RFC 1781 for more **| details. ** **| arg: string dn **| an UTF-8 string with the dn to convert. ** **| returns: the user friendly form of the DN. */ static void f_ldap_dn2ufn(INT32 args) { struct pike_string *dn = NULL; char *ufn; if (args != 1) Pike_error("OpenLDAP.Client->dn2ufn(): requires exactly one 8-bit string argument\n"); get_all_args("OpenLDAP.Client->dn2ufn()", args, "%S", &dn); pop_n_elems(args); if (!dn) { push_int(0); return; } ufn = ldap_dn2ufn(dn->str); if (!ufn) { push_int(0); } else { push_string(make_shared_string(ufn)); ldap_memfree(ufn); } }
static INLINE struct svalue *lookup_header(char *headername) { struct svalue *headers, *value; struct pike_string *sind; #ifdef ROXEN_USE_ZTS GET_THIS(); #endif sind = make_shared_string("env"); headers = low_mapping_string_lookup(REQUEST_DATA, sind); free_string(sind); if(!headers || headers->type != PIKE_T_MAPPING) return NULL; sind = make_shared_string(headername); value = low_mapping_string_lookup(headers->u.mapping, sind); free_string(sind); if(!value) return NULL; return value; }
/* * Associate a command with function in this object. * * The optinal third argument is a flag that will state that the verb should * only match against leading characters. * * The object must be near the command giver, so that we ensure that the * sentence is removed when the command giver leaves. * * If the call is from a shadow, make it look like it is really from * the shadowed object. */ static void add_action (svalue_t * str, const char *cmd, int flag) { sentence_t *p; object_t *ob; if (current_object->flags & O_DESTRUCTED) return; ob = current_object; #ifndef NO_SHADOWS while (ob->shadowing) { ob = ob->shadowing; } /* don't allow add_actions of a static function from a shadowing object */ if ((ob != current_object) && str->type == T_STRING && is_static(str->u.string, ob)) { return; } #endif if (command_giver == 0 || (command_giver->flags & O_DESTRUCTED)) return; if (ob != command_giver #ifndef NO_ENVIRONMENT && ob->super != command_giver && ob->super != command_giver->super && ob != command_giver->super #endif ) return; /* No need for an error, they know what they * did wrong. */ p = alloc_sentence(); if (str->type == T_STRING) { debug(d_flag, ("--Add action %s", str->u.string)); p->function.s = make_shared_string(str->u.string); p->flags = flag; } else { debug(d_flag, ("--Add action <function>")); p->function.f = str->u.fp; str->u.fp->hdr.ref++; p->flags = flag | V_FUNCTION; } p->ob = ob; p->verb = make_shared_string(cmd); /* This is ok; adding to the top of the list doesn't harm anything */ p->next = command_giver->sent; command_giver->sent = p; }
static void f_smtp_strerror(INT32 args) { int err; char buf[512], *str; if (args != 1) generic_error("strerror", Pike_sp-args, args, "Incorrect number of parameters - required 1.\n"); get_all_args("strerror", args, "%i", &err); pop_n_elems(args); str = smtp_strerror(err, buf, sizeof(buf)); if (!str) push_string(make_shared_string("Unknown error code.")); else push_string(make_shared_string(str)); }
static void init_ldap(struct object *o) { base_str = make_shared_string("base"); add_ref(base_str); scope_str = make_shared_string("scope"); add_ref(scope_str); filter_str = make_shared_string("filter"); add_ref(filter_str); attrs_str = make_shared_string("attrs"); add_ref(attrs_str); attrsonly_str = make_shared_string("attrsonly"); add_ref(attrsonly_str); timeout_str = make_shared_string("timeout"); add_ref(timeout_str); empty_str = make_shared_string(""); add_ref(empty_str); modify_op = make_shared_string("op"); add_ref(modify_op); modify_type = make_shared_string("type"); add_ref(modify_type); modify_values = make_shared_string("values"); add_ref(modify_values); THIS->conn = NULL; THIS->server_url = NULL; THIS->basedn = empty_str; THIS->scope = LDAP_SCOPE_DEFAULT; THIS->bound = 0; THIS->lerrno = 0; THIS->caching = 0; }
void pike_module_init( void ) { STRS(data) = make_shared_string("data"); STRS(file) = make_shared_string("file"); STRS(method) = make_shared_string("method"); STRS(protocol) = make_shared_string("protocol"); STRS(query) = make_shared_string("query"); STRS(raw_url) = make_shared_string("raw_url"); SVAL(data)->type = T_STRING; SVAL(file)->type = T_STRING; SVAL(method)->type = T_STRING; SVAL(protocol)->type = T_STRING; SVAL(query)->type = T_STRING; SVAL(raw_url)->type = T_STRING; add_function_constant( "parse_headers", f_parse_headers, "function(string:mapping)", 0); add_function_constant( "parse_query_string", f_parse_query_string, "function(string,mapping:void)", OPT_SIDE_EFFECT); add_function_constant( "get_address", f_get_address, "function(string:string)", 0); start_new_program(); ADD_STORAGE( buffer ); add_function( "append", f_buf_append, "function(string:int)", OPT_SIDE_EFFECT ); add_function( "create", f_buf_create, "function(mapping,mapping:void)", 0 ); set_exit_callback(free_buf_struct); set_init_callback(alloc_buf_struct); parsehttp_program = end_program(); add_program_constant("ParseHTTP", parsehttp_program, 0); }
void f_notify_fail (void) { if (command_giver && command_giver->interactive) { clear_notify(command_giver); if (sp->type == T_STRING) { command_giver->interactive->default_err_message.s = make_shared_string(sp->u.string); } else { command_giver->interactive->iflags |= NOTIFY_FAIL_FUNC; command_giver->interactive->default_err_message.f = sp->u.fp; sp->u.fp->hdr.ref++; } } pop_stack(); }
static int dict_insert(DICT *dict, struct object *obj, void *data) { INFUN(); if (!obj) return DICT_NULL_OBJECT; if (!data) return DICT_NULL_DATA; if (!dict) return DICT_NULL_DICT; if (dict->used && (dict->used >= dict->dict->data->num_keypairs)) { struct mapping *nmap, *tmp; nmap = allocate_mapping(dict->dict->data->num_keypairs << 1); tmp = merge_mappings(dict->dict, nmap, PIKE_ARRAY_OP_AND); free_mapping(dict->dict); free_mapping(nmap); dict->dict = tmp; } { struct svalue skey, sval, *tmp; char addr[64]; sval.type = T_OBJECT; sval.u.object = obj; sprintf(addr, "0x%X", (unsigned)data); skey.type = T_STRING; skey.u.string = make_shared_string(addr); tmp = low_mapping_lookup(dict->dict, &skey); if (tmp) { free_string(skey.u.string); OUTFUN(); return DICT_EXISTS; } mapping_insert(dict->dict, &skey, &sval); dict->used++; } OUTFUN(); return DICT_OK; }
static struct mapping *tree2mapping(xmlElementContentPtr content) { struct mapping *ret; struct svalue sv; if (!content) return NULL; ret = allocate_mapping(12); sv.type = T_INT; sv.u.integer = content->type; mapping_string_insert(ret, econtent_type, &sv); sv.u.integer = content->ocur; mapping_string_insert(ret, econtent_ocur, &sv); mapping_string_insert_string(ret, econtent_name, make_shared_string(content->name)); mapping_string_insert_string(ret, econtent_prefix, make_shared_string(content->prefix)); if (content->c1) { sv.type = T_MAPPING; sv.u.mapping = tree2mapping(content->c1); } else sv.u.integer = 0; mapping_string_insert(ret, econtent_c1, &sv); if (content->c2) { sv.type = T_MAPPING; sv.u.mapping = tree2mapping(content->c2); } else { sv.type = T_INT; sv.u.integer = 0; } mapping_string_insert(ret, econtent_c2, &sv); return ret; }
static void set_living_name (object_t * ob, const char *str) { int flags = ob->flags & O_ENABLE_COMMANDS; object_t **hl; if (ob->flags & O_DESTRUCTED) return; remove_living_name(ob); num_living_names++; hl = &hashed_living[hash_living_name(str)]; ob->next_hashed_living = *hl; *hl = ob; ob->living_name = make_shared_string(str); ob->flags |= flags; }
/* **| method: string err2string ( int lerrno ); **| Converts the specified error code into the corresponding **| message. ** **| arg: int lerrno **| LDAP error code. */ static void f_ldap_err2string(INT32 args) { int err; char *str; if (args != 1) Pike_error("OpenLDAP.Client->err2string() requires a single integer argument\n"); get_all_args("OpenLDAP.Client->err2string()", args, "%i", &err); pop_n_elems(args); str = ldap_err2string(err); push_string(make_shared_string(str)); }
/* Glue */ static void f_smtp_version(INT32 args) { char buf[256]; if (args != 0) generic_error("version", Pike_sp-args, args, "Too many arguments. None required.\n"); if (!smtp_version(buf, sizeof(buf), 0)) generic_error("version", Pike_sp, args, "libesmtp: 'smtp_version' returned 'buffer too small' - " "please report it to [email protected]\n"); pop_n_elems(args); push_string(make_shared_string(buf)); }
/* * add a new domain to the domain list. If it exists, do nothing. */ static mudlib_stats_t *add_stat_entry (const char * str, mudlib_stats_t ** list) { mudlib_stats_t *entry; if ((entry = find_stat_entry(str, *list))) return entry; entry = ALLOCATE(mudlib_stats_t, TAG_MUDLIB_STATS, "add_stat_entry"); entry->name = make_shared_string(str); entry->length = strlen(str); entry->moves = 0; entry->heart_beats = 0; entry->errors = 0; entry->objects = 0; entry->next = NULL; entry->size_array = 0; insert_stat_entry(entry, list); return entry; }
static struct object* dict_lookup(DICT *dict, void *data) { struct svalue *obj, skey; char addr[64]; INFUN(); if (!dict || !data) return NULL; sprintf(addr, "0x%X", (unsigned)data); skey.type = T_STRING; skey.u.string = make_shared_string(addr); obj = low_mapping_lookup(dict->dict, &skey); free_string(skey.u.string); OUTFUN(); return obj->u.object; }
void set_close_callback (int which, svalue_t * cb) { char *s; if (lpc_socks[which].flags & S_CLOSE_FP) { free_funp(lpc_socks[which].close_callback.f); lpc_socks[which].flags &= ~S_CLOSE_FP; } else if ((s = lpc_socks[which].close_callback.s)) free_string(s); if (cb) { if (cb->type == T_FUNCTION) { lpc_socks[which].flags |= S_CLOSE_FP; lpc_socks[which].close_callback.f = cb->u.fp; cb->u.fp->hdr.ref++; } else { lpc_socks[which].close_callback.s = make_shared_string(cb->u.string); } } else lpc_socks[which].close_callback.s = 0; }
void f_traceprefix (void) { char *old = 0; if (command_giver && command_giver->interactive) { old = command_giver->interactive->trace_prefix; if (sp->type & T_STRING) { const char *p = sp->u.string; if (*p == '/') p++; command_giver->interactive->trace_prefix = make_shared_string(p); free_string_svalue(sp); } else command_giver->interactive->trace_prefix = 0; } if (old) { put_malloced_string(add_slash(old)); free_string(old); } else *sp = const0; }
void f_destructed_objects (void) { int i; array_t *ret; object_t *ob; ret = allocate_empty_array(tot_dangling_object); ob = obj_list_dangling; for (i = 0; i < tot_dangling_object; i++) { ret->item[i].type = T_ARRAY; ret->item[i].u.arr = allocate_empty_array(2); ret->item[i].u.arr->item[0].type = T_STRING; ret->item[i].u.arr->item[0].subtype = STRING_SHARED; ret->item[i].u.arr->item[0].u.string = make_shared_string(ob->obname); ret->item[i].u.arr->item[1].type = T_NUMBER; ret->item[i].u.arr->item[1].u.number = ob->ref; ob = ob->next_all; } push_refed_array(ret); }
/* * check permission */ int check_valid_socket (const char * const what, int fd, object_t * owner, const char * const addr, int port) { array_t *info; svalue_t *mret; info = allocate_empty_array(4); info->item[0].type = T_NUMBER; info->item[0].u.number = fd; assign_socket_owner(&info->item[1], owner); info->item[2].type = T_STRING; info->item[2].subtype = STRING_SHARED; info->item[2].u.string = make_shared_string(addr); info->item[3].type = T_NUMBER; info->item[3].u.number = port; push_object(current_object); push_constant_string(what); push_refed_array(info); mret = apply_master_ob(APPLY_VALID_SOCKET, 3); return MASTER_APPROVED(mret); }
static void init_sax(struct object *o) { if (!THIS) return; THIS->ctxt = NULL; THIS->sax = NULL; THIS->filename = NULL; THIS->parsing_method = 0; THIS->callbacks = NULL; THIS->file_obj = NULL; THIS->input_data = NULL; econtent_type = make_shared_string("type"); econtent_ocur = make_shared_string("ocur"); econtent_name = make_shared_string("name"); econtent_prefix = make_shared_string("prefix"); econtent_c1 = make_shared_string("child1"); econtent_c2 = make_shared_string("child2"); }
/* Initialize and start module */ void pike_module_init( void ) { STRS(data) = make_shared_string("data"); STRS(file) = make_shared_string("file"); STRS(method) = make_shared_string("method"); STRS(protocol) = make_shared_string("protocol"); STRS(query) = make_shared_string("query"); STRS(raw_url) = make_shared_string("raw_url"); SVAL(data)->type = T_STRING; SVAL(file)->type = T_STRING; SVAL(method)->type = T_STRING; SVAL(protocol)->type = T_STRING; SVAL(query)->type = T_STRING; SVAL(raw_url)->type = T_STRING; add_function_constant( "parse_headers", f_parse_headers, "function(string:mapping)", 0); add_function_constant( "parse_query_string", f_parse_query_string, "function(string,mapping:void)", OPT_SIDE_EFFECT); add_function_constant( "parse_prestates", f_parse_prestates, "function(string,multiset,multiset:string)", OPT_SIDE_EFFECT); add_function_constant( "get_address", f_get_address, "function(string:string)", 0); add_function_constant( "extension", f_extension, "function(string:string)", 0); add_function_constant( "create_process", f_create_process, "function(array(string),void|mapping(string:mixed):int)", 0); start_new_program(); ADD_STORAGE( buffer ); add_function( "append", f_buf_append, "function(string:int)", OPT_SIDE_EFFECT ); add_function( "create", f_buf_create, "function(mapping,mapping,int|void:void)", 0 ); set_init_callback(alloc_buf_struct); set_exit_callback(free_buf_struct); end_class("ParseHTTP", 0); init_nbio(); }
static void f_create_process( INT32 args ) { struct perishables storage; struct array *cmd = 0; struct mapping *optional = 0; struct svalue *tmp; int e; int stds[3]; int *fds; int num_fds = 3; int wanted_gid=0, wanted_uid=0; int gid_request=0, uid_request=0; char *tmp_cwd = NULL; pid_t pid=-2; extern char **environ; fds = stds; storage.env = NULL; storage.argv = NULL; storage.disabled = 0; storage.fds = NULL; storage.limits = NULL; check_all_args("create_process",args, BIT_ARRAY, BIT_MAPPING | BIT_VOID, 0); switch(args) { default: optional=Pike_sp[1-args].u.mapping; mapping_fix_type_field(optional); if(m_ind_types(optional) & ~BIT_STRING) Pike_error("Bad index type in argument 2 to Caudium.create_process()\n"); case 1: cmd=Pike_sp[-args].u.array; if(cmd->size < 1) Pike_error("Too few elements in argument array.\n"); for(e=0; e<cmd->size; e++) if(ITEM(cmd)[e].type!=T_STRING) Pike_error("Argument is not a string.\n"); array_fix_type_field(cmd); if(cmd->type_field & ~BIT_STRING) Pike_error("Bad argument 1 to Caudium.create_process().\n"); } if (optional) { if ((tmp = simple_mapping_string_lookup(optional, "gid"))) { switch(tmp->type) { case T_INT: wanted_gid = tmp->u.integer; gid_request = 1; break; default: Pike_error("Invalid argument for gid."); break; } } if ((tmp = simple_mapping_string_lookup(optional, "uid"))) { switch(tmp->type) { case T_INT: wanted_uid = tmp->u.integer; uid_request = 1; break; default: Pike_error("Invalid argument for uid."); break; } } if((tmp = simple_mapping_string_lookup( optional, "cwd" )) && tmp->type == T_STRING && !tmp->u.string->size_shift) tmp_cwd = tmp->u.string->str; if((tmp = simple_mapping_string_lookup( optional, "stdin" )) && tmp->type == T_OBJECT) { fds[0] = fd_from_object( tmp->u.object ); if(fds[0] == -1) Pike_error("Invalid stdin file\n"); } if((tmp = simple_mapping_string_lookup( optional, "stdout" )) && tmp->type == T_OBJECT) { fds[1] = fd_from_object( tmp->u.object ); if(fds[1] == -1) Pike_error("Invalid stdout file\n"); } if((tmp = simple_mapping_string_lookup( optional, "stderr" )) && tmp->type == T_OBJECT) { fds[2] = fd_from_object( tmp->u.object ); if(fds[2] == -1) Pike_error("Invalid stderr file\n"); } if((tmp=simple_mapping_string_lookup(optional, "rlimit"))) { struct svalue *tmp2; if(tmp->type != T_MAPPING) Pike_error("Wrong type of argument for the 'rusage' option. " "Should be mapping.\n"); #define ADD_LIMIT(X,Y,Z) internal_add_limit(&storage,X,Y,Z); #ifdef RLIMIT_NPROC if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "nproc"))) ADD_LIMIT( "nproc", RLIMIT_NPROC, tmp2 ); #endif #ifdef RLIMIT_MEMLOCK if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "memlock"))) ADD_LIMIT( "memlock", RLIMIT_MEMLOCK, tmp2 ); #endif #ifdef RLIMIT_RSS if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "rss"))) ADD_LIMIT( "rss", RLIMIT_RSS, tmp2 ); #endif #ifdef RLIMIT_CORE if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "core"))) ADD_LIMIT( "core", RLIMIT_CORE, tmp2 ); #endif #ifdef RLIMIT_CPU if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "cpu"))) ADD_LIMIT( "cpu", RLIMIT_CPU, tmp2 ); #endif #ifdef RLIMIT_DATA if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "data"))) ADD_LIMIT( "data", RLIMIT_DATA, tmp2 ); #endif #ifdef RLIMIT_FSIZE if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "fsize"))) ADD_LIMIT( "fsize", RLIMIT_FSIZE, tmp2 ); #endif #ifdef RLIMIT_NOFILE if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "nofile"))) ADD_LIMIT( "nofile", RLIMIT_NOFILE, tmp2 ); #endif #ifdef RLIMIT_STACK if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "stack"))) ADD_LIMIT( "stack", RLIMIT_STACK, tmp2 ); #endif #ifdef RLIMIT_VMEM if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "map_mem")) ||(tmp2=simple_mapping_string_lookup(tmp->u.mapping, "vmem"))) ADD_LIMIT( "map_mem", RLIMIT_VMEM, tmp2 ); #endif #ifdef RLIMIT_AS if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "as")) ||(tmp2=simple_mapping_string_lookup(tmp->u.mapping, "mem"))) ADD_LIMIT( "mem", RLIMIT_AS, tmp2 ); #endif #undef ADD_LIMIT } } if((tmp=simple_mapping_string_lookup(optional, "env"))) { if(tmp->type == T_MAPPING) { struct mapping *m=tmp->u.mapping; struct array *i,*v; int ptr=0; i=mapping_indices(m); v=mapping_values(m); storage.env=(char **)xalloc((1+m_sizeof(m)) * sizeof(char *)); for(e=0;e<i->size;e++) { if(ITEM(i)[e].type == T_STRING && ITEM(v)[e].type == T_STRING) { check_stack(3); ref_push_string(ITEM(i)[e].u.string); push_string(make_shared_string("=")); ref_push_string(ITEM(v)[e].u.string); f_add(3); storage.env[ptr++]=Pike_sp[-1].u.string->str; } } storage.env[ptr++]=0; free_array(i); free_array(v); } } storage.argv = (char **)xalloc((1 + cmd->size) * sizeof(char *)); for (e = 0; e < cmd->size; e++) storage.argv[e] = ITEM(cmd)[e].u.string->str; storage.argv[e] = 0; th_atfork_prepare(); pid = fork(); if (pid) { th_atfork_parent(); } else { th_atfork_child(); } if (pid == -1) { Pike_error("Caudium.create_process() failed."); } else if (pid) { pop_n_elems(args); push_int(pid); return; } else { if(storage.limits) { struct plimit *l = storage.limits; while(l) { int tmpres = setrlimit( l->resource, &l->rlp ); l = l->next; } } if(storage.env) environ = storage.env; chdir(tmp_cwd); seteuid(0); setegid(0); setgroups(0, NULL); if (gid_request) setgid(wanted_gid); if (uid_request) setuid(wanted_uid); dup2(fds[0], 0); dup2(fds[1], 1); dup2(fds[2], 2); set_close_on_exec(0,0); set_close_on_exec(1,0); set_close_on_exec(2,0); execvp(storage.argv[0],storage.argv); exit(99); } pop_n_elems(args); push_int(0); }
/* This function reads some data from the file cache.. * Called when we want some data to send. */ static INLINE struct pike_string* gimme_some_data(size_t pos) { struct buffer *b; ptrdiff_t len; struct pipe *this = THIS; /* We have a file cache, read from it */ if (this->fd!=-1) { char buffer[READ_BUFFER_SIZE]; if (this->pos<=pos) return NULL; /* no data */ len=this->pos-pos; if (len>READ_BUFFER_SIZE) len=READ_BUFFER_SIZE; THREADS_ALLOW(); fd_lseek(this->fd, pos, SEEK_SET); THREADS_DISALLOW(); do { THREADS_ALLOW(); len = fd_read(this->fd, buffer, len); THREADS_DISALLOW(); if (len < 0) { if (errno != EINTR) { return(NULL); } check_threads_etc(); } } while(len < 0); /* * FIXME: What if len is 0? */ return make_shared_binary_string(buffer,len); } if (pos<this->pos) return make_shared_string("buffer underflow"); /* shit */ /* We want something in the next buffer */ while (this->firstbuffer && pos>=this->pos+this->firstbuffer->s->len) { /* Free the first buffer, and update THIS->pos */ b=this->firstbuffer; this->pos+=b->s->len; this->bytes_in_buffer-=b->s->len; this->firstbuffer=b->next; if (!b->next) this->lastbuffer=NULL; sbuffers-=b->s->len; nbuffers--; free_string(b->s); free((char *)b); /* Wake up first input if it was sleeping and we * have room for more in the buffer. */ if (this->sleeping && this->firstinput && this->bytes_in_buffer<MAX_BYTES_IN_BUFFER) { if (this->firstinput->type == I_BLOCKING_OBJ) { if (!read_some_data()) { this->sleeping = 0; input_finish(); } } else { this->sleeping=0; push_callback(offset_input_read_callback); push_int(0); push_callback(offset_input_close_callback); apply(this->firstinput->u.obj, "set_nonblocking", 3); pop_stack(); } } } while (!this->firstbuffer) { if (this->firstinput) { #if defined(HAVE_MMAP) && defined(HAVE_MUNMAP) if (this->firstinput->type==I_MMAP) { char *src; struct pike_string *tmp; if (pos >= this->firstinput->len + this->pos) /* end of mmap */ { this->pos += this->firstinput->len; input_finish(); continue; } len = this->firstinput->len + this->pos - pos; if (len > READ_BUFFER_SIZE) len=READ_BUFFER_SIZE; tmp = begin_shared_string( len ); src = this->firstinput->u.mmap + pos - this->pos; /* This thread_allow/deny is at the cost of one extra memory copy */ THREADS_ALLOW(); MEMCPY(tmp->str, src, len); THREADS_DISALLOW(); return end_shared_string(tmp); } else #endif if (this->firstinput->type!=I_OBJ) { /* FIXME: What about I_BLOCKING_OBJ? */ input_finish(); /* shouldn't be anything else ... maybe a finished object */ } } return NULL; /* no data */ } if (pos==this->pos) { add_ref(this->firstbuffer->s); return this->firstbuffer->s; } return make_shared_binary_string(this->firstbuffer->s->str+ pos-this->pos, this->firstbuffer->s->len- pos+this->pos); }
static void make_colors(void) { static struct color { int r,g,b; char *name; struct pike_string *pname; } c[]={ #define COLOR(name,R,G,B) \ {R,G,B,name,NULL}, #include "colors.h" #undef COLOR }; int i; const int n=sizeof(c)/sizeof(c[0]); for (i=0; (size_t)i<sizeof(html_color)/sizeof(html_color[0]); i++) html_color[i].pname=make_shared_string(html_color[i].name); for (i=0;i<n;i++) { struct color_struct *cs; push_text(c[i].name); copy_shared_string(c[i].pname,sp[-1].u.string); push_object(clone_object(image_color_program,0)); cs=get_storage(sp[-1].u.object,image_color_program); cs->rgb.r=(COLORTYPE)c[i].r; cs->rgb.g=(COLORTYPE)c[i].g; cs->rgb.b=(COLORTYPE)c[i].b; RGB_TO_RGBL(cs->rgbl,cs->rgb); copy_shared_string(cs->name,c[i].pname); } f_aggregate_mapping(n*2); colors=sp[-1].u.mapping; sp--; dmalloc_touch_svalue(sp); for (i=0;i<n;i++) { push_int(c[i].r); push_int(c[i].g); push_int(c[i].b); f_aggregate(3); } f_aggregate(n); colortable=clone_object(image_colortable_program,1); if (!colortable) Pike_fatal("couldn't create colortable\n"); push_int(12); push_int(12); push_int(12); push_int(1); safe_apply(colortable,"cubicles",4); pop_stack(); for (i=0;i<n;i++) push_string(c[i].pname); f_aggregate(n); colornames=sp[-1].u.array; sp--; dmalloc_touch_svalue(sp); }
static void f_ultraparse( INT32 args ) { FD f = -1; int lines=0, cls, c=0, my_fd=1, tzs=0, state=0, next; unsigned char *char_pointer=0; /* array with offsets for fields in the string buffer */ int buf_points[16]; INT32 v=0, offs0=0, len=0, bytes=0, gotdate=0; INT32 last_hour=0, last_date=0, last_year=0, last_month=0, this_date=0, broken_lines=0, tmpinteger=0, field_position=0; time_t start; unsigned char *read_buf; struct svalue *statfun, *daily, *pagexts=0, *file, *refsval, *log_format; unsigned char *buf; char *field_buf; #ifdef BROKEN_LINE_DEBUG INT32 broken_line_pos=0; unsigned char *broken_line; #endif INT32 *state_list, *save_field_num, *field_endings, num_states; char *notref = 0; INT32 state_pos=0, bufpos=0, i, fieldnum=0; struct pike_string *url_str = 0, *ref_str = 0, *rfc_str = 0, *hst_str = 0, *tmpagent = 0; struct svalue *url_sval; ONERROR unwind_protect; unsigned INT32 hits_per_hour[24]; unsigned INT32 hosts_per_hour[24]; unsigned INT32 pages_per_hour[24]; unsigned INT32 sessions_per_hour[24]; double kb_per_hour[24]; unsigned INT32 session_length[24]; /* struct mapping *unique_per_hour = allocate_mapping(1);*/ struct mapping *hits_per_error = allocate_mapping(10); struct mapping *error_urls = allocate_mapping(10); struct mapping *error_refs = allocate_mapping(10); struct mapping *user_agents = allocate_mapping(10); struct mapping *directories = allocate_mapping(20); struct mapping *referrers = allocate_mapping(1); struct mapping *refsites = allocate_mapping(1); struct mapping *referredto = allocate_mapping(1); struct mapping *pages = allocate_mapping(1); struct mapping *hosts = allocate_mapping(1); struct mapping *hits = allocate_mapping(1); struct mapping *session_start = allocate_mapping(1); struct mapping *session_end = allocate_mapping(1); struct mapping *hits20x = allocate_mapping(300); struct mapping *hits302 = allocate_mapping(2); struct mapping *sites = allocate_mapping(1); struct mapping *domains = allocate_mapping(1); struct mapping *topdomains = allocate_mapping(1); struct mapping *tmpdest = NULL; /* struct mapping *hits30x = allocate_mapping(2);*/ if(args>6 && sp[-1].type == T_INT) { offs0 = sp[-1].u.integer; pop_n_elems(1); --args; } if(args>5 && sp[-1].type == T_STRING) { notref = sp[-1].u.string->str; pop_n_elems(1); --args; } lmu = 0; get_all_args("UltraLog.ultraparse", args, "%*%*%*%*%*", &log_format, &statfun, &daily, &file, &pagexts); if(log_format->type != T_STRING) Pike_error("Bad argument 1 to Ultraparse.ultraparse, expected string.\n"); if(statfun->type != T_FUNCTION) Pike_error("Bad argument 2 to Ultraparse.ultraparse, expected function.\n"); if(daily->type != T_FUNCTION) Pike_error("Bad argument 3 to Ultraparse.ultraparse, expected function.\n"); if(pagexts->type != T_MULTISET) Pike_error("Bad argument 5 to Ultraparse.ultraparse, expected multiset.\n"); if(file->type == T_OBJECT) { f = fd_from_object(file->u.object); if(f == -1) Pike_error("UltraLog.ultraparse: File is not open.\n"); my_fd = 0; } else if(file->type == T_STRING && file->u.string->size_shift == 0) { do { f=fd_open(file->u.string->str, fd_RDONLY, 0); } while(f < 0 && errno == EINTR); if(errno < 0) Pike_error("UltraLog.ultraparse(): Failed to open file for reading (errno=%d).\n", errno); } else Pike_error("Bad argument 4 to UltraLog.ultraparse, expected string or object .\n"); state_list = malloc((log_format->u.string->len +3) * sizeof(INT32)); save_field_num = malloc((log_format->u.string->len +3) * sizeof(INT32)); field_endings = malloc((log_format->u.string->len +3) * sizeof(INT32)); num_states = parse_log_format(log_format->u.string, state_list, field_endings, save_field_num); if(num_states < 1) { free(state_list); free(save_field_num); free(field_endings); Pike_error("UltraLog.ultraparse(): Failed to parse log format.\n"); } fd_lseek(f, offs0, SEEK_SET); read_buf = malloc(READ_BLOCK_SIZE+1); buf = malloc(MAX_LINE_LEN+2); #ifdef BROKEN_LINE_DEBUG broken_line = malloc(MAX_LINE_LEN*10); #endif MEMSET(hits_per_hour, 0, sizeof(hits_per_hour)); MEMSET(hosts_per_hour, 0, sizeof(hosts_per_hour)); MEMSET(session_length, 0, sizeof(session_length)); MEMSET(pages_per_hour, 0, sizeof(pages_per_hour)); MEMSET(sessions_per_hour, 0, sizeof(sessions_per_hour)); MEMSET(kb_per_hour, 0, sizeof(kb_per_hour)); /*url_sval.u.type = TYPE_STRING;*/ BUFSET(0); field_position = bufpos; buf_points[0] = buf_points[1] = buf_points[2] = buf_points[3] = buf_points[4] = buf_points[5] = buf_points[6] = buf_points[7] = buf_points[8] = buf_points[9] = buf_points[10] = buf_points[11] = buf_points[12] = buf_points[13] = buf_points[14] = buf_points[15] = 0; while(1) { /* THREADS_ALLOW();*/ do { len = fd_read(f, read_buf, READ_BLOCK_SIZE); } while(len < 0 && errno == EINTR); /* THREADS_DISALLOW();*/ if(len <= 0) break; /* nothing more to read or error. */ offs0 += len; char_pointer = read_buf+len - 1; while(len--) { c = char_pointer[-len]; cls = char_class[c]; #if 0 fprintf(stdout, "DFA(%d:%d): '%c' (%d) ", state, state_pos, c, (int)c); switch(cls) { case CLS_WSPACE: fprintf(stdout, "CLS_WSPACE\n"); break; case CLS_CRLF: fprintf(stdout, "CLS_CRLF\n"); break; case CLS_TOKEN: fprintf(stdout, "CLS_TOKEN\n"); break; case CLS_DIGIT: fprintf(stdout, "CLS_DIGIT\n"); break; case CLS_QUOTE: fprintf(stdout, "CLS_QUOTE\n"); break; case CLS_LBRACK: fprintf(stdout, "CLS_LBRACK\n"); break; case CLS_RBRACK: fprintf(stdout, "CLS_RBRACK\n"); break; case CLS_SLASH: fprintf(stdout, "CLS_SLASH\n"); break; case CLS_COLON: fprintf(stdout, "CLS_COLON\n"); break; case CLS_HYPHEN: fprintf(stdout, "CLS_HYPHEN/CLS_MINUS\n"); break; case CLS_PLUS: fprintf(stdout, "CLS_PLUS\n"); break; default: fprintf(stdout, "??? %d ???\n", cls); } #endif #ifdef BROKEN_LINE_DEBUG broken_line[broken_line_pos++] = c; #endif if(cls == field_endings[state_pos]) { /* Field is done. Nullify. */ process_field: /* printf("Processing field %d of %d\n", state_pos, num_states);*/ switch(save_field_num[state_pos]) { case DATE: case HOUR: case MINUTE: case UP_SEC: case CODE: /* BUFSET(0);*/ tmpinteger = 0; for(v = field_position; v < bufpos; v++) { if(char_class[buf[v]] == CLS_DIGIT) tmpinteger = tmpinteger*10 + (buf[v]&0xf); else { goto skip; } } BUFPOINT = tmpinteger; break; case YEAR: tmpinteger = 0; for(v = field_position; v < bufpos; v++) { if(char_class[buf[v]] == CLS_DIGIT) tmpinteger = tmpinteger*10 + (buf[v]&0xf); else { goto skip; } } if(tmpinteger < 100) { if(tmpinteger < 60) tmpinteger += 2000; else tmpinteger += 1900; } BUFPOINT = tmpinteger; break; case BYTES: v = field_position; switch(char_class[buf[v++]]) { case CLS_QUESTION: case CLS_HYPHEN: if(v == bufpos) tmpinteger = 0; else { goto skip; } break; case CLS_DIGIT: tmpinteger = (buf[field_position]&0xf); for(; v < bufpos; v++) { if(char_class[buf[v]] == CLS_DIGIT) tmpinteger = tmpinteger*10 + (buf[v]&0xf); else { goto skip; } } /* printf("Digit: %d\n", tmpinteger);*/ break; default: goto skip; } BUFPOINT = tmpinteger; /* bufpos++;*/ break; case MONTH: /* Month */ /* BUFSET(0);*/ /* field_buf = buf + field_positions[state_pos];*/ switch(bufpos - field_position) { case 2: tmpinteger = 0; for(v = field_position; v < bufpos; v++) { if(char_class[buf[v]] == CLS_DIGIT) tmpinteger = tmpinteger*10 + (buf[v]&0xf); else { goto skip; } } break; case 3: switch(((buf[field_position]|0x20)<<16)|((buf[field_position+1]|0x20)<<8)| (buf[field_position+2]|0x20)) { case ('j'<<16)|('a'<<8)|'n': tmpinteger = 1; break; case ('f'<<16)|('e'<<8)|'b': tmpinteger = 2; break; case ('m'<<16)|('a'<<8)|'r': tmpinteger = 3; break; case ('a'<<16)|('p'<<8)|'r': tmpinteger = 4; break; case ('m'<<16)|('a'<<8)|'y': tmpinteger = 5; break; case ('j'<<16)|('u'<<8)|'n': tmpinteger = 6; break; case ('j'<<16)|('u'<<8)|'l': tmpinteger = 7; break; case ('a'<<16)|('u'<<8)|'g': tmpinteger = 8; break; case ('s'<<16)|('e'<<8)|'p': tmpinteger = 9; break; case ('o'<<16)|('c'<<8)|'t': tmpinteger = 10; break; case ('n'<<16)|('o'<<8)|'v': tmpinteger = 11; break; case ('d'<<16)|('e'<<8)|'c': tmpinteger = 12; break; } break; default: goto skip; } /*printf("Month: %0d\n", mm);*/ if(tmpinteger < 1 || tmpinteger > 12) goto skip; /* Broken Month */ BUFPOINT = tmpinteger; /* bufpos++;*/ break; case ADDR: case REFER: case AGENT: case TZ: case METHOD: case URL: case RFC: case PROTO: BUFSET(0); SETPOINT(); /* printf("Field %d, pos %d, %s\n", save_field_num[state_pos],BUFPOINT,*/ /* buf + BUFPOINT); */ break; } state_pos++; field_position = bufpos; if(cls != CLS_CRLF) continue; } else if(cls != CLS_CRLF) { BUFSET(c); continue; } else { /* printf("Processing last field (%d).\n", state_pos);*/ goto process_field; /* End of line - process what we got */ } /* printf("%d %d\n", state_pos, num_states);*/ /* buf_points[8] = buf_points[9] = buf_points[10] = buf_points[11] = buf;*/ /* buf_points[12] = buf_points[13] = buf_points[14] = buf_points[15] = buf;*/ #if 0 if(!((lines+broken_lines)%100000)) { push_int(lines+broken_lines); push_int((int)((float)offs0/1024.0/1024.0)); apply_svalue(statfun, 2); pop_stack(); /*printf("%5dk lines, %5d MB\n", lines/1000, (int)((float)offs0/1024.0/1024.0));*/ } #endif if(state_pos < num_states) { #ifdef BROKEN_LINE_DEBUG broken_line[broken_line_pos] = 0; printf("too few states (pos=%d): %s\n", state_pos, broken_line); #endif broken_lines++; goto ok; } #define yy buf_points[YEAR] #define mm buf_points[MONTH] #define dd buf_points[DATE] #define h buf_points[HOUR] #define m buf_points[MINUTE] #define s buf_points[UP_SEC] #define v buf_points[CODE] #define bytes buf_points[BYTES] this_date = (yy*10000) + (mm*100) + dd; if(!this_date) { broken_lines++; goto ok; } #if 1 if(!last_date) { /* First loop w/o a value.*/ last_date = this_date; last_hour = h; } else { if(last_hour != h || last_date != this_date) { pages_per_hour[last_hour] += hourly_page_hits(hits20x, pages, hits, pagexts->u.multiset, 200); /* pages_per_hour[last_hour] +=*/ /* hourly_page_hits(hits304, pages, hits, pagexts->u.multiset, 300);*/ /* printf("%5d %5d for %d %02d:00\n",*/ /* pages_per_hour[last_hour], hits_per_hour[last_hour],*/ /*last_date, last_hour);*/ if(m_sizeof(session_start)) { summarize_sessions(last_hour, sessions_per_hour, session_length, session_start, session_end); free_mapping(session_start); free_mapping(session_end); session_start = allocate_mapping(1); session_end = allocate_mapping(1); } hosts_per_hour[last_hour] += m_sizeof(sites); do_map_addition(hosts, sites); free_mapping(sites); sites = allocate_mapping(100); last_hour = h; free_mapping(hits20x); /* Reset this one */ /* free_mapping(hits304); Reset this one */ /* hits304 = allocate_mapping(2);*/ hits20x = allocate_mapping(2); } #if 1 if(last_date != this_date) { /* printf("%d %d\n", last_date, this_date);*/ tmpdest = allocate_mapping(1); summarize_refsites(refsites, referrers, tmpdest); free_mapping(referrers); referrers = tmpdest; tmpdest = allocate_mapping(1); clean_refto(referredto, tmpdest, pagexts->u.multiset); free_mapping(referredto); referredto = tmpdest; summarize_directories(directories, pages); summarize_directories(directories, hits); tmpdest = allocate_mapping(1); http_decode_mapping(user_agents, tmpdest); free_mapping(user_agents); user_agents = tmpdest; tmpdest = allocate_mapping(1); summarize_hosts(hosts, domains, topdomains, tmpdest); free_mapping(hosts); hosts = tmpdest; #if 1 push_int(last_date / 10000); push_int((last_date % 10000)/100); push_int((last_date % 10000)%100); push_mapping(pages); push_mapping(hits); push_mapping(hits302); push_mapping(hits_per_error); push_mapping(error_urls); push_mapping(error_refs); push_mapping(referredto); push_mapping(refsites); push_mapping(referrers); push_mapping(directories); push_mapping(user_agents); push_mapping(hosts); push_mapping(domains); push_mapping(topdomains); for(i = 0; i < 24; i++) { push_int(sessions_per_hour[i]); } f_aggregate(24); for(i = 0; i < 24; i++) { push_int(hits_per_hour[i]); hits_per_hour[i] = 0; } f_aggregate(24); for(i = 0; i < 24; i++) { push_int(pages_per_hour[i]); pages_per_hour[i] = 0; } f_aggregate(24); for(i = 0; i < 24; i++) { /* KB per hour.*/ push_float(kb_per_hour[i]); kb_per_hour[i] = 0.0; } f_aggregate(24); for(i = 0; i < 24; i++) { push_float(sessions_per_hour[i] ? ((float)session_length[i] / (float)sessions_per_hour[i]) / 60.0 : 0.0); sessions_per_hour[i] = 0; session_length[i] = 0; } f_aggregate(24); for(i = 0; i < 24; i++) { push_int(hosts_per_hour[i]); hosts_per_hour[i] = 0; } f_aggregate(24); apply_svalue(daily, 23); pop_stack(); #else free_mapping(error_refs); free_mapping(referredto); free_mapping(refsites); free_mapping(directories); free_mapping(error_urls); free_mapping(hits); free_mapping(hits_per_error); free_mapping(pages); free_mapping(hosts); free_mapping(domains); free_mapping(topdomains); free_mapping(referrers); free_mapping(hits302); #endif user_agents = allocate_mapping(10); hits302 = allocate_mapping(1); hits_per_error = allocate_mapping(10); error_urls = allocate_mapping(10); error_refs = allocate_mapping(10); directories = allocate_mapping(20); referrers = allocate_mapping(1); referredto = allocate_mapping(1); refsites = allocate_mapping(1); pages = allocate_mapping(1); hits = allocate_mapping(1); sites = allocate_mapping(1); hosts = allocate_mapping(1); domains = allocate_mapping(1); topdomains = allocate_mapping(1); last_date = this_date; } #endif } #endif #if 1 process_session(buf+buf_points[ADDR], h*3600+m*60+s, h, sessions_per_hour, session_length, session_start, session_end, sites); url_str = make_shared_binary_string((char *)(buf + buf_points[URL]), strlen((char *)(buf + buf_points[URL]))); #if 1 switch(v) { /* Do error-code specific logging. Error urls that are specially treated do not include auth required, service unavailable etc. They are only included in the return code summary. */ case 200: case 201: case 202: case 203: case 204: case 205: case 206: case 207: case 304: mapaddstr(hits20x, url_str); DO_REFERRER(); break; case 300: case 301: case 302: case 303: case 305: mapaddstr(hits302, url_str); DO_REFERRER(); break; case 400: case 404: case 405: case 406: case 408: case 409: case 410: case 411: case 412: case 413: case 414: case 415: case 416: case 500: case 501: DO_ERREF(); map2addint(error_urls, v, url_str); break; } /*rfc_str = http_decode_string(buf + buf_points[RFC]);*/ /*hst_str = make_shared_binary_string(buf, strlen(buf));*/ #endif free_string(url_str); mapaddint(hits_per_error, v); kb_per_hour[h] += (float)bytes / 1024.0; hits_per_hour[h]++; /*#endif*/ if(strlen((char *)(buf + buf_points[AGENT]))>1) { /* Got User Agent */ tmpagent = make_shared_string((char *)(buf + buf_points[AGENT])); mapaddstr(user_agents, tmpagent); free_string(tmpagent); } #endif lines++; #if 0 printf("%s %s %s\n%s %s %s\n%04d-%02d-%02d %02d:%02d:%02d \n%d %d\n", buf + buf_points[ADDR], buf + buf_points[REFER], buf + buf_points[ RFC ], buf + buf_points[METHOD], buf + buf_points[ URL ], buf + buf_points[PROTO], yy, mm, dd, h, m, s, v, bytes); /* if(lines > 10) exit(0);*/ #endif ok: gotdate = /* v = bytes =h = m = s = tz = tzs = dd = mm = yy = */ buf_points[0] = buf_points[1] = buf_points[2] = buf_points[3] = buf_points[4] = buf_points[5] = buf_points[6] = buf_points[7] = /*buf_points[8] = buf_points[9] = buf_points[10] =*/ buf_points[11] = buf_points[12] = buf_points[13] = buf_points[14] = buf_points[15] = bufpos = state_pos = 0; field_position = 1; #ifdef BROKEN_LINE_DEBUG broken_line_pos = 0; #endif BUFSET(0); } } cleanup: free(save_field_num); free(state_list); free(field_endings); free(buf); push_int(lines); push_int((int)((float)offs0 / 1024.0/1024.0)); push_int(1); apply_svalue(statfun, 3); pop_stack(); free(read_buf); #ifdef BROKEN_LINE_DEBUG free(broken_line); #endif if(my_fd) /* If my_fd == 0, the second argument was an object and thus we don't * want to free it. */ fd_close(f); /* push_int(offs0); */ /* printf("Done: %d %d %d ", yy, mm, dd);*/ if(yy && mm && dd) { /* printf("\nLast Summary for %d-%02d-%02d %02d:%02d\n", yy, mm, dd, h, m);*/ pages_per_hour[last_hour] += hourly_page_hits(hits20x, pages, hits, pagexts->u.multiset, 200); if(m_sizeof(session_start)) { summarize_sessions(last_hour, sessions_per_hour, session_length, session_start, session_end); } hosts_per_hour[last_hour] += m_sizeof(sites); do_map_addition(hosts, sites); free_mapping(sites); tmpdest = allocate_mapping(1); summarize_refsites(refsites, referrers, tmpdest); free_mapping(referrers); referrers = tmpdest; summarize_directories(directories, pages); summarize_directories(directories, hits); tmpdest = allocate_mapping(1); clean_refto(referredto, tmpdest, pagexts->u.multiset); free_mapping(referredto); referredto = tmpdest; tmpdest = allocate_mapping(1); http_decode_mapping(user_agents, tmpdest); free_mapping(user_agents); user_agents = tmpdest; tmpdest = allocate_mapping(1); summarize_hosts(hosts, domains, topdomains, tmpdest); free_mapping(hosts); hosts = tmpdest; push_int(yy); push_int(mm); push_int(dd); push_mapping(pages); push_mapping(hits); push_mapping(hits302); push_mapping(hits_per_error); push_mapping(error_urls); push_mapping(error_refs); push_mapping(referredto); push_mapping(refsites); push_mapping(referrers); push_mapping(directories); push_mapping(user_agents); push_mapping(hosts); push_mapping(domains); push_mapping(topdomains); for(i = 0; i < 24; i++) { push_int(sessions_per_hour[i]); } f_aggregate(24); for(i = 0; i < 24; i++) { push_int(hits_per_hour[i]); } f_aggregate(24); for(i = 0; i < 24; i++) { push_int(pages_per_hour[i]); } f_aggregate(24); for(i = 0; i < 24; i++) { push_float(kb_per_hour[i]); } f_aggregate(24); for(i = 0; i < 24; i++) { push_float(sessions_per_hour[i] ? ((float)session_length[i] / (float)sessions_per_hour[i]) / 60.0 : 0.0); } f_aggregate(24); for(i = 0; i < 24; i++) { push_int(hosts_per_hour[i]); hosts_per_hour[i] = 0; } f_aggregate(24); apply_svalue(daily, 23); pop_stack(); } else { free_mapping(error_refs); free_mapping(referredto); free_mapping(refsites); free_mapping(directories); free_mapping(error_urls); free_mapping(hits); free_mapping(hits_per_error); free_mapping(pages); free_mapping(referrers); free_mapping(hits302); free_mapping(user_agents); free_mapping(hosts); free_mapping(domains); free_mapping(topdomains); } free_mapping(hits20x); free_mapping(session_start); free_mapping(session_end); /* free_mapping(hits30x); */ printf("\nTotal lines: %d, broken lines: %d, mapping lookups: %d\n\n", lines, broken_lines, lmu); fflush(stdout); pop_n_elems(args); push_int(offs0); return; skip: broken_lines++; while(1) { while(len--) { #ifdef BROKEN_LINE_DEBUG broken_line[broken_line_pos] = char_pointer[-len]; #endif if(char_class[char_pointer[-len]] == CLS_CRLF) { #ifdef BROKEN_LINE_DEBUG broken_line[broken_line_pos] = 0; printf("Broken Line (pos=%d): %s\n", state_pos, broken_line); #endif goto ok; } } do { len = fd_read(f, read_buf, READ_BLOCK_SIZE); } while(len < 0 && errno == EINTR); if(len <= 0) break; /* nothing more to read. */ offs0 += len; char_pointer = read_buf+len - 1; } goto cleanup; }
int main (int argc, char ** argv) { time_t tm; int i, new_mudlib = 0, got_defaults = 0; char *p; char version_buf[80]; #if 0 int dtablesize; #endif error_context_t econ; #ifdef PROTO_TZSET void tzset(); #endif #ifdef INCL_LOCALE_H setlocale(LC_ALL, "C"); #endif #if !defined(__SASC) && (defined(AMITCP) || defined(AS225)) amiga_sockinit(); atexit(amiga_sockexit); #endif #ifdef WRAPPEDMALLOC wrappedmalloc_init(); #endif /* WRAPPEDMALLOC */ #ifdef DEBUGMALLOC MDinit(); #endif #if (defined(PROFILING) && !defined(PROFILE_ON) && defined(HAS_MONCONTROL)) moncontrol(0); #endif #ifdef USE_TZSET tzset(); #endif boot_time = get_current_time(); const0.type = T_NUMBER; const0.u.number = 0; const1.type = T_NUMBER; const1.u.number = 1; /* const0u used by undefinedp() */ const0u.type = T_NUMBER; const0u.subtype = T_UNDEFINED; const0u.u.number = 0; //fake_prog.program_size = 0; //0 anyway /* * Check that the definition of EXTRACT_UCHAR() is correct. */ p = (char *) &i; *p = -10; if (EXTRACT_UCHAR(p) != 0x100 - 10) { fprintf(stderr, "Bad definition of EXTRACT_UCHAR() in interpret.h.\n"); exit(-1); } /* * An added test: can we do EXTRACT_UCHAR(x++)? * (read_number, etc uses it) */ p = (char *) &i; (void) EXTRACT_UCHAR(p++); if ((p - (char *) &i) != 1) { fprintf(stderr, "EXTRACT_UCHAR() in interpret.h evaluates its argument more than once.\n"); exit(-1); } /* * Check the living hash table size */ if (CFG_LIVING_HASH_SIZE != 4 && CFG_LIVING_HASH_SIZE != 16 && CFG_LIVING_HASH_SIZE != 64 && CFG_LIVING_HASH_SIZE != 256 && CFG_LIVING_HASH_SIZE != 1024 && CFG_LIVING_HASH_SIZE != 4096) { fprintf(stderr, "CFG_LIVING_HASH_SIZE in options.h must be one of 4, 16, 64, 256, 1024, 4096, ...\n"); exit(-1); } #ifdef RAND srand(get_current_time()); #else # ifdef DRAND48 srand48(get_current_time()); # else # ifdef RANDOM srandom(get_current_time()); # else fprintf(stderr, "Warning: no random number generator specified!\n"); # endif # endif #endif current_time = get_current_time(); /* * Initialize the microsecond clock. */ init_usec_clock(); /* read in the configuration file */ got_defaults = 0; for (i = 1; (i < argc) && !got_defaults; i++) { if (argv[i][0] != '-') { set_defaults(argv[i]); got_defaults = 1; } } get_version(version_buf); if (!got_defaults) { fprintf(stderr, "%s for %s.\n", version_buf, ARCH); fprintf(stderr, "You must specify the configuration filename as an argument.\n"); exit(-1); } printf("Initializing internal tables....\n"); init_strings(); /* in stralloc.c */ init_otable(); /* in otable.c */ init_identifiers(); /* in lex.c */ init_locals(); /* in compiler.c */ /* * If our estimate is larger than FD_SETSIZE, then we need more file * descriptors than the operating system can handle. This is a problem * that can be resolved by decreasing MAX_USERS, MAX_EFUN_SOCKS, or both. * * Unfortunately, since neither MAX_USERS or MAX_EFUN_SOCKS exist any more, * we have no clue how many we will need. This code really should be * moved to places where ENFILE/EMFILE is returned. */ #if 0 if (dtablesize > FD_SETSIZE) { fprintf(stderr, "Warning: File descriptor requirements exceed system capacity!\n"); fprintf(stderr, " Configuration exceeds system capacity by %d descriptor(s).\n", dtablesize - FD_SETSIZE); } #ifdef HAS_SETDTABLESIZE /* * If the operating system supports setdtablesize() then we can request * the number of file descriptors we really need. First check to see if * wee already have enough. If so dont bother the OS. If not, attempt to * allocate the number we estimated above. There are system imposed * limits on file descriptors, so we may not get as many as we asked for. * Check to make sure we get enough. */ if (getdtablesize() < dtablesize) if (setdtablesize(dtablesize) < dtablesize) { fprintf(stderr, "Warning: Could not allocate enough file descriptors!\n"); fprintf(stderr, " setdtablesize() could not allocate %d descriptor(s).\n", getdtablesize() - dtablesize); } /* * Just be polite and tell the administrator how many he has. */ fprintf(stderr, "%d file descriptors were allocated, (%d were requested).\n", getdtablesize(), dtablesize); #endif #endif time_to_clean_up = TIME_TO_CLEAN_UP; max_cost = MAX_COST; reserved_size = RESERVED_SIZE; max_array_size = MAX_ARRAY_SIZE; if(max_array_size > 65535){ fprintf(stderr, "Maximum array size can not exceed 65535"); max_array_size = 65535; } max_buffer_size = MAX_BUFFER_SIZE; max_string_length = MAX_STRING_LENGTH; mud_lib = (char *) MUD_LIB; set_inc_list(INCLUDE_DIRS); if (reserved_size > 0) reserved_area = (char *) DMALLOC(reserved_size, TAG_RESERVED, "main.c: reserved_area"); for (i = 0; i < sizeof consts / sizeof consts[0]; i++) consts[i] = exp(-i / 900.0); reset_machine(1); /* * The flags are parsed twice ! The first time, we only search for the -m * flag, which specifies another mudlib, and the D-flags, so that they * will be available when compiling master.c. */ for (i = 1; i < argc; i++) { if (argv[i][0] != '-') continue; switch (argv[i][1]) { case 'D': if (argv[i][2]) { lpc_predef_t *tmp = ALLOCATE(lpc_predef_t, TAG_PREDEFINES, "predef"); tmp->flag = argv[i] + 2; tmp->next = lpc_predefs; lpc_predefs = tmp; continue; } fprintf(stderr, "Illegal flag syntax: %s\n", argv[i]); exit(-1); case 'N': no_ip_demon++; continue; #ifdef HAS_CONSOLE case 'C': has_console = 1; continue; #endif #ifdef YYDEBUG case 'y': yydebug = 1; continue; #endif /* YYDEBUG */ case 'm': mud_lib = alloc_cstring(argv[i] + 2, "mudlib dir"); if (chdir(mud_lib) == -1) { fprintf(stderr, "Bad mudlib directory: %s\n", mud_lib); exit(-1); } new_mudlib = 1; break; } } if (!new_mudlib && chdir(mud_lib) == -1) { fprintf(stderr, "Bad mudlib directory: %s\n", mud_lib); exit(-1); } time(&tm); debug_message("----------------------------------------------------------------------------\n%s (%s) starting up on %s - %s\n\n", MUD_NAME, version_buf, ARCH, ctime(&tm)); add_predefines(); #ifdef WIN32 _tzset(); #endif #ifndef NO_IP_DEMON if (!no_ip_demon && ADDR_SERVER_IP) init_addr_server(ADDR_SERVER_IP, ADDR_SERVER_PORT); #endif /* NO_IP_DEMON */ set_eval(max_cost); save_context(&econ); if (SETJMP(econ.context)) { debug_message("The simul_efun (%s) and master (%s) objects must be loadable.\n", SIMUL_EFUN, MASTER_FILE); exit(-1); } else { init_simul_efun(SIMUL_EFUN); init_master(); } pop_context(&econ); for (i = 1; i < argc; i++) { if (argv[i][0] != '-') { continue; } else { /* * Look at flags. -m and -o has already been tested. */ switch (argv[i][1]) { case 'D': case 'N': case 'm': case 'y': case 'C': continue; case 'f': save_context(&econ); if (SETJMP(econ.context)) { debug_message("Error while calling master::flag(\"%s\"), aborting ...\n", argv[i] + 2); exit(-1); } push_constant_string(argv[i] + 2); apply_master_ob(APPLY_FLAG, 1); if (MudOS_is_being_shut_down) { debug_message("Shutdown by master object.\n"); exit(0); } pop_context(&econ); continue; case 'e': e_flag++; continue; case 'p': external_port[0].port = atoi(argv[i] + 2); continue; case 'd': #ifdef DEBUG_MACRO if (argv[i][2]) debug_level_set(&argv[i][2]); else debug_level |= DBG_d_flag; #else debug_message("Driver must be compiled with DEBUG_MACRO on to use -d.\n"); #endif break; case 'c': comp_flag++; continue; case 't': t_flag++; continue; default: debug_message("Unknown flag: %s\n", argv[i]); exit(-1); } } } if (MudOS_is_being_shut_down) exit(1); if (*(DEFAULT_FAIL_MESSAGE)) { char buf[8192]; strcpy(buf, DEFAULT_FAIL_MESSAGE); strcat(buf, "\n"); default_fail_message = make_shared_string(buf); } else default_fail_message = "What?\n"; #ifdef PACKAGE_MUDLIB_STATS restore_stat_files(); #endif preload_objects(e_flag); #ifdef SIGFPE signal(SIGFPE, sig_fpe); #endif #ifdef TRAP_CRASHES #ifdef SIGUSR1 signal(SIGUSR1, sig_usr1); #endif #ifdef SIGUSR2 signal(SIGUSR2, sig_usr2); #endif signal(SIGTERM, sig_term); signal(SIGINT, sig_int); #ifndef DEBUG #if defined(SIGABRT) signal(SIGABRT, sig_abrt); #endif #ifdef SIGIOT signal(SIGIOT, sig_iot); #endif #ifdef SIGHUP signal(SIGHUP, sig_hup); #endif #ifdef SIGBUS signal(SIGBUS, sig_bus); #endif signal(SIGSEGV, sig_segv); signal(SIGILL, sig_ill); #endif /* DEBUG */ #endif #ifndef WIN32 #ifdef USE_BSD_SIGNALS signal(SIGCHLD, sig_cld); #else signal(SIGCLD, sig_cld); #endif #endif #ifdef HAS_CONSOLE if(has_console >= 0) signal(SIGTTIN, sig_ttin); signal(SIGTTOU, SIG_IGN); #endif backend(); return 0; }
INLINE void bson_to_mapping P2(const char *, data, svalue_t *, v){ int id; int oi; int mask; int size; int count = 0; const char *key_c; bson_iterator i; mapping_t *m; svalue_t key, value; mapping_node_t **a, *elt, *elt2; size = sizeof_bson(data); if (!size) { v->type = T_MAPPING; v->u.map = allocate_mapping(0); return; } m = allocate_mapping(size); a = m->table; mask = m->table_size; bson_iterator_from_buffer( &i, data ); while(bson_iterator_next( &i )){ key_c = bson_iterator_key( &i ); key.u.string = make_shared_string(key_c); key.type = T_STRING; key.subtype = STRING_SHARED; bson_to_v(&i,&value); oi = MAP_POINTER_HASH(key.u.number); id = oi & mask; if ((elt2 = elt = a[id])) { do { /* This should never happen, but don't bail on it */ if (msameval(&key, elt->values)) { free_svalue(&key, "bson_to_map: duplicate key"); free_svalue(elt->values+1, "bson_to_map: replaced value"); *(elt->values+1) = value; break; } } while ((elt = elt->next)); if (elt) continue; } else if (!(--m->unfilled)) { if (growMap(m)) { a = m->table; if (oi & ++mask) elt2 = a[id |= mask]; mask <<= 1; mask--; } else { add_map_stats(m, count); free_mapping(m); free_svalue(&key, "bson_to_map: out of memory"); free_svalue(&value, "bson_to_map: out of memory"); error("Out of memory\n"); } } if (++count > MAX_MAPPING_SIZE) { add_map_stats(m, count -1); free_mapping(m); free_svalue(&key, "bson_to_map: mapping too large"); free_svalue(&value, "bson_to_map: mapping too large"); mapping_too_large(); } elt = new_map_node(); *elt->values = key; *(elt->values + 1) = value; (a[id] = elt)->next = elt2; } add_map_stats(m, count); v->type = T_MAPPING; v->u.map = m; }
void create_shared_string_tests() { BOOST_CHECK_EQUAL( make_shared_string( "hello" )->c_str(), "hello" ); }
/* * Parse the given string and fill the passed multisets with, * respectively, "normal" and "internal" prestates. Note that the * latter is filled only if the FIRST prestate is "internal" and in * such case the former has just one member - "internal". * Returns the passed url without the prestate part. */ static void f_parse_prestates( INT32 args ) { struct pike_string *url; struct multiset *prestate; struct multiset *internal; struct svalue ind; char *tmp; int prestate_end = -1; int done_first = 0, i; int last_start; ind.type = T_STRING; get_all_args("Caudium.parse_prestates", args, "%S%M%M", &url, &prestate, &internal); if (url->len < 5 || url->str[1] != '(') { /* must have at least '/(#)/ */ pop_n_elems(args-1); /* Leave URL on the stack == return it */ return; } tmp = &url->str[3]; while (tmp && *tmp) { if (*tmp == '/' && *(tmp - 1) == ')') { prestate_end = tmp - url->str; break; } tmp++; } if (prestate_end < 0) { pop_n_elems(args-1); /* Leave URL on the stack == return it */ return; /* not a prestate */ } /* * Determine which prestate we should fill. */ last_start = 2; for(i = 2; i <= prestate_end; i++) { if (url->str[i] == ',' || url->str[i] == ')') { int len = i - last_start; switch(done_first) { case 0: if (!MEMCMP(&url->str[last_start], "internal", len)) { done_first = -1; ind.u.string = make_shared_string("internal"); } else { done_first = 1; ind.u.string = make_shared_binary_string(&url->str[last_start], len); } multiset_insert(prestate, &ind); break; case -1: /* internal */ ind.u.string = make_shared_binary_string(&url->str[last_start], len); multiset_insert(internal, &ind); break; default: /* prestate */ ind.u.string = make_shared_binary_string(&url->str[last_start], len); multiset_insert(prestate, &ind); break; } free_svalue(&ind); last_start = i + 1; } } pop_n_elems(args); push_string(make_shared_string(url->str + prestate_end)); }
static void f_buf_append( INT32 args ) { struct pike_string *str; struct svalue skey, sval; /* header, value */ int slash_n = 0, cnt, num; unsigned char *pp,*ep; struct svalue *tmp; int os=0, i, j=0, l, qmark = -1; unsigned char *in, *query; if( Pike_sp[-1].type != T_STRING ) Pike_error("Wrong type of argument to append()\n"); str = Pike_sp[-1].u.string; if( str->len >= BUF->free ) { pop_n_elems(args); push_int(413); /* Request Entity Too Large */ return; } MEMCPY( BUF->pos, str->str, str->len ); for( ep = (BUF->pos + str->len), pp = MAX(BUF->data, BUF->pos-3); pp < ep && slash_n < 2; pp++ ) if( *pp == '\n' ) slash_n++; else if( *pp != '\r' ) slash_n=0; BUF->free -= str->len; BUF->pos += str->len; BUF->pos[0] = 0; pop_n_elems( args ); if( slash_n != 2 ) { /* need more data */ push_int( 0 ); return; } skey.type = sval.type = T_STRING; sval.u.string = make_shared_binary_string( (char *)pp, BUF->pos - pp); mapping_insert(BUF->other, SVAL(data), &sval); /* data */ free_string(sval.u.string); in = BUF->data; l = pp - BUF->data; /* find method */ for( i = 0; i < l; i++ ) { if( in[i] == ' ' ) break; else if(in[i] == '\n') { push_int( 400 ); /* Bad Request */ return; } } sval.u.string = make_shared_binary_string((char *)in, i); mapping_insert(BUF->other, SVAL(method), &sval); free_string(sval.u.string); i++; in += i; l -= i; /* find file */ for( i = 0; i < l; i++ ) { if(in[i] == ' ') { break; } else if(in[i] == '\n') { push_int( 400 ); /* Bad Request */ return; } } sval.u.string = make_shared_binary_string((char *)in, i); mapping_insert(BUF->other, SVAL(raw_url), &sval); free_string(sval.u.string); /* Decode file part and return pointer to query, if any */ query = char_decode_url(in, i); /* Decoded, query-less file up to the first \0 */ sval.u.string = make_shared_string((char *)in); mapping_insert(BUF->other, SVAL(file), &sval); free_string(sval.u.string); if(query != NULL) { /* Store the query string */ sval.u.string = make_shared_binary_string((char *)query, i - (query-in)); /* Also up to first null */ mapping_insert(BUF->other, SVAL(query), &sval); free_string(sval.u.string); } i++; in += i; l -= i; /* find protocol */ for( i = 0; i < l; i++ ) { if( in[i] == '\n' ) break; else if(in[i] == ' ') { push_int( 400 ); /* Bad Request */ return; } } if( in[i-1] != '\r' ) i++; sval.u.string = make_shared_binary_string((char *)in, i-1); mapping_insert(BUF->other, SVAL(protocol), &sval); free_string(sval.u.string); in += i; l -= i; if( *in == '\n' ) (in++),(l--); for(i = 0; i < l; i++) { if(in[i] >= 'A' && in[i] <= 'Z') in[i] |= 32; /* Lowercasing the header */ else if( in[i] == ':' ) { /* in[os..i-1] == the header */ skey.u.string = make_shared_binary_string((char*)in+os, i - os); os = i+1; while(in[os]==' ') os++; /* Remove initial spaces */ for(j=os;j<l;j++) if( in[j] == '\n' || in[j]=='\r') break; if((tmp = low_mapping_lookup(BUF->headers, &skey)) && tmp->type == T_STRING) { int len = j - os + 1; int len2 = len +tmp->u.string->len; sval.u.string = begin_shared_string(len2); MEMCPY(sval.u.string->str, tmp->u.string->str, tmp->u.string->len); sval.u.string->str[tmp->u.string->len] = ','; MEMCPY(sval.u.string->str + tmp->u.string->len + 1, (char*)in + os, len); sval.u.string = end_shared_string(sval.u.string); } else { sval.u.string = make_shared_binary_string((char*)in + os, j - os); } mapping_insert(BUF->headers, &skey, &sval); if( in[j+1] == '\n' ) j++; os = j+1; i = j; free_string(sval.u.string); free_string(skey.u.string); } } push_int(1); }