static int aPGSQL_disconnect(struct cw_channel *chan, void *data) { char *s1,*s3; int l; PGconn *karoto; int id; char *stringp=NULL; l=strlen(data)+2; s1=malloc(l); strncpy(s1, data, l - 1); stringp=s1; strsep(&stringp," "); /* eat the first token, we already know it :P */ s3=strsep(&stringp," "); id=atoi(s3); if ((karoto=find_identifier(id,CW_PGSQL_ID_CONNID))==NULL) { cw_log(LOG_WARNING,"Invalid connection identifier %d passed in aPGSQL_disconnect\n",id); } else { PQfinish(karoto); del_identifier(id,CW_PGSQL_ID_CONNID); } free(s1); return(0); }
struct source *source_pikestream_make( struct svalue *s, INT64 start, INT64 len ) { struct pf_source *res; if( (TYPEOF(*s) != PIKE_T_OBJECT) || (find_identifier("set_read_callback",s->u.object->prog)==-1) ) return 0; res = calloc( 1, sizeof( struct pf_source ) ); if( !res ) return NULL; res->len = len; res->skip = start; res->s.get_data = get_data; res->s.free_source = free_source; res->s.set_callback = set_callback; res->s.setup_callbacks = setup_callbacks; res->s.remove_callbacks = remove_callbacks; res->obj = s->u.object; add_ref(res->obj); res->cb_obj = clone_object( callback_program, 0 ); ((struct callback_prog *)res->cb_obj->storage)->s = res; return (struct source *)res; }
static int aPGSQL_query(struct cw_channel *chan, void *data) { char *s1,*s2,*s3,*s4; char s[100] = ""; char *querystring; char *var; int l; int res,nres; PGconn *karoto; PGresult *PGSQLres; int id,id1; char *stringp=NULL; res=0; l=strlen(data)+2; s1=malloc(l); s2=malloc(l); strncpy(s1, data, l - 1); stringp=s1; strsep(&stringp," "); /* eat the first token, we already know it :P */ s3=strsep(&stringp," "); while (1) { /* ugly trick to make branches with break; */ var=s3; s4=strsep(&stringp," "); id=atoi(s4); querystring=strsep(&stringp,"\n"); if ((karoto=find_identifier(id,CW_PGSQL_ID_CONNID))==NULL) { cw_log(LOG_WARNING,"Invalid connection identifier %d passed in aPGSQL_query\n",id); res=-1; break; } PGSQLres=PQexec(karoto,querystring); if (PGSQLres==NULL) { cw_log(LOG_WARNING,"aPGSQL_query: Connection Error (connection identifier = %d, error message : %s)\n",id,PQerrorMessage(karoto)); res=-1; break; } if (PQresultStatus(PGSQLres) == PGRES_BAD_RESPONSE || PQresultStatus(PGSQLres) == PGRES_NONFATAL_ERROR || PQresultStatus(PGSQLres) == PGRES_FATAL_ERROR) { cw_log(LOG_WARNING,"aPGSQL_query: Query Error (connection identifier : %d, error message : %s)\n",id,PQcmdStatus(PGSQLres)); res=-1; break; } nres=PQnfields(PGSQLres); id1=add_identifier(CW_PGSQL_ID_RESID,PGSQLres); snprintf(s, sizeof(s), "%d", id1); pbx_builtin_setvar_helper(chan,var,s); break; } free(s1); free(s2); return(res); }
tree_t * make_subprogram_head(identifier_t * ident, parameter_list_t * params, type_t * type) { subprogram_head_t * node = malloc(sizeof(subprogram_head_t)); node->ident = ident; node->params = params; node->type = type; find_identifier(node->ident->ident)->node->type = type; return make_tree(node, SUBPROGRAM_HEAD_T); }
/* 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); }
/* Initialized the sender */ void init_nbio(void) { start_new_program(); ADD_STORAGE( nbio_storage ); set_init_callback(alloc_nb_struct); set_exit_callback(free_nb_struct); ADD_FUNCTION("start", f_nbio_start, tFunc(tVoid, tVoid), 0); ADD_FUNCTION("nbio_status", f_nbio_status, tFunc(tVoid, tArray), 0); ADD_FUNCTION("input", f_input, tFunc(tObj tOr(tInt, tVoid), tVoid), 0); ADD_FUNCTION("write", f_write, tFunc(tStr, tVoid), 0); ADD_FUNCTION("output", f_output, tFunc(tObj, tVoid), 0); ADD_FUNCTION("_output_write_cb", f__output_write_cb, tFunc(tInt, tVoid), 0); ADD_FUNCTION("_input_read_cb", f__input_read_cb, tFunc(tInt tStr, tVoid), 0); ADD_FUNCTION("_input_close_cb", f__input_close_cb, tFunc(tInt, tVoid), 0); ADD_FUNCTION("set_done_callback", f_set_done_callback, tFunc(tOr(tVoid,tFunc(tMix, tMix)) tOr(tVoid,tMix),tVoid),0); ADD_FUNCTION("bytes_sent", f_bytes_sent, tFunc(tNone,tInt), 0); nbio_program = end_program(); add_program_constant("nbio", nbio_program, 0); output_write_cb_off = find_identifier("_output_write_cb", nbio_program); input_read_cb_off = find_identifier("_input_read_cb", nbio_program); input_close_cb_off = find_identifier("_input_close_cb", nbio_program); }
/* To learn which callbacks are required take a look at the callbacks_api * array above. */ static int is_callback_ok(struct object *callbacks, char **missing_method) { int ioff, i; struct identifier *ident; void **tmp; if (!callbacks) return 0; i = 0; if (missing_method) *missing_method = NULL; /* * walk the array of required methods, check whether each of them exists * in the passed object and is a method, then record its offset in our * storage so that the methods can be called later on. */ while (i < CB_API_SIZE) { ioff = find_identifier(callback_api[i].name, callbacks->prog); if (ioff < 0 && callback_api[i].req) { if (missing_method) *missing_method = callback_api[i].name; return 0; } else if (ioff < 0) { THIS->callbackOffsets[i] = -1; i++; continue; } ident = ID_FROM_INT(callbacks->prog, ioff); if (!IDENTIFIER_IS_FUNCTION(ident->identifier_flags)) { if (missing_method) *missing_method = callback_api[i].name; return 0; } /* Put the offset in the callbacks array and initialize the SAX handler * structure with appropriate function pointer. The pointer arithmetic * is hairy, but it works :> */ THIS->callbackOffsets[i] = ioff; tmp = (void**)((char*)THIS->sax + callback_api[i].saxFunIdx); *tmp = *((void**)((char*)(&pextsSAX) + callback_api[i].saxFunIdx)); i++; } return 1; }
static int aMYSQL_fetch(struct cw_channel *chan, char *data) { MYSQL_RES *mysqlres; MYSQL_ROW mysqlrow; char *fetchid_var,*s5,*s6; int resultid,numFields,j; strsep(&data," "); // eat the first token, we already know it :P fetchid_var = strsep(&data," "); resultid = safe_scan_int(&data," ",-1); if (fetchid_var && (resultid>=0) ) { if ((mysqlres=find_identifier(resultid,CW_MYSQL_ID_RESID))!=NULL) { /* Grab the next row */ if ((mysqlrow=mysql_fetch_row(mysqlres))!=NULL) { numFields=mysql_num_fields(mysqlres); for (j=0;j<numFields;j++) { s5=strsep(&data," "); if (s5==NULL) { cw_log(LOG_WARNING,"cw_MYSQL_fetch: More fields (%d) than variables (%d)\n",numFields,j); break; } s6=mysqlrow[j]; pbx_builtin_setvar_helper(chan,s5, s6 ? s6 : "NULL"); } #if EXTRA_LOG cw_log(LOG_WARNING,"cw_MYSQL_fetch: numFields=%d\n",numFields); #endif set_callweaver_int(chan,fetchid_var,1); // try more rows } else { #if EXTRA_LOG cw_log(LOG_WARNING,"cw_MYSQL_fetch : EOF\n"); #endif set_callweaver_int(chan,fetchid_var,0); // no more rows } return 0; } else { cw_log(LOG_WARNING,"aMYSQL_fetch: Invalid result identifier %d passed\n",resultid); } } else { cw_log(LOG_WARNING,"aMYSQL_fetch: missing some arguments\n"); } return -1; }
static int aMYSQL_disconnect(struct cw_channel *chan, char *data) { MYSQL *mysql; int id; strsep(&data," "); // eat the first token, we already know it :P id = safe_scan_int(&data," \n",-1); if ((mysql=find_identifier(id,CW_MYSQL_ID_CONNID))==NULL) { cw_log(LOG_WARNING,"Invalid connection identifier %d passed in aMYSQL_disconnect\n",id); } else { mysql_close(mysql); del_identifier(id,CW_MYSQL_ID_CONNID); } return 0; }
static int aMYSQL_clear(struct cw_channel *chan, char *data) { MYSQL_RES *mysqlres; int id; strsep(&data," "); // eat the first token, we already know it :P id = safe_scan_int(&data," \n",-1); if ((mysqlres=find_identifier(id,CW_MYSQL_ID_RESID))==NULL) { cw_log(LOG_WARNING,"Invalid result identifier %d passed in aMYSQL_clear\n",id); } else { mysql_free_result(mysqlres); del_identifier(id,CW_MYSQL_ID_RESID); } return 0; }
static int aMYSQL_query(struct cw_channel *chan, char *data) { MYSQL *mysql; MYSQL_RES *mysqlres; char *resultid_var; int connid; char *querystring; strsep(&data," "); // eat the first token, we already know it :P resultid_var = strsep(&data," "); connid = safe_scan_int(&data," ",-1); querystring = strsep(&data,"\n"); if (resultid_var && (connid>=0) && querystring) { if ((mysql=find_identifier(connid,CW_MYSQL_ID_CONNID))!=NULL) { mysql_query(mysql,querystring); if ((mysqlres=mysql_use_result(mysql))!=NULL) { add_identifier_and_set_callweaver_int(chan,resultid_var,CW_MYSQL_ID_RESID,mysqlres); return 0; } else if( mysql_field_count(mysql)==0 ) { return 0; // See http://dev.mysql.com/doc/mysql/en/mysql_field_count.html } else { cw_log(LOG_WARNING,"aMYSQL_query: mysql_store_result() failed on query %s\n",querystring); } } else { cw_log(LOG_WARNING,"aMYSQL_query: Invalid connection identifier %d passed in aMYSQL_query\n",connid); } } else { cw_log(LOG_WARNING,"aMYSQL_query: missing some arguments\n"); } return -1; }
/* 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; } }
/*! @decl void output(object obj, int|void start_pos) *! *! Add an output file object. */ static void pipe_output(INT32 args) { struct object *obj; struct output *o; int fd; struct stat s; struct buffer *b; if (args<1 || sp[-args].type != T_OBJECT || !sp[-args].u.object || !sp[-args].u.object->prog) Pike_error("Bad/missing argument 1 to pipe->output().\n"); if (args==2 && sp[1-args].type != T_INT) Pike_error("Bad argument 2 to pipe->output().\n"); if (THIS->fd==-1) /* no buffer */ { /* test if usable as buffer */ apply(sp[-args].u.object,"query_fd",0); if ((sp[-1].type==T_INT) && (fd=sp[-1].u.integer)>=0 && (fstat(fd,&s)==0) && S_ISREG(s.st_mode) && (THIS->fd=fd_dup(fd))!=-1 ) { /* keep the file pointer of the duped fd */ THIS->pos=fd_lseek(fd, 0L, SEEK_CUR); THIS->living_outputs++; while (THIS->firstbuffer) { b=THIS->firstbuffer; THIS->firstbuffer=b->next; fd_lseek(THIS->fd, THIS->pos, SEEK_SET); fd_write(THIS->fd,b->s->str,b->s->len); sbuffers-=b->s->len; nbuffers--; free_string(b->s); free((char *)b); } THIS->lastbuffer=NULL; /* keep the file pointer of the duped fd THIS->pos=0; */ push_int(0); apply(sp[-args-2].u.object,"set_id", 1); pop_n_elems(args+2); /* ... and from apply x 2 */ return; } pop_stack(); /* from apply */ } THIS->living_outputs++; /* add_ref(THISOBJ); */ /* Weird */ /* Allocate a new struct output */ obj=clone_object(output_program,0); o=(struct output *)(obj->storage); o->next=THIS->firstoutput; THIS->firstoutput=obj; noutputs++; o->obj=NULL; add_ref(o->obj=sp[-args].u.object); o->write_offset=find_identifier("write",o->obj->prog); o->set_nonblocking_offset=find_identifier("set_nonblocking",o->obj->prog); o->set_blocking_offset=find_identifier("set_blocking",o->obj->prog); if (o->write_offset<0 || o->set_nonblocking_offset<0 || o->set_blocking_offset<0) { free_object(o->obj); Pike_error("illegal file object%s%s%s\n", ((o->write_offset<0)?"; no write":""), ((o->set_nonblocking_offset<0)?"; no set_nonblocking":""), ((o->set_blocking_offset<0)?"; no set_blocking":"")); } o->mode=O_RUN; /* keep the file pointer of the duped fd o->pos=0; */ /* allow start position as 2nd argument for additional outputs o->pos=THIS->pos; */ if(args>=2) o->pos=sp[1-args].u.integer; else o->pos=THIS->pos; push_object(obj); /* Ok, David, this is probably correct, but I dare you to explain why :) */ apply(o->obj,"set_id",1); pop_stack(); push_int(0); push_callback(offset_output_write_callback); push_callback(offset_output_close_callback); apply_low(o->obj,o->set_nonblocking_offset,3); pop_stack(); pop_n_elems(args-1); }
/*! @decl void input(object obj) *! *! Add an input file to this pipe. */ static void pipe_input(INT32 args) { struct input *i; int fd=-1; /* Per, one less warning to worry about... */ struct object *obj; if (args<1 || sp[-args].type != T_OBJECT) Pike_error("Bad/missing argument 1 to pipe->input().\n"); obj=sp[-args].u.object; if(!obj || !obj->prog) Pike_error("pipe->input() on destructed object.\n"); push_int(0); apply(sp[-args-1].u.object,"set_id", 1); pop_stack(); i=new_input(); #if defined(HAVE_MMAP) && defined(HAVE_MUNMAP) /* We do not handle mmaps if we have a buffer */ if(THIS->fd == -1) { char *m; struct stat s; apply(obj, "query_fd", 0); if(sp[-1].type == T_INT) fd=sp[-1].u.integer; pop_stack(); if (fd != -1 && fstat(fd,&s)==0) { off_t filep=fd_lseek(fd, 0L, SEEK_CUR); /* keep the file pointer */ size_t len = s.st_size - filep; if(S_ISREG(s.st_mode) /* regular file */ && ((m=(char *)mmap(0, len, PROT_READ, MAP_FILE|MAP_SHARED,fd,filep))+1)) { mmapped += len; i->type=I_MMAP; i->len = len; i->u.mmap=m; #if defined(HAVE_MADVISE) && defined(MADV_SEQUENTIAL) /* Mark the pages as sequential read only access... */ madvise(m, len, MADV_SEQUENTIAL); #endif pop_n_elems(args); push_int(0); return; } } } #endif i->u.obj=obj; nobjects++; i->type=I_OBJ; add_ref(i->u.obj); i->set_nonblocking_offset=find_identifier("set_nonblocking",i->u.obj->prog); i->set_blocking_offset=find_identifier("set_blocking",i->u.obj->prog); if (i->set_nonblocking_offset<0 || i->set_blocking_offset<0) { if (find_identifier("read", i->u.obj->prog) < 0) { /* Not even a read function */ free_object(i->u.obj); i->u.obj=NULL; i->type=I_NONE; nobjects--; Pike_error("illegal file object%s%s\n", ((i->set_nonblocking_offset<0)?"; no set_nonblocking":""), ((i->set_blocking_offset<0)?"; no set_blocking":"")); } else { /* Try blocking mode */ i->type = I_BLOCKING_OBJ; if (i==THIS->firstinput) { /* * FIXME: What if read_som_data() returns 0? */ read_some_data(); } return; } } if (i==THIS->firstinput) { push_callback(offset_input_read_callback); push_int(0); push_callback(offset_input_close_callback); apply_low(i->u.obj,i->set_nonblocking_offset,3); pop_stack(); } else { /* DOESN'T WORK!!! */ push_int(0); push_int(0); push_callback(offset_input_close_callback); apply_low(i->u.obj,i->set_nonblocking_offset,3); pop_stack(); } pop_n_elems(args); push_int(0); }
/*! @decl void create(string|object input, object callbacks, mapping|void entities, mixed|void user_data, int|void input_is_data) */ static void f_create(INT32 args) { struct object *file_obj = NULL, *callbacks = NULL; char *file_name = NULL; struct mapping *entities = NULL; int input_is_data = 0; struct pike_string *input_data = NULL; struct svalue *user_data = NULL; char *missing_method = NULL; switch(args) { case 5: if (ARG(5).type != T_INT) Pike_error("Incorrect type for argument 4: expected an integer\n"); input_is_data = ARG(5).u.integer != 0; /* fall through */ case 4: user_data = &ARG(4); /* fall_through */ case 3: if (ARG(3).type != T_MAPPING) Pike_error("Incorrect type for argument 3: expected a mapping\n"); entities = ARG(3).u.mapping; /* fall through */ case 2: if (ARG(2).type != T_OBJECT) Pike_error("Incorrect type for argument 2: expected an object\n"); callbacks = ARG(2).u.object; add_ref(callbacks); /* fall through */ case 1: if (ARG(1).type != T_OBJECT && ARG(1).type != T_STRING) Pike_error("Incorrect type for argument 1: expected a string or an object\n"); if (ARG(1).type == T_OBJECT) { file_obj = ARG(1).u.object; add_ref(file_obj); } else input_data = ARG(1).u.string; break; default: Pike_error("Incorrect number of arguments: expected between 2 and 4\n"); } /* check whether file_obj is Stdio.File or derived */ if (file_obj && find_identifier("read", file_obj->prog) < 0) Pike_error("Passed file object is not Stdio.File or derived from it\n"); /* The parser state is initialized so that no time is wasted for * callbacks that aren't used by the calling Pike code. */ THIS->sax = (xmlSAXHandler*)calloc(1, sizeof(xmlSAXHandler)); if (!THIS->sax) SIMPLE_OUT_OF_MEMORY_ERROR("create", sizeof(xmlSAXHandler)); /* check whether the callbacks object contains all the required methods * */ if (!is_callback_ok(callbacks, &missing_method)) Pike_error("Passed callbacks object is not valid. The %s method is missing.\n", missing_method); /* choose the parsing method */ if (file_obj) THIS->parsing_method = PARSE_PUSH_PARSER; else if (input_data && input_is_data) THIS->parsing_method = PARSE_MEMORY_PARSER; else if (input_data) THIS->parsing_method = PARSE_FILE_PARSER; else Pike_error("Cannot determine the parser type to use\n"); pop_n_elems(args); /* initialize the parser and state */ switch (THIS->parsing_method) { case PARSE_PUSH_PARSER: THIS->file_obj = file_obj; /* the context creation is delayed in this case */ break; case PARSE_MEMORY_PARSER: case PARSE_FILE_PARSER: copy_shared_string(THIS->input_data, input_data); break; } THIS->callbacks = callbacks; if (user_data) assign_svalue_no_free(&THIS->user_data, user_data); else { THIS->user_data.type = PIKE_T_INT; THIS->user_data.u.integer = 0; THIS->user_data.subtype = 1; } }
/* Our write callback */ static void f__output_write_cb(INT32 args) { NBIO_INT_T written = 0, len = 0; char *buf = NULL; input *inp = THIS->inputs; pop_n_elems(args); DERR(fprintf(stderr, "output write callback\n")); if(THIS->buf_len) { /* We currently have buffered data to write */ len = THIS->buf_len; buf = THIS->buf + THIS->buf_pos; DERR(fprintf(stderr, "Sending buffered data (%ld bytes left)\n", (long)len)); written = do_write(THIS->buf + THIS->buf_pos, THIS->buf_len); switch(written) { case -1: /* We're done here. The write is the weakest link. Goodbye. */ case 0: /* Done, but because the write would block or * nothing was written. I.e try again later. */ set_outp_write_cb(THIS->outp); return; default: /* Write succeeded */ THIS->buf_len -= written; THIS->buf_pos += written; if(THIS->buf_len) { /* We couldn't write everything. Return to try later. */ set_outp_write_cb(THIS->outp); return; } /* We wrote all our buffered data. Just fall through to possibly * write more. */ THIS->buf_pos = 0; THIS->buf_len = 0; } } if(inp == NULL) { finished(); return; } switch(inp->type) { case NBIO_OBJ: /* non-blocking input - if no data available, * just return. once data is available, write_cb will * be called. */ THIS->outp->mode = IDLE; DERR(fprintf(stderr, "Waiting for NB input data.\n")); if(inp->mode == SLEEPING) { /* Set read callback here since object is idle */ push_callback(input_read_cb_off); push_int(0); push_callback(input_close_cb_off); apply_low(THIS->inputs->u.file, THIS->inputs->set_nb_off, 3); inp->mode = READING; } return; case NBIO_STR: buf = inp->u.data->str + inp->pos; len = inp->len - inp->pos; DERR(fprintf(stderr, "Sending string data (%ld bytes left)\n", (long)len)); written = do_write(buf, len); if(written >= 0) { inp->pos += written; if(inp->pos == inp->len) { DERR(fprintf(stderr, "Done sending string input (position == length).\n")); free_input(inp); } set_outp_write_cb(THIS->outp); } break; #ifdef USE_MMAP case NBIO_MMAP: len = inp->u.mmap_storage->m_end - inp->pos; if(!len) { /* need to mmap more data. No need to check if there's more to allocate * since the object would have been freed in that case */ DERR(fprintf(stderr, "mmapping more data from fd %d\n", inp->fd)); len = MIN(inp->len - inp->pos, MAX_MMAP_SIZE); munmap(inp->u.mmap_storage->data, inp->u.mmap_storage->m_len); mmapped -= inp->u.mmap_storage->m_len; DERR(fprintf(stderr, "trying to mmap %ld bytes starting at pos %ld\n", (long)len, (long)inp->pos)); #ifdef TEST_MMAP_FAILOVER inp->u.mmap_storage->data = MAP_FAILED; #else inp->u.mmap_storage->data = (char *)mmap(0, len, PROT_READ, MAP_FILE | MAP_SHARED, inp->fd, inp->pos); #endif if(inp->u.mmap_storage->data == MAP_FAILED) { struct object *tmp; /* FIXME: Better error handling here before falling over to * normal file objects? */ DERR(perror("additional mmap failed")); /* converting to NBIO_OBJ */ THIS->outp->mode = IDLE; tmp = inp->u.mmap_storage->file; free(inp->u.mmap_storage); inp->u.file = tmp; #if TEST_MMAP_FAILOVER == NBIO_BLOCK_OBJ inp->set_nb_off = -1; inp->set_b_off = -1; #else inp->set_nb_off = find_identifier("set_nonblocking",inp->u.file->prog); inp->set_b_off = find_identifier("set_blocking", inp->u.file->prog); #endif 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, "Converting input to NBIO_BLOCK_OBJ.\n")); goto nbio_block_obj_read; } else { DERR(fprintf(stderr, "Converting input to NBIO_OBJ.\n")); inp->type = NBIO_OBJ; /* Fake nonblocking object */ push_callback(input_read_cb_off); push_int(0); push_callback(input_close_cb_off); apply_low(inp->u.file, inp->set_nb_off, 3); inp->mode = READING; } nobjects++; break; } else { inp->u.mmap_storage->m_start = inp->pos; inp->u.mmap_storage->m_len = len; inp->u.mmap_storage->m_end = len + inp->pos; mmapped += len; } } buf = inp->u.mmap_storage->data + (inp->pos - inp->u.mmap_storage->m_start); DERR(fprintf(stderr,"Sending mmapped file (%ld to write, %ld total left)\n" , (long)len, (long)(inp->len - inp->pos))); written = do_write(buf, len); if(written >= 0) { inp->pos += written; if(inp->pos == inp->len){ DERR(fprintf(stderr, "Done sending mmapped input (position == length).\n")); free_input(inp); } set_outp_write_cb(THIS->outp); } #endif break; case NBIO_BLOCK_OBJ: nbio_block_obj_read: { int read; read = read_data(); /* At this point we have no data, so read some */ switch(read) { case -1: /* We are done. No more inputs */ finished(); return; case -2: /* Invalid input for read_data == redo this function */ case -3: /* We read from a fake object and got a string == redo */ f__output_write_cb(0); return; } len = THIS->buf_len; buf = THIS->buf; DERR(fprintf(stderr, "Sending buffered data (%ld bytes left)\n", (long)len)); written = do_write(buf, len); if(written >= 0) { THIS->buf_len -= written; THIS->buf_pos += written; set_outp_write_cb(THIS->outp); } } } if(written < 0) { return; } if(!THIS->buf_len && THIS->inputs == NULL) { finished(); } }
static int aPGSQL_fetch(struct cw_channel *chan, void *data) { char *s1,*s2,*fetchid_var,*s4,*s5,*s6,*s7; char s[100]; char *var; int l; int res; PGresult *PGSQLres; int id,id1,i,j,fnd; int *lalares=NULL; int nres; struct cw_var_t *variables; struct varshead *headp; char *stringp=NULL; headp=&chan->varshead; res=0; l=strlen(data)+2; s7=NULL; s1=malloc(l); s2=malloc(l); strncpy(s1, data, l - 1); stringp=s1; strsep(&stringp," "); /* eat the first token, we already know it :P */ fetchid_var=strsep(&stringp," "); while (1) { /* ugly trick to make branches with break; */ var=fetchid_var; /* fetchid */ fnd=0; CW_LIST_TRAVERSE(headp,variables,entries) { if (strncasecmp(cw_var_name(variables),fetchid_var,strlen(fetchid_var))==0) { s7=cw_var_value(variables); fnd=1; break; } } if (fnd==0) { s7="0"; pbx_builtin_setvar_helper(chan,fetchid_var,s7); } s4=strsep(&stringp," "); id=atoi(s4); /* resultid */ if ((PGSQLres=find_identifier(id,CW_PGSQL_ID_RESID))==NULL) { cw_log(LOG_WARNING,"Invalid result identifier %d passed in aPGSQL_fetch\n",id); res=-1; break; } id=atoi(s7); /*fetchid */ if ((lalares=find_identifier(id,CW_PGSQL_ID_FETCHID))==NULL) { i=0; /* fetching the very first row */ } else { i=*lalares; free(lalares); del_identifier(id,CW_PGSQL_ID_FETCHID); /* will re-add it a bit later */ } if (i<PQntuples(PGSQLres)) { nres=PQnfields(PGSQLres); cw_log(LOG_WARNING,"cw_PGSQL_fetch : nres = %d i = %d ;\n",nres,i); for (j=0; j<nres; j++) { s5=strsep(&stringp," "); if (s5==NULL) { cw_log(LOG_WARNING,"cw_PGSQL_fetch : More tuples (%d) than variables (%d)\n",nres,j); break; } s6=PQgetvalue(PGSQLres,i,j); if (s6==NULL) { cw_log(LOG_WARNING,"PWgetvalue(res,%d,%d) returned NULL in cw_PGSQL_fetch\n",i,j); break; } cw_log(LOG_WARNING,"===setting variable '%s' to '%s'\n",s5,s6); pbx_builtin_setvar_helper(chan,s5,s6); } lalares=malloc(sizeof(int)); *lalares = ++i; /* advance to the next row */ id1 = add_identifier(CW_PGSQL_ID_FETCHID,lalares); } else { cw_log(LOG_WARNING,"cw_PGSQL_fetch : EOF\n"); id1 = 0; /* no more rows */ } snprintf(s, sizeof(s), "%d", id1); cw_log(LOG_WARNING,"Setting var '%s' to value '%s'\n",fetchid_var,s); pbx_builtin_setvar_helper(chan,fetchid_var,s); break; } free(s1); free(s2); return(res); }