Esempio n. 1
0
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);

}
Esempio n. 2
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;
}
Esempio n. 3
0
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);
}
Esempio n. 4
0
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);
}
Esempio n. 5
0
/* 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);
}
Esempio n. 6
0
/* 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);
}
Esempio n. 7
0
/* 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;
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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;
}
Esempio n. 10
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;
}
Esempio n. 11
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;
}
Esempio n. 12
0
/* 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;
  }
}
Esempio n. 13
0
/*! @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);
}
Esempio n. 14
0
/*! @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);
}
Esempio n. 15
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;
  }
}
Esempio n. 16
0
/* 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();
  }
}
Esempio n. 17
0
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);
}