/* Set the output file (file object) */ static void f_output(INT32 args) { if(args) { if(ARG(1).type != T_OBJECT) { SIMPLE_BAD_ARG_ERROR("_Caudium.nbio()->output", 1, "object"); } else { output *outp; if(THIS->outp != NULL) { free_output(THIS->outp); THIS->outp = NULL; } outp = malloc(sizeof(output)); outp->file = ARG(1).u.object; outp->fd = fd_from_object(outp->file); outp->set_nb_off = find_identifier("set_nonblocking", outp->file->prog); outp->set_b_off = find_identifier("set_blocking", outp->file->prog); outp->write_off = find_identifier("write", outp->file->prog); if (outp->write_off < 0 || outp->set_nb_off < 0 || outp->set_b_off < 0) { free(outp); Pike_error("_Caudium.nbio()->output: illegal file object%s%s%s\n", ((outp->write_off < 0)?"; no write":""), ((outp->set_nb_off < 0)?"; no set_nonblocking":""), ((outp->set_b_off < 0)?"; no set_blocking":"")); } DERR(fprintf(stderr, "New output (fd = %d)\n", outp->fd)); outp->mode = ACTIVE; add_ref(outp->file); THIS->outp = outp; noutputs++; /* Set up the read callback. We don't need a close callback since * it never will be called w/o a read_callback (which we don't want one). */ set_outp_write_cb(outp); } } else { SIMPLE_TOO_FEW_ARGS_ERROR("_Caudium.nbio()->output", 1); } pop_n_elems(args-1); }
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; }
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); }
static void f_read( INT32 args ) { char *read_buf; struct svalue *logfun, *file; FD f = -1; int cls, c, my_fd=1, state=0, tzs=0; char *char_pointer; INT32 v=0, yy=0, mm=0, dd=0, h=0, m=0, s=0, tz=0; ptrdiff_t offs0=0, len=0; struct svalue *old_sp; /* #define DYNAMIC_BUF */ #ifdef DYNAMIC_BUF dynamic_buffer buf; #else #define BUFSET(X) do { if(bufpos == bufsize) { bufsize *= 2; buf = realloc(buf, bufsize+1); } buf[bufpos++] = c; } while(0) #define PUSHBUF() do { push_string( make_shared_binary_string( buf,bufpos ) ); bufpos=0; } while(0) char *buf; int bufsize=CLF_BLOCK_SIZE, bufpos=0; #endif if(args>2 && sp[-1].type == T_INT) { offs0 = sp[-1].u.integer; pop_n_elems(1); --args; } old_sp = sp; get_all_args("CommonLog.read", args, "%*%*", &logfun, &file); if(logfun->type != T_FUNCTION) SIMPLE_BAD_ARG_ERROR("CommonLog.read", 1, "function"); if(file->type == T_OBJECT) { f = fd_from_object(file->u.object); if(f == -1) Pike_error("CommonLog.read: File is not open.\n"); my_fd = 0; } else if(file->type == T_STRING && file->u.string->size_shift == 0) { #ifdef PIKE_SECURITY if(!CHECK_SECURITY(SECURITY_BIT_SECURITY)) { if(!CHECK_SECURITY(SECURITY_BIT_CONDITIONAL_IO)) Pike_error("Permission denied.\n"); push_text("read"); push_int(0); ref_push_string(file->u.string); push_text("r"); push_int(00666); safe_apply(OBJ2CREDS(CURRENT_CREDS)->user,"valid_open",5); switch(Pike_sp[-1].type) { case PIKE_T_INT: switch(Pike_sp[-1].u.integer) { case 0: /* return 0 */ errno=EPERM; Pike_error("CommonLog.read(): Failed to open file for reading (errno=%d).\n", errno); case 2: /* ok */ pop_stack(); break; case 3: /* permission denied */ Pike_error("CommonLog.read: permission denied.\n"); default: Pike_error("Error in user->valid_open, wrong return value.\n"); } break; default: Pike_error("Error in user->valid_open, wrong return type.\n"); case PIKE_T_STRING: /* if(Pike_sp[-1].u.string->shift_size) */ /* file=Pike_sp[-1]; */ pop_stack(); } } #endif do { THREADS_ALLOW(); f=fd_open((char *)STR0(file->u.string), fd_RDONLY, 0); THREADS_DISALLOW(); if (f >= 0 || errno != EINTR) break; check_threads_etc(); } while (1); if(f < 0) Pike_error("CommonLog.read(): Failed to open file for reading (errno=%d).\n", errno); } else SIMPLE_BAD_ARG_ERROR("CommonLog.read", 2, "string|Stdio.File"); #ifdef HAVE_LSEEK64 lseek64(f, offs0, SEEK_SET); #else fd_lseek(f, offs0, SEEK_SET); #endif read_buf = malloc(CLF_BLOCK_SIZE+1); #ifndef DYNAMIC_BUF buf = malloc(bufsize); #endif while(1) { do { THREADS_ALLOW(); len = fd_read(f, read_buf, CLF_BLOCK_SIZE); THREADS_DISALLOW(); if (len >= 0 || errno != EINTR) break; check_threads_etc(); } while (1); if(len == 0) break; /* nothing more to read. */ if(len < 0) break; char_pointer = read_buf; while(len--) { offs0++; c = char_pointer[0] & 0xff; char_pointer ++; cls = char_class[c]; #ifdef TRACE_DFA fprintf(stderr, "DFA(%d): '%c' ", state, (c<32? '.':c)); switch(cls) { case CLS_WSPACE: fprintf(stderr, "CLS_WSPACE"); break; case CLS_CRLF: fprintf(stderr, "CLS_CRLF"); break; case CLS_TOKEN: fprintf(stderr, "CLS_TOKEN"); break; case CLS_DIGIT: fprintf(stderr, "CLS_DIGIT"); break; case CLS_QUOTE: fprintf(stderr, "CLS_QUOTE"); break; case CLS_LBRACK: fprintf(stderr, "CLS_LBRACK"); break; case CLS_RBRACK: fprintf(stderr, "CLS_RBRACK"); break; case CLS_SLASH: fprintf(stderr, "CLS_SLASH"); break; case CLS_COLON: fprintf(stderr, "CLS_COLON"); break; case CLS_HYPHEN: fprintf(stderr, "CLS_HYPHEN"); break; case CLS_PLUS: fprintf(stderr, "CLS_PLUS"); break; default: fprintf(stderr, "???"); } fprintf(stderr, " %d items on stack\n", sp-old_sp); #endif switch(state) { case 0: if(sp != old_sp) { if(sp == old_sp+15) { f_aggregate(15); push_int64(offs0); apply_svalue(logfun, 2); pop_stack(); } else pop_n_elems(sp-old_sp); } if(cls > CLS_CRLF) { if(cls == CLS_HYPHEN) { push_int(0); state = 2; break; } #ifdef DYNAMIC_BUF buf.s.str = NULL; initialize_buf( &buf ); low_my_putchar( c, &buf ); #else bufpos = 0; BUFSET(c); #endif state=1; } break; case 1: if(cls > CLS_CRLF) { #ifdef DYNAMIC_BUF low_my_putchar( c, &buf ); #else BUFSET(c); #endif break; } #ifdef DYNAMIC_BUF push_string( low_free_buf( &buf ) ); /* remotehost */ #else PUSHBUF(); #endif state = (cls == CLS_WSPACE? 2:0); break; case 2: if(cls > CLS_CRLF) { if(cls == CLS_HYPHEN) { push_int(0); state = 4; break; } #ifdef DYNAMIC_BUF buf.s.str = NULL; initialize_buf( &buf ); low_my_putchar( c, &buf ); #else bufpos = 0; BUFSET(c); #endif state=3; } else if(cls == CLS_CRLF) state=0; break; case 3: if(cls > CLS_CRLF) { #ifdef DYNAMIC_BUF low_my_putchar( c, &buf ); #else BUFSET(c); #endif break; } #ifdef DYNAMIC_BUF push_string( low_free_buf( &buf ) ); /* rfc931 */ #else PUSHBUF(); /* rfc931 */ #endif state = (cls == CLS_WSPACE? 4:0); break; case 4: if(cls > CLS_CRLF) { if(cls == CLS_HYPHEN) { push_int(0); state = 6; break; } #ifdef DYNAMIC_BUF buf.s.str = NULL; initialize_buf( &buf ); low_my_putchar( c, &buf ); #else bufpos = 0; BUFSET(c); #endif state=5; } else if(cls == CLS_CRLF) state=0; break; case 5: if(cls > CLS_CRLF) { #ifdef DYNAMIC_BUF low_my_putchar( c, &buf ); #else BUFSET(c); #endif break; } #ifdef DYNAMIC_BUF push_string( low_free_buf( &buf ) ); /* authuser */ #else PUSHBUF(); /* authuser */ #endif state = (cls == CLS_WSPACE? 6:0); break; case 6: if(cls == CLS_LBRACK) state = 15; else if(cls == CLS_CRLF) state = 0; else if(cls == CLS_HYPHEN) { push_int(0); push_int(0); push_int(0); state = 7; } break; case 7: if(cls == CLS_QUOTE) { #ifdef DYNAMIC_BUF buf.s.str = NULL; initialize_buf( &buf ); #else bufpos = 0; #endif state = 31; } else if(cls == CLS_CRLF) state = 0; else if(cls == CLS_HYPHEN) { push_int(0); push_int(0); push_int(0); state = 10; } break; case 8: if(cls == CLS_QUOTE) state = 9; else if(cls == CLS_CRLF) { #ifdef DYNAMIC_BUF push_string( low_free_buf( &buf ) ); #else PUSHBUF(); #endif state = 0; } else #ifdef DYNAMIC_BUF low_my_putchar( c, &buf ); #else BUFSET(c); #endif break; case 9: if(cls > CLS_CRLF) { #ifdef DYNAMIC_BUF low_my_putchar( '"', &buf); low_my_putchar( c, &buf); #else BUFSET('"'); BUFSET(c); #endif state = 8; break; } #ifdef DYNAMIC_BUF push_string( low_free_buf( &buf ) ); /* protocol */ #else PUSHBUF(); /* protoocl */ #endif state = (cls == CLS_CRLF? 0 : 10); break; case 10: if(cls == CLS_DIGIT) { v = c&0xf; state = 11; } else if(cls == CLS_CRLF) state = 0; else if(cls == CLS_HYPHEN) { push_int(0); state = 12; } break; case 11: if(cls == CLS_DIGIT) v = v*10+(c&0xf); else if(cls == CLS_WSPACE) { push_int(v); /* status */ state = 12; } else state = 0; break; case 12: if(cls == CLS_DIGIT) { v = c&0xf; state = 13; } else if(cls == CLS_CRLF) state = 0; else if(cls == CLS_HYPHEN) { push_int(0); state = 14; } break; case 13: if(cls == CLS_DIGIT) v = v*10+(c&0xf); else { push_int(v); /* bytes */ state = (cls == CLS_CRLF? 0:14); } break; case 14: if(cls == CLS_CRLF) state = 0; break; case 15: if(cls == CLS_DIGIT) { dd = c&0xf; state = 16; } else state = (cls == CLS_CRLF? 0:14); break; case 16: /* getting day */ if(cls == CLS_DIGIT) dd = dd*10+(c&0xf); else if(cls == CLS_SLASH) state = 17; else state = (cls == CLS_CRLF? 0:14); break; case 17: if(cls == CLS_DIGIT) { mm = c&0xf; state = 18; } else if(cls == CLS_TOKEN) { mm = c|0x20; state = 21; } else state = (cls == CLS_CRLF? 0:14); break; case 18: /* getting numeric month */ if(cls == CLS_DIGIT) mm = mm*10+(c&0xf); else if(cls == CLS_SLASH) state = 19; else state = (cls == CLS_CRLF? 0:14); break; case 19: if(cls == CLS_DIGIT) { yy = c&0xf; state = 20; } else state = (cls == CLS_CRLF? 0:14); break; case 20: /* getting year */ if(cls == CLS_DIGIT) yy = yy*10+(c&0xf); else if(cls == CLS_COLON) state = 22; else state = (cls == CLS_CRLF? 0:14); break; case 21: /* getting textual month */ if(cls == CLS_TOKEN) mm = (mm<<8)|c|0x20; else if(cls == CLS_SLASH) { state = 19; switch(mm) { case ('j'<<16)|('a'<<8)|'n': mm=1; break; case ('f'<<16)|('e'<<8)|'b': mm=2; break; case ('m'<<16)|('a'<<8)|'r': mm=3; break; case ('a'<<16)|('p'<<8)|'r': mm=4; break; case ('m'<<16)|('a'<<8)|'y': mm=5; break; case ('j'<<16)|('u'<<8)|'n': mm=6; break; case ('j'<<16)|('u'<<8)|'l': mm=7; break; case ('a'<<16)|('u'<<8)|'g': mm=8; break; case ('s'<<16)|('e'<<8)|'p': mm=9; break; case ('o'<<16)|('c'<<8)|'t': mm=10; break; case ('n'<<16)|('o'<<8)|'v': mm=11; break; case ('d'<<16)|('e'<<8)|'c': mm=12; break; default: state = 14; } } break; case 22: if(cls == CLS_DIGIT) { h = c&0xf; state = 23; } else state = (cls == CLS_CRLF? 0:14); break; case 23: /* getting hour */ if(cls == CLS_DIGIT) h = h*10+(c&0xf); else if(cls == CLS_COLON) state = 24; else state = (cls == CLS_CRLF? 0:14); break; case 24: if(cls == CLS_DIGIT) { m = c&0xf; state = 25; } else state = (cls == CLS_CRLF? 0:14); break; case 25: /* getting minute */ if(cls == CLS_DIGIT) m = m*10+(c&0xf); else if(cls == CLS_COLON) state = 26; else state = (cls == CLS_CRLF? 0:14); break; case 26: if(cls == CLS_DIGIT) { s = c&0xf; state = 27; } else state = (cls == CLS_CRLF? 0:14); break; case 27: /* getting second */ if(cls == CLS_DIGIT) s = s*10+(c&0xf); else if(cls == CLS_WSPACE) state = 28; else state = (cls == CLS_CRLF? 0:14); break; case 28: if(cls>=CLS_HYPHEN) { state = 29; tzs = cls!=CLS_PLUS; tz = 0; } else if(cls == CLS_DIGIT) { state = 29; tzs = 0; tz = c&0xf; } else if(cls==CLS_CRLF) state = 0; break; case 29: /* getting timezone */ if(cls == CLS_DIGIT) tz = tz*10+(c&0xf); else { if(tzs) tz = -tz; push_int(yy); push_int(mm); push_int(dd); push_int(h); push_int(m); push_int(s); push_int(tz); if(cls == CLS_RBRACK) state = 7; else state = (cls == CLS_CRLF? 0 : 30); } break; case 30: if(cls == CLS_RBRACK) state = 7; else if(cls == CLS_CRLF) state = 0; break; case 31: if(cls == CLS_QUOTE) { #ifdef DYNAMIC_BUF push_string( low_free_buf( &buf ) ); #else PUSHBUF(); #endif push_int(0); push_int(0); state = 10; } else if(cls >= CLS_TOKEN) #ifdef DYNAMIC_BUF low_my_putchar( c, &buf ); #else BUFSET(c); #endif else { #ifdef DYNAMIC_BUF push_string( low_free_buf( &buf ) ); /* method */ #else PUSHBUF(); /* method */ #endif state = (cls == CLS_CRLF? 0 : 32); } break; case 32: if(cls == CLS_QUOTE) { push_int(0); push_int(0); state = 10; } else if(cls >= CLS_TOKEN) { #ifdef DYNAMIC_BUF buf.s.str = NULL; initialize_buf( &buf ); low_my_putchar( c, &buf ); #else bufpos = 0; BUFSET(c); #endif state = 33; } else if(cls == CLS_CRLF) state = 0; break; case 33: if(cls == CLS_QUOTE) state = 34; else if(cls == CLS_CRLF) { #ifdef DYNAMIC_BUF push_string( low_free_buf( &buf ) ); #else PUSHBUF(); #endif state = 0; } else if(cls == CLS_WSPACE) { #ifdef DYNAMIC_BUF push_string( low_free_buf( &buf ) ); /* path */ #else PUSHBUF(); /* path */ #endif state = 35; } else #ifdef DYNAMIC_BUF low_my_putchar( c, &buf ); #else BUFSET(c); #endif break; case 34: if(cls >= CLS_TOKEN) { #ifdef DYNAMIC_BUF low_my_putchar( '"', &buf ); low_my_putchar( c, &buf ); #else BUFSET('"'); BUFSET(c); #endif state = 33; } else if(cls == CLS_CRLF) { #ifdef DYNAMIC_BUF push_string( low_free_buf( &buf ) ); #else PUSHBUF(); #endif state = 0; } else { #ifdef DYNAMIC_BUF push_string( low_free_buf( &buf ) ); #else PUSHBUF(); #endif push_text("HTTP/0.9"); state = 10; } break; case 35: if(cls == CLS_QUOTE) { push_text("HTTP/0.9"); state = 10; } else if(cls >= CLS_TOKEN) { #ifdef DYNAMIC_BUF buf.s.str = NULL; initialize_buf( &buf ); low_my_putchar( c, &buf ); #else bufpos = 0; BUFSET(c); #endif state = 8; } else if(cls == CLS_CRLF) state = 0; break; } } }
/* Allocate new input object and add it to our list */ static INLINE void new_input(struct svalue inval, NBIO_INT_T len, int first) { struct stat s; input *inp; inp = malloc(sizeof(input)); if(inp == NULL) { Pike_error("Out of memory!\n"); return; } inp->pos = 0; inp->mode = SLEEPING; inp->set_nb_off = -1; inp->set_b_off = -1; DERR(fprintf(stderr, "Allocated new input at 0x%x\n", (unsigned int)inp)); if(inval.type == T_STRING) { inp->type = NBIO_STR; add_ref(inp->u.data = inval.u.string); inp->len = len ? len : inval.u.string->len << inval.u.string->size_shift; nstrings++; DERR(fprintf(stderr, "string input added: %ld bytes\n", (long)inp->len)); } else if(inval.type == T_OBJECT) { inp->fd = fd_from_object(inval.u.object); inp->len = len; if(inp->fd == -1) { /* Fake file object */ inp->u.file = inval.u.object; inp->set_nb_off = find_identifier("set_nonblocking",inp->u.file->prog); inp->set_b_off = find_identifier("set_blocking", inp->u.file->prog); if(inp->set_nb_off < 0 || inp->set_b_off < 0) { inp->type = NBIO_BLOCK_OBJ; /* No set_nonblocking/set_blocking funcs */ inp->set_nb_off = inp->set_b_off = 0; DERR(fprintf(stderr, "New fake blocking input\n")); } else { inp->type = NBIO_OBJ; /* Fake nonblocking object */ DERR(fprintf(stderr, "New fake non-blocking input\n")); } DERR(fprintf(stderr, "input object not a real FD\n")); if ((inp->read_off = find_identifier("read", inp->u.file->prog)) < 0) { free(inp); Pike_error("_Caudium.nbio()->input: Illegal file object, " "missing read()\n"); return; } add_ref(inp->u.file); nobjects++; } else { inp->type = NBIO_OBJ; inp->set_nb_off = find_identifier("set_nonblocking", inval.u.object->prog); inp->set_b_off = find_identifier("set_blocking", inval.u.object->prog); #ifdef USE_MMAP if (fstat(inp->fd, &s) == 0 && S_ISREG(s.st_mode)) { char *mtmp; unsigned NBIO_INT_T filep = lseek(inp->fd, 0L, SEEK_CUR); int alloc_len = MIN(s.st_size - filep, MAX_MMAP_SIZE); mtmp = (char *)mmap(0, alloc_len, PROT_READ, MAP_FILE | MAP_SHARED, inp->fd, filep); if(mtmp != MAP_FAILED) { if( (inp->u.mmap_storage = malloc(sizeof(mmap_data))) == NULL) { Pike_error("Failed to allocate mmap structure. Out of memory?\n"); } inp->type = NBIO_MMAP; inp->len = s.st_size; inp->pos = filep; inp->u.mmap_storage->data = mtmp; inp->u.mmap_storage->m_start = filep; inp->u.mmap_storage->m_len = alloc_len; inp->u.mmap_storage->m_end = filep + alloc_len; add_ref(inp->u.mmap_storage->file = inval.u.object); DERR(fprintf(stderr, "new mmap input (fd %d)\n", inp->fd)); mmapped += alloc_len; #ifdef NB_DEBUG } else { DERR(perror("mmap failed")); #endif } } #endif if(inp->type == NBIO_OBJ) { /* mmap failed or not a regular file. We'll use non-blocking IO * here, to support pipes and such (which are actual fds, but can * block). Typical example is CGI. */ inp->u.file = inval.u.object; if(inp->set_nb_off < 0 || inp->set_b_off < 0) { free(inp); Pike_error("set_nonblocking and/or set_blocking missing from actual file object!\n"); } add_ref(inp->u.file); nobjects++; DERR(fprintf(stderr, "new input FD == %d\n", inp->fd)); } } } if(inp->set_nb_off != -1 && inp->set_b_off != -1) { DERR(fprintf(stderr, "Resetting input object callbacks.\n")); push_int(0); push_int(0); push_int(0); apply_low(inval.u.object, inp->set_nb_off, 3); apply_low(inval.u.object, inp->set_b_off, 0); pop_n_elems(2); } ninputs++; if(first) { /* Add first in list */ inp->next = THIS->inputs; THIS->inputs = inp; } else { inp->next = NULL; if (THIS->last_input) THIS->last_input->next = inp; else THIS->inputs = inp; THIS->last_input = inp; } }