static handler_t mod_status_handler(server *srv, connection *con, void *p_d) { inform_proxy1_arrival(); // Communicating arrival of a request to Proxy1 (BTP) //For verifying if token is authentic //if(verify_token((con->uri.query)->ptr) == 0) // return HANDLER_ERROR; //modified if(verify_token((con->uri.query)->ptr) == 0) { con->http_status = 404; con->file_finished = 1; return HANDLER_FINISHED; } gettimeofday(&(con->tv_temp),NULL); con->start_time = ((con->tv_temp).tv_sec)*1000000 + ((con->tv_temp).tv_usec); plugin_data *p = p_d; mod_status_patch_connection(srv, con, p); if (!buffer_is_empty(p->conf.status_url) && buffer_is_equal(p->conf.status_url, con->uri.path)) { return mod_status_handle_server_status(srv, con, p_d); } else if (!buffer_is_empty(p->conf.config_url) && buffer_is_equal(p->conf.config_url, con->uri.path)) { return mod_status_handle_server_config(srv, con, p_d); } else if (!buffer_is_empty(p->conf.statistics_url) && buffer_is_equal(p->conf.statistics_url, con->uri.path)) { return mod_status_handle_server_statistics(srv, con, p_d); } return HANDLER_GO_ON; }
static int proxy_create_env(server *srv, handler_ctx *hctx) { size_t i; connection *con = hctx->remote_conn; buffer *b; /* build header */ b = buffer_init(); /* request line */ buffer_copy_string(b, get_http_method_name(con->request.http_method)); buffer_append_string_len(b, CONST_STR_LEN(" ")); buffer_append_string_buffer(b, con->request.uri); buffer_append_string_len(b, CONST_STR_LEN(" HTTP/1.0\r\n")); proxy_append_header(con, "X-Forwarded-For", (char *)inet_ntop_cache_get_ip(srv, &(con->dst_addr))); /* http_host is NOT is just a pointer to a buffer * which is NULL if it is not set */ if (!buffer_string_is_empty(con->request.http_host)) { proxy_set_header(con, "X-Host", con->request.http_host->ptr); } proxy_set_header(con, "X-Forwarded-Proto", con->uri.scheme->ptr); /* request header */ for (i = 0; i < con->request.headers->used; i++) { data_string *ds; ds = (data_string *)con->request.headers->data[i]; if (!buffer_is_empty(ds->value) && !buffer_is_empty(ds->key)) { if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue; if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Proxy-Connection"))) continue; buffer_append_string_buffer(b, ds->key); buffer_append_string_len(b, CONST_STR_LEN(": ")); buffer_append_string_buffer(b, ds->value); buffer_append_string_len(b, CONST_STR_LEN("\r\n")); } } buffer_append_string_len(b, CONST_STR_LEN("\r\n")); hctx->wb->bytes_in += buffer_string_length(b); chunkqueue_append_buffer(hctx->wb, b); buffer_free(b); /* body */ if (con->request.content_length) { chunkqueue *req_cq = con->request_content_queue; chunkqueue_steal(hctx->wb, req_cq, req_cq->bytes_in); } return 0; }
int log_error_open(server *srv) { #ifdef HAVE_SYSLOG_H /* perhaps someone wants to use syslog() */ openlog("lighttpd", LOG_CONS | LOG_PID, LOG_DAEMON); #endif srv->errorlog_mode = ERRORLOG_FD; srv->errorlog_fd = STDERR_FILENO; if (srv->srvconf.errorlog_use_syslog) { srv->errorlog_mode = ERRORLOG_SYSLOG; } else if (!buffer_is_empty(srv->srvconf.errorlog_file)) { const char *logfile = srv->srvconf.errorlog_file->ptr; if (-1 == (srv->errorlog_fd = open_logfile_or_pipe(srv, logfile))) { return -1; } srv->errorlog_mode = (logfile[0] == '|') ? ERRORLOG_PIPE : ERRORLOG_FILE; } log_error_write(srv, __FILE__, __LINE__, "s", "server started"); if (srv->errorlog_mode == ERRORLOG_FD && !srv->srvconf.dont_daemonize) { /* We can only log to stderr in dont-daemonize mode; * if we do daemonize and no errorlog file is specified, we log into /dev/null */ srv->errorlog_fd = -1; } if (!buffer_is_empty(srv->srvconf.breakagelog_file)) { int breakage_fd; const char *logfile = srv->srvconf.breakagelog_file->ptr; if (srv->errorlog_mode == ERRORLOG_FD) { srv->errorlog_fd = dup(STDERR_FILENO); #ifdef FD_CLOEXEC fcntl(srv->errorlog_fd, F_SETFD, FD_CLOEXEC); #endif } if (-1 == (breakage_fd = open_logfile_or_pipe(srv, logfile))) { return -1; } if (STDERR_FILENO != breakage_fd) { dup2(breakage_fd, STDERR_FILENO); close(breakage_fd); } } else if (!srv->srvconf.dont_daemonize) { /* move stderr to /dev/null */ openDevNull(STDERR_FILENO); } return 0; }
static int check_aicloud_auth_url(server *srv, connection *con, plugin_data *p){ smb_info_t *c; int i, j, k; plugin_config *s; /* skip the first, the global context */ for (i = 1; i < srv->config_context->used; i++) { data_config *dc = (data_config *)srv->config_context->data[i]; s = p->config_storage[i]; /* condition didn't match */ if (!config_check_cond(srv, con, dc)) continue; /* merge config */ for (j = 0; j < dc->value->used; j++) { data_unset *du = dc->value->data[j]; if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.aicloud-auth-deny"))) { PATCH(auth_deny); } } } if(p->conf.auth_deny){ for (k = 0; k < p->conf.auth_deny->used; k++) { data_string *ds = (data_string *)p->conf.auth_deny->data[k]; if (ds->value->used == 0) continue; if (strstr(con->uri.path->ptr, ds->value->ptr)) { if(p->smb_info_list==NULL) return 0; for (c = p->smb_info_list; c; c = c->next) { if( buffer_is_empty(c->server) && buffer_is_empty(c->share) && buffer_is_equal(c->src_ip, con->dst_addr_buf) ){ if(buffer_is_empty(c->username)) return 0; else return 1; } } return 0; } } } return 1; }
static handler_t magnet_attract_array(server *srv, connection *con, plugin_data *p, array *files) { size_t i; handler_t ret = HANDLER_GO_ON; /* no filename set */ if (files->used == 0) return HANDLER_GO_ON; /** * execute all files and jump out on the first !HANDLER_GO_ON */ for (i = 0; i < files->used; i++) { data_string *ds = (data_string *)files->data[i]; if (buffer_is_empty(ds->value)) continue; ret = magnet_attract(srv, con, p, ds->value); if (ret != HANDLER_GO_ON) break; } /* reset conditional cache. */ config_cond_cache_reset_all_items(srv, con); return ret; }
static int magnet_env_get(lua_State *L) { server *srv; connection *con; const char *key = luaL_checkstring(L, 2); buffer *dest = NULL; lua_pushstring(L, "lighty.srv"); lua_gettable(L, LUA_REGISTRYINDEX); srv = lua_touserdata(L, -1); lua_pop(L, 1); lua_pushstring(L, "lighty.con"); lua_gettable(L, LUA_REGISTRYINDEX); con = lua_touserdata(L, -1); lua_pop(L, 1); dest = magnet_env_get_buffer(srv, con, key); if (!buffer_is_empty(dest)) { lua_pushlstring(L, CONST_BUF_LEN(dest)); } else { lua_pushnil(L); } return 1; }
static int tokenizer_open(server *srv, tokenizer_t *t, buffer *basedir, const char *fn) { if (buffer_is_empty(basedir) || (fn[0] == '/' || fn[0] == '\\') || (fn[0] == '.' && (fn[1] == '/' || fn[1] == '\\'))) { t->file = buffer_init_string(fn); } else { t->file = buffer_init_buffer(basedir); buffer_append_string(t->file, fn); } if (0 != stream_open(&(t->s), t->file)) { log_error_write(srv, __FILE__, __LINE__, "sbss", "opening configfile ", t->file, "failed:", strerror(errno)); buffer_free(t->file); return -1; } t->input = t->s.start; t->offset = 0; t->size = t->s.size; t->line = 1; t->line_pos = 1; t->in_key = 1; t->in_brace = 0; t->in_cond = 0; return 0; }
static int _search_flush_and_process_buffer(ReaderArgs *args) { int status = PROCESS_STATUS_OK; assert(args != NULL); assert(args->buffer != NULL); args->count = 0; if(args->cb && !buffer_is_empty(args->buffer)) { status = _search_process_lines_from_buffer(args); if(status == PROCESS_STATUS_OK && buffer_flush(args->buffer, &args->line, &args->llen)) { if(_search_process_line(args) == PROCESS_STATUS_OK) { if(args->count < INT32_MAX) { ++args->count; } } } } return status; }
int config_parse_file(server *srv, config_t *context, const char *fn) { tokenizer_t t; stream s; int ret; buffer *filename; if (buffer_is_empty(context->basedir) || (fn[0] == '/' || fn[0] == '\\') || (fn[0] == '.' && (fn[1] == '/' || fn[1] == '\\'))) { filename = buffer_init_string(fn); } else { filename = buffer_init_buffer(context->basedir); buffer_append_string(filename, fn); } if (0 != stream_open(&s, filename)) { if (s.size == 0) { /* the file was empty, nothing to parse */ ret = 0; } else { log_error_write(srv, __FILE__, __LINE__, "sbss", "opening configfile ", filename, "failed:", strerror(errno)); ret = -1; } } else { tokenizer_init(&t, filename, s.start, s.size); ret = config_parse(srv, context, &t); } stream_close(&s); buffer_free(filename); return ret; }
int config_parse_cmd(server *srv, config_t *context, const char *cmd) { tokenizer_t t; int ret; buffer *source; buffer *out; char *oldpwd; if (NULL == (oldpwd = getCWD())) { log_error_write(srv, __FILE__, __LINE__, "s", "cannot get cwd", strerror(errno)); return -1; } source = buffer_init_string(cmd); out = buffer_init(); if (!buffer_is_empty(context->basedir)) { chdir(context->basedir->ptr); } if (0 != proc_open_buffer(cmd, NULL, out, NULL)) { log_error_write(srv, __FILE__, __LINE__, "sbss", "opening", source, "failed:", strerror(errno)); ret = -1; } else { tokenizer_init(&t, source, out->ptr, out->used); ret = config_parse(srv, context, &t); } buffer_free(source); buffer_free(out); chdir(oldpwd); free(oldpwd); return ret; }
static int magnet_env_next(lua_State *L) { server *srv = magnet_get_server(L); connection *con = magnet_get_connection(L); const int pos = lua_tointeger(L, lua_upvalueindex(1)); buffer *dest; /* ignore previous key: use upvalue for current pos */ lua_settop(L, 0); if (NULL == magnet_env[pos].name) return 0; /* end of list */ /* Update our positional upval to reflect our new current position */ lua_pushinteger(L, pos + 1); lua_replace(L, lua_upvalueindex(1)); /* key to return */ lua_pushstring(L, magnet_env[pos].name); /* get value */ dest = magnet_env_get_buffer_by_id(srv, con, magnet_env[pos].type); if (!buffer_is_empty(dest)) { lua_pushlstring(L, CONST_BUF_LEN(dest)); } else { lua_pushnil(L); } /* return 2 items on the stack (key, value) */ return 2; }
int buffer_size(bufferADT buffer) { if(buffer_is_empty(buffer)) return 0; if(buffer->tail < buffer->head) return (buffer->head - buffer->tail); return buffer->size - (buffer->tail - buffer->head); }
static void chunk_reset(chunk *c) { if (!c) return; buffer_reset(c->mem); if (c->file.is_temp && !buffer_is_empty(c->file.name)) { unlink(c->file.name->ptr); } buffer_reset(c->file.name); if(c->type == SMB_CHUNK){ if (c->file.fd != -1) { smbc_close(c->file.fd); Cdbg(DBE,"close smb file-------------------------------->remote computer"); c->file.fd = -1; } } else{ if (c->file.fd != -1) { close(c->file.fd); Cdbg(DBE,"close usbdisk file-------------------------------->usb disk"); c->file.fd = -1; } if (MAP_FAILED != c->file.mmap.start) { munmap(c->file.mmap.start, c->file.mmap.length); c->file.mmap.start = MAP_FAILED; } } }
END_TEST /** * Make sure things are sometimes accepted and sometimes not. * * Note this test assumes (incorrectly, but practically) that the probability of * all zeros or all ones is 0.0. If the test fails, double check that the random * numbers generated aren't the cause. */ START_TEST (test_50_50) { INIT_CON(); SET_CON_BERNOULLI(0.5); // Fill the buffer with packets, some of which will be accepted for (int i = 0; i < BUFFER_SIZE; i++) buffer_push(&b, spinn_packet_pool_palloc(&pool)); for (int i = 0; i < PERIOD * BUFFER_SIZE; i++) scheduler_tick_tock(&s); // Make sure some packets got accepted and others didn't ck_assert(!buffer_is_empty(&b)); ck_assert(!buffer_is_full(&b)); ck_assert(packets_received > 0); ck_assert(packets_received < BUFFER_SIZE); }
END_TEST /** * Make sure everything is accepted if the probability of acceptance is 1.0. */ START_TEST (test_active) { INIT_CON(); SET_CON_BERNOULLI(1.0); // Fill the buffer with packets which will all be accepted for (int i = 0; i < BUFFER_SIZE; i++) buffer_push(&b, spinn_packet_pool_palloc(&pool)); // Make sure all packets are accepted in the expected timeframe for (int i = 0; i < PERIOD * BUFFER_SIZE; i++) scheduler_tick_tock(&s); ck_assert(buffer_is_empty(&b)); ck_assert_int_eq(packets_received, BUFFER_SIZE); // Make sure nothing catches fire when the buffer is empty for (int i = 0; i < PERIOD * BUFFER_SIZE; i++) scheduler_tick_tock(&s); ck_assert_int_eq(packets_received, BUFFER_SIZE); }
static handler_t mod_status_handler(server *srv, connection *con, void *p_d) { plugin_data *p = p_d; mod_status_patch_connection(srv, con, p); if (!buffer_is_empty(p->conf.status_url) && buffer_is_equal(p->conf.status_url, con->uri.path)) { return mod_status_handle_server_status(srv, con, p_d); } else if (!buffer_is_empty(p->conf.config_url) && buffer_is_equal(p->conf.config_url, con->uri.path)) { return mod_status_handle_server_config(srv, con, p_d); } else if (!buffer_is_empty(p->conf.statistics_url) && buffer_is_equal(p->conf.statistics_url, con->uri.path)) { return mod_status_handle_server_statistics(srv, con, p_d); } return HANDLER_GO_ON; }
char buffer_consume(bufferADT buffer) { if(buffer_is_empty(buffer)) { return EMPTY; } char ans = buffer->mem_start[buffer->tail]; buffer->tail = buffer_next_index(buffer, buffer->tail); return ans; }
END_TEST /** * Ensure with a periodic interval, packets are received at the correct times * when the input is empty. */ START_TEST (test_periodic_blocked) { INIT_CON(); SET_CON_PERIODIC(INTERVAL); // Run the generator for one and a half intervals, during which time nothing // should be received and we end up at what would be mid-interval had a packet // been received. for (int j = 0; j < PERIOD*(INTERVAL + (INTERVAL/2)); j++) { scheduler_tick_tock(&s); // Nothing should have got through ck_assert_int_eq(packets_received, 0); } // If a couple of packets are added to the buffer, the consumer should // immediately consume a packet. buffer_push(&b, spinn_packet_pool_palloc(&pool)); buffer_push(&b, spinn_packet_pool_palloc(&pool)); for (int k = 0; k < PERIOD; k++) scheduler_tick_tock(&s); ck_assert_int_eq(packets_received, 1); ck_assert(!buffer_is_empty(&b)); // The consumer should then consume a further packet exactly one interval // later for (int j = 0; j < INTERVAL; j++) { // The second value should not have got through yet ck_assert_int_eq(packets_received, 1); for (int k = 0; k < PERIOD; k++) { scheduler_tick_tock(&s); } } ck_assert_int_eq(packets_received, 2); ck_assert(buffer_is_empty(&b)); }
//Returns last element of the key buffer enum KEYCODE kbrd_get_key () { if (buffer_is_empty() ) { return KEY_UNKNOWN; } enum KEYCODE c = key_buffer[buffer_first_key]; buffer_first_key = (buffer_first_key + 1) % KEY_BUFFER_SIZE; return c; }
int test(){ if (buffer_is_empty(p->conf.basepath) #ifdef HAVE_PWD_H && NULL == (pwd = getpwnam(p->username->ptr)) #endif ) { /* user not found */ return HANDLER_GO_ON; } }
static void http_list_directory_footer(server *srv, connection *con, plugin_data *p, buffer *out) { UNUSED(srv); buffer_append_string_len(out, CONST_STR_LEN( "</tbody>\n" "</table>\n" "</div>\n" )); if (!buffer_string_is_empty(p->conf.show_readme)) { /* if we have a README file, display it in <pre class="readme"></pre> */ buffer *rb = p->conf.show_readme; if (rb->ptr[0] != '/') { buffer_copy_buffer(p->tmp_buf, con->physical.path); buffer_append_path_len(p->tmp_buf, CONST_BUF_LEN(p->conf.show_readme)); rb = p->tmp_buf; } http_list_directory_include_file(out, con->conf.follow_symlink, rb, "readme", p->conf.encode_readme); } if(p->conf.auto_layout) { buffer_append_string_len(out, CONST_STR_LEN( "<div class=\"foot\">" )); if (!buffer_string_is_empty(p->conf.set_footer)) { buffer_append_string_buffer(out, p->conf.set_footer); } else { buffer_append_string_buffer(out, con->conf.server_tag); } buffer_append_string_len(out, CONST_STR_LEN( "</div>\n" )); if (!buffer_string_is_empty(p->conf.external_js)) { buffer_append_string_len(out, CONST_STR_LEN("<script type=\"text/javascript\" src=\"")); buffer_append_string_buffer(out, p->conf.external_js); buffer_append_string_len(out, CONST_STR_LEN("\"></script>\n")); } else if (buffer_is_empty(p->conf.external_js)) { http_dirlist_append_js_table_resort(out, con); } buffer_append_string_len(out, CONST_STR_LEN( "</body>\n" "</html>\n" )); } }
static void cgi_copy_err(chunkqueue *cq) { buffer *line = buffer_init(); chunk *c; for (c = cq->first; c; c = c->next) { off_t we_have; char *str, *nl; if (c->type != MEM_CHUNK) { ERROR("%s", "wrong chunk type"); chunk_set_done(c); continue; } we_have = c->mem->used - 1 - c->offset; str = c->mem->ptr + c->offset; if (we_have <= 0) continue; for ( ; NULL != (nl = strchr(str, '\n')); str = nl+1) { *nl = '\0'; if (!buffer_is_empty(line)) { buffer_append_string(line, str); cgi_log_err(SAFE_BUF_STR(line)); buffer_reset(line); } else { cgi_log_err(str); } } if (*str) { buffer_append_string(line, str); } chunk_set_done(c); } if (!buffer_is_empty(line)) { cgi_log_err(SAFE_BUF_STR(line)); } chunkqueue_remove_finished_chunks(cq); }
static int buffer_copy_dirname(buffer *dst, buffer *file) { size_t i; if (buffer_is_empty(file)) return -1; for (i = file->used - 1; i+1 > 0; i--) { if (file->ptr[i] == '/') { buffer_copy_string_len(dst, file->ptr, i); return 0; } } return -1; }
static void http_list_directory_footer(server *srv, connection *con, plugin_data *p, buffer *out) { UNUSED(srv); buffer_append_string_len(out, CONST_STR_LEN( "</tbody>\n" "</table>\n" "</div>\n" )); if (p->conf.show_readme) { stream s; /* if we have a README file, display it in <pre class="readme"></pre> */ buffer_copy_string_buffer(p->tmp_buf, con->physical.path); BUFFER_APPEND_SLASH(p->tmp_buf); buffer_append_string_len(p->tmp_buf, CONST_STR_LEN("README.txt")); if (-1 != stream_open(&s, p->tmp_buf)) { if (p->conf.encode_readme) { buffer_append_string_len(out, CONST_STR_LEN("<pre class=\"readme\">")); buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML); buffer_append_string_len(out, CONST_STR_LEN("</pre>")); } else { buffer_append_string_len(out, s.start, s.size); } } stream_close(&s); } if(p->conf.auto_layout) { buffer_append_string_len(out, CONST_STR_LEN( "<div class=\"foot\">" )); if (p->conf.set_footer->used > 1) { buffer_append_string_buffer(out, p->conf.set_footer); } else if (buffer_is_empty(con->conf.server_tag)) { buffer_append_string_len(out, CONST_STR_LEN(PACKAGE_DESC)); } else { buffer_append_string_buffer(out, con->conf.server_tag); } buffer_append_string_len(out, CONST_STR_LEN( "</div>\n" "</body>\n" "</html>\n" )); } }
static int magnet_cgi_get(lua_State *L) { connection *con = magnet_get_connection(L); data_string *ds; /* __index: param 1 is the (empty) table the value was not found in */ const char *key = luaL_checkstring(L, 2); ds = (data_string *)array_get_element(con->environment, key); if (NULL != ds && !buffer_is_empty(ds->value)) lua_pushlstring(L, CONST_BUF_LEN(ds->value)); else lua_pushnil(L); return 1; }
static int data_string_insert_dup(data_unset *dst, data_unset *src) { data_string *ds_dst = (data_string *)dst; data_string *ds_src = (data_string *)src; if (!buffer_is_empty(ds_dst->value)) { buffer_append_string_len(ds_dst->value, CONST_STR_LEN(", ")); buffer_append_string_buffer(ds_dst->value, ds_src->value); } else { buffer_copy_buffer(ds_dst->value, ds_src->value); } src->free(src); return 0; }
int log_error_open(server *srv) { int close_stderr = 0; /* * perhaps someone wants to use syslog() */ openlog("swiftd", LOG_CONS | LOG_PID, LOG_DAEMON); srv->errorlog_mode = ERRORLOG_STDERR; //默认的日志输出的标准错误输出。 if (srv->srvconf.errorlog_use_syslog) //使用系统的日志函数syslog() { srv->errorlog_mode = ERRORLOG_SYSLOG; } else if (!buffer_is_empty(srv->srvconf.errorlog_file)) //使用日志文件。 { const char *logfile = srv->srvconf.errorlog_file->ptr; if (-1 == (srv->errorlog_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) { log_error_write(srv, __FILE__, __LINE__, "SSSS", "opening errorlog '", logfile, "' failed: ", strerror(errno)); return -1; } srv->errorlog_mode = ERRORLOG_FILE; } log_error_write(srv, __FILE__, __LINE__, "s", "server started"); if (srv->errorlog_mode == ERRORLOG_STDERR && srv->srvconf.dont_daemonize) { /* * 在非守护进程模式下,我们只向标准错误输出写日志。如果在守护进程模式下并且没有设定日志文件, * 则将日志写到/dev/null中。 */ close_stderr = 0; } /* * move stderr to /dev/null * 将标准错误输出打开到/dev/null上。 */ if (close_stderr) openDevNull(STDERR_FILENO); return 0; }
static buffer * cgi_get_handler(array *a, buffer *fn) { size_t k, s_len = buffer_string_length(fn); for (k = 0; k < a->used; ++k) { data_string *ds = (data_string *)a->data[k]; size_t ct_len = buffer_string_length(ds->key); if (buffer_is_empty(ds->key)) continue; if (s_len < ct_len) continue; if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) { return ds->value; } } return NULL; }
static handler_t mod_authn_gssapi_check (server *srv, connection *con, void *p_d, const struct http_auth_require_t *require, const struct http_auth_backend_t *backend) { data_string * const ds = (data_string *)array_get_element(con->request.headers, "Authorization"); UNUSED(backend); if (NULL == ds || buffer_is_empty(ds->value)) { return mod_authn_gssapi_send_401_unauthorized_negotiate(srv, con); } if (0 != strncasecmp(ds->value->ptr, "Negotiate ", sizeof("Negotiate ")-1)) { return mod_authn_gssapi_send_400_bad_request(srv, con); } return mod_authn_gssapi_check_spnego(srv, con, (plugin_data *)p_d, require, ds->value->ptr+sizeof("Negotiate ")-1); }
/* if any id of the specified type is found, appropriate updates will be made to id_info no updates are made to the buffer about consumed data, the caller is responsible */ void find_last_id_in_buffer(buf_info_t *buffer, id_info_t *id_info, bz_info_t *bfile, char *type, int verbose) { regmatch_t *match_id; regex_t compiled_id; char *page_id_pattern = "<page>\n[ ]+<title>[^<]+</title>\n([ ]+<ns>[0-9]+</ns>\n)?[ ]+<id>([0-9]+)</id>\n"; char *rev_id_pattern = "<revision>\n[ ]+<id>([0-9]+)</id>\n"; char *match_from ; int index; if (buffer_is_empty(buffer)) return; match_id = (regmatch_t *)malloc(sizeof(regmatch_t)*3); match_from = (char *)buffer->next_to_read; if (! strcmp(type, "rev")) { index = 1; regcomp(&compiled_id, rev_id_pattern, REG_EXTENDED); } else if (! strcmp(type, "page")) { index = 2; regcomp(&compiled_id, page_id_pattern, REG_EXTENDED); } else { fprintf(stderr, "unknown type of tag to find, %s, giving up\n", type); exit(-1); } while (regexec(&compiled_id, match_from, 3, match_id, 0) == 0) { /* found one, yay */ if (match_id[index].rm_so >=0) { id_info->id = atoi((char *)(match_from +match_id[index].rm_so)); id_info->position = bfile->block_start; id_info->bits_shifted = bfile->bits_shifted; /* get ready to search rest of buffer */ match_from += match_id[0].rm_eo; } else { /* should never happen */ fprintf(stderr,"regex gone bad...\n"); exit(-1); } } free(match_id); regfree(&compiled_id); return; }