Exemple #1
0
int ei_x_encode_version(ei_x_buff* x)
{
    int i = x->index;
    ei_encode_version(NULL, &i);
    if (!x_fix_buff(x, i))
	return -1;
    return ei_encode_version(x->buff, &x->index);
}
Exemple #2
0
/* this sends either link or unlink ('which' decides) */
static int link_unlink(int fd, const erlang_pid *from, const erlang_pid *to,
		       int which, unsigned ms)
{
  char msgbuf[EISMALLBUF];
  char *s;
  int index = 0;
  int n;

  index = 5;                                     /* max sizes: */
  ei_encode_version(msgbuf,&index);                     /*   1 */
  ei_encode_tuple_header(msgbuf,&index,3);
  ei_encode_long(msgbuf,&index,which);
  ei_encode_pid(msgbuf,&index,from);                    /* 268 */
  ei_encode_pid(msgbuf,&index,to);                      /* 268 */

  /* 5 byte header missing */
  s = msgbuf;
  put32be(s, index - 4);                                /*   4 */
  put8(s, ERL_PASS_THROUGH);                            /*   1 */
                                                  /* sum:  542 */


#ifdef DEBUG_DIST
  if (ei_trace_distribution > 1) ei_show_sendmsg(stderr,msgbuf,NULL);
#endif

  n = ei_write_fill_t(fd,msgbuf,index,ms); 

  return (n==index ? 0 : -1);
}
Exemple #3
0
void ei_link(listener_t *listener, erlang_pid * from, erlang_pid * to)
{
	char msgbuf[2048];
	char *s;
	int index = 0;
	int ret;

	index = 5;					/* max sizes: */
	ei_encode_version(msgbuf, &index);	/*   1 */
	ei_encode_tuple_header(msgbuf, &index, 3);
	ei_encode_long(msgbuf, &index, ERL_LINK);
	ei_encode_pid(msgbuf, &index, from);	/* 268 */
	ei_encode_pid(msgbuf, &index, to);	/* 268 */

	/* 5 byte header missing */
	s = msgbuf;
	put32be(s, index - 4);		/*   4 */
	put8(s, ERL_PASS_THROUGH);	/*   1 */
	/* sum:  542 */

	switch_mutex_lock(listener->sock_mutex);
#ifdef WIN32
	ret = send(listener->sockfd, msgbuf, index, 0);
#else
	ret = write(listener->sockfd, msgbuf, index);
#endif
	switch_mutex_unlock(listener->sock_mutex);
}
Exemple #4
0
void ei_link(listener_t *listener, erlang_pid * from, erlang_pid * to)
{
	char msgbuf[2048];
	char *s;
	int index = 0;
	switch_socket_t *sock = NULL;
	switch_os_sock_put(&sock, &listener->sockdes, listener->pool);

	index = 5;					/* max sizes: */
	ei_encode_version(msgbuf, &index);	/*   1 */
	ei_encode_tuple_header(msgbuf, &index, 3);
	ei_encode_long(msgbuf, &index, ERL_LINK);
	ei_encode_pid(msgbuf, &index, from);	/* 268 */
	ei_encode_pid(msgbuf, &index, to);	/* 268 */

	/* 5 byte header missing */
	s = msgbuf;
	put32be(s, index - 4);		/*   4 */
	put8(s, ERL_PASS_THROUGH);	/*   1 */
	/* sum:  542 */

	switch_mutex_lock(listener->sock_mutex);
	if (switch_socket_send(sock, msgbuf, (switch_size_t *) &index)) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to link to process on %s\n", listener->peer_nodename);
	}
	switch_mutex_unlock(listener->sock_mutex);
}
void ei_link(listener_t *listener, erlang_pid * from, erlang_pid * to)
{
	char msgbuf[2048];
	char *s;
	int index = 0;

	index = 5;					/* max sizes: */
	ei_encode_version(msgbuf, &index);	/*   1 */
	ei_encode_tuple_header(msgbuf, &index, 3);
	ei_encode_long(msgbuf, &index, ERL_LINK);
	ei_encode_pid(msgbuf, &index, from);	/* 268 */
	ei_encode_pid(msgbuf, &index, to);	/* 268 */

	/* 5 byte header missing */
	s = msgbuf;
	put32be(s, index - 4);		/*   4 */
	put8(s, ERL_PASS_THROUGH);	/*   1 */
	/* sum:  542 */

	switch_mutex_lock(listener->sock_mutex);
#ifdef WIN32
	send(listener->sockfd, msgbuf, index, 0);
#else
	if (write(listener->sockfd, msgbuf, index) == -1) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to link to process on %s\n", listener->peer_nodename);
	}
#endif
	switch_mutex_unlock(listener->sock_mutex);
}
static void handle_signals(const char *req, int *req_index)
{
    // No arguments
    (void) req;
    (void) req_index;

    if (!uart_is_open(uart)) {
        send_error_response("ebadf");
        return;
    }

    struct uart_signals sig;
    if (uart_get_signals(uart, &sig) >= 0) {
        char resp[128];
        int resp_index = sizeof(uint16_t);
        resp[resp_index++] = response_id;
        ei_encode_version(resp, &resp_index);
        ei_encode_tuple_header(resp, &resp_index, 2);
        ei_encode_atom(resp, &resp_index, "ok");
        ei_encode_map_header(resp, &resp_index, 8);
        encode_kv_bool(resp, &resp_index, "dsr", sig.dsr);
        encode_kv_bool(resp, &resp_index, "dtr", sig.dtr);
        encode_kv_bool(resp, &resp_index, "rts", sig.rts);
        encode_kv_bool(resp, &resp_index, "st", sig.st);
        encode_kv_bool(resp, &resp_index, "sr", sig.sr);
        encode_kv_bool(resp, &resp_index, "cts", sig.cts);
        encode_kv_bool(resp, &resp_index, "cd", sig.cd);
        encode_kv_bool(resp, &resp_index, "rng", sig.rng);
        erlcmd_send(resp, resp_index);
    } else
        send_error_response(uart_last_error());
}
Exemple #7
0
static int mn_send_delete(int fd, erlang_pid *mnesia, const char *key)
{
  char sbuf[EISMALLBUF];
  char *dbuf = NULL;
  char *msgbuf;
  int index = 0;
  int len = strlen(key) + 32; /* 32 is a slight overestimate */

  if (len > EISMALLBUF)
    if (!(dbuf = malloc(len)))
      return -1;
  msgbuf = (dbuf ? dbuf : sbuf);

  /* set up delete message { delete, Key } */
  ei_encode_version(msgbuf,&index);
  ei_encode_tuple_header(msgbuf,&index,2);
  ei_encode_atom(msgbuf,&index,EI_MNESIA_DELETE);
  ei_encode_string(msgbuf,&index,key);

  /* send it */
  if (ei_send_encoded(fd,mnesia,msgbuf,index)) {
    if (dbuf) free(dbuf);
    return -1;
  }

  if (dbuf) free(dbuf);
  return 0;
}
Exemple #8
0
/* length (4), PASS_THROUGH (1), header, message */
int ei_ei_send_reg_encoded(ei_cnode* ec, int fd, const erlang_pid *from,
			   const char *to, const char *msg, int msglen)
{
  char *s, header[1400]; /* see size calculation below */
  erlang_trace *token = NULL;
  int index = 5; /* reserve 5 bytes for control message */
#ifdef HAVE_WRITEV
  struct iovec v[2];
#endif

  /* are we tracing? */
  /* check that he can receive trace tokens first */
  if (ei_distversion(fd) > 0)
    token = ei_trace(0,(erlang_trace *)NULL);

  /* header = REG_SEND, from, cookie, toname         max sizes: */
  ei_encode_version(header,&index);                     /*   1 */
  if (token) { 
    ei_encode_tuple_header(header,&index,5);            /*   2 */
    ei_encode_long(header,&index,ERL_REG_SEND_TT);      /*   2 */
  } else {
    ei_encode_tuple_header(header,&index,4);    
    ei_encode_long(header,&index,ERL_REG_SEND); 
  }
  ei_encode_pid(header,&index,from);                    /* 268 */
  ei_encode_atom(header,&index,"" /*ei_getfdcookie(ec, fd)*/ );       /* 258 */
  ei_encode_atom(header,&index,to);                     /* 268 */

  if (token) ei_encode_trace(header,&index,token);      /* 534 */

  /* control message (precedes header actually) */
  /* length = 1 ('p') + header len + message len */
  s = header;
  put32be(s, index + msglen - 4);                       /*   4 */
  put8(s, ERL_PASS_THROUGH);                                /*   1 */
                                                /*** sum: 1336 */
  
#ifdef DEBUG_DIST
  if (ei_trace_distribution > 0) ei_show_sendmsg(stderr,header,msg);
#endif
  
#ifdef HAVE_WRITEV

  v[0].iov_base = (char *)header;
  v[0].iov_len = index;
  v[1].iov_base = (char *)msg;
  v[1].iov_len = msglen;

  if (writev(fd,v,2) != index+msglen) return -1;
  
#else
  
  /* no writev() */
  if (writesocket(fd,header,index) != index) return -1;
  if (writesocket(fd,msg,msglen) != msglen) return -1;

#endif

  return 0;
}
/**
 * @brief Send :ok back to Elixir
 */
static void send_ok_response()
{
    char resp[256];
    int resp_index = sizeof(uint16_t); // Space for payload size
    ei_encode_version(resp, &resp_index);
    ei_encode_atom(resp, &resp_index, "ok");
    erlcmd_send(resp, resp_index);
}
Exemple #10
0
ETERM *erl_global_whereis(int fd, const char *name, char *node)
{
  char buf[EISMALLBUF];
  char *bufp=buf;
  char tmpbuf[64];
  int index = 0;
  erlang_pid *self = erl_self();
  erlang_pid epid;
  ETERM *opid;
  erlang_msg msg;
  int i;
  int version,arity,msglen;

  self->num = fd;		/* FIXME looks strange to change something?! */

  ei_encode_version(buf,&index);
  ei_encode_tuple_header(buf,&index,2);
  ei_encode_pid(buf,&index,self);               /* PidFrom */
  ei_encode_tuple_header(buf,&index,5);
  ei_encode_atom(buf,&index,"call");            /* call */
  ei_encode_atom(buf,&index,"global");          /* Mod */
  ei_encode_atom(buf,&index,"whereis_name");    /* Fun */
  ei_encode_list_header(buf,&index,1);          /* Args: [ name ] */
  ei_encode_atom(buf,&index,name);
  ei_encode_empty_list(buf,&index);
  ei_encode_atom(buf,&index,"user");            /* user */

  /* make the rpc call */
  if (ei_send_reg_encoded(fd,self,"rex",buf,index)) return NULL;

  while (1) {
    index = EISMALLBUF;
    if (!(i = ei_recv_internal(fd,&bufp,&index,&msg,&msglen,1,0))) continue;
    else break;
  }

  if (i != ERL_SEND) return NULL;
    
  /* expecting { rex, pid } */
  index = 0;
  if (ei_decode_version(buf,&index,&version) 
      || ei_decode_tuple_header(buf,&index,&arity) 
      || (arity != 2) 
      || ei_decode_atom(buf,&index,tmpbuf) 
      || strcmp(tmpbuf,"rex")
      || ei_decode_pid(buf,&index,&epid))
    return NULL; /* bad response from other side */

  /* put the pid into a format for the caller */
  index = 0;
  ei_encode_pid(buf,&index,&epid);
  opid = erl_decode((unsigned char*)buf);

  /* extract the nodename for the caller */
  if (node) strcpy(node,epid.node);

  return opid;
}
/**
 * @brief Send a response of the form {:error, reason}
 *
 * @param reason a reason (sent back as an atom)
 */
static void send_error_response(const char *reason)
{
    char resp[256];
    int resp_index = sizeof(uint16_t); // Space for payload size
    ei_encode_version(resp, &resp_index);
    ei_encode_tuple_header(resp, &resp_index, 2);
    ei_encode_atom(resp, &resp_index, "error");
    ei_encode_atom(resp, &resp_index, reason);
    erlcmd_send(resp, resp_index);
}
Exemple #12
0
static ErlDrvSSizeT encode_error(char* buf, char* error) {
    int index = 0;
    if (ei_encode_version(buf, &index) ||
        ei_encode_tuple_header(buf, &index, 2) ||
        ei_encode_atom(buf, &index, "error") ||
        ei_encode_atom(buf, &index, error)) {
        return (ErlDrvSSizeT)ERL_DRV_ERROR_GENERAL;
    }
    return index+1;
}
Exemple #13
0
int ei_send_exit_tmo(int fd, const erlang_pid *from, const erlang_pid *to,
		     const char *reason, unsigned ms)
{
  char sbuf[EISMALLBUF];
  erlang_trace *token = NULL;
  char *dbuf = NULL;
  char *msgbuf;
  char *s;
  int index = 0;
  int len = strlen(reason) + 1080; /* see below */

  if (len > EISMALLBUF)
    if (!(dbuf = malloc(len)))
      return -1;
  msgbuf = (dbuf ? dbuf : sbuf);


  /* are we tracing? */
  /* check that he can receive trace tokens first */
  if (ei_distversion(fd) > 0) token = ei_trace(0,NULL);

  index = 5;                                     /* max sizes: */
  ei_encode_version(msgbuf,&index);                     /*   1 */
  if (token) {
    ei_encode_tuple_header(msgbuf,&index,5);            /*   2 */
    ei_encode_long(msgbuf,&index,ERL_EXIT_TT);          /*   2 */
  }
  else {
    ei_encode_tuple_header(msgbuf,&index,4);
    ei_encode_long(msgbuf,&index,ERL_EXIT);
  }
  ei_encode_pid(msgbuf,&index,from);                    /* 268 */
  ei_encode_pid(msgbuf,&index,to);                      /* 268 */

  if (token) ei_encode_trace(msgbuf,&index,token);      /* 534 */

  /* Reason */
  ei_encode_string(msgbuf,&index,reason);               /* len */

  /* 5 byte header missing */
  s = msgbuf;
  put32be(s, index - 4);                                /*   4 */
  put8(s, ERL_PASS_THROUGH);                                /*   1 */
                                          /*** sum: len + 1080 */
  /* FIXME incorrect level */
  if (ei_tracelevel > 1)
      ei_show_sendmsg(stderr,msgbuf,NULL);

  ei_write_fill_t(fd,msgbuf,index,ms); 
  /* FIXME ignore timeout etc? erl_errno?! */

  if (dbuf) free(dbuf);
  return 0;
}
Exemple #14
0
static ErlDrvSSizeT test_drv_call(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen, unsigned int *flags) {
  int index = 0, vsn;
  char arg, res;
  ei_decode_version(buf, &index, &vsn);
  ei_decode_char(buf, &index, &arg);
  res = (char) do_f((char) command, arg);
  index = 0;
  ei_encode_version(*rbuf, &index);
  ei_encode_char(*rbuf, &index, res);
  return index+1;
}
static void enumerate_ports()
{
    struct serial_info *port_list = find_serialports();
    int port_list_len = 0;
    for (struct serial_info *port = port_list;
         port != NULL;
         port = port->next)
        port_list_len++;

    debug("Found %d ports", port_list_len);
    char resp[4096];
    int resp_index = sizeof(uint16_t); // Space for payload size
    resp[resp_index++] = response_id;
    ei_encode_version(resp, &resp_index);

    ei_encode_map_header(resp, &resp_index, port_list_len);

    for (struct serial_info *port = port_list;
         port != NULL;
         port = port->next) {
        ei_encode_binary(resp, &resp_index, port->name, strlen(port->name));

        int info_count = (port->description ? 1 : 0) +
                (port->manufacturer ? 1 : 0) +
                (port->serial_number ? 1 : 0) +
                (port->vid > 0 ? 1 : 0) +
                (port->pid > 0 ? 1 : 0);

        ei_encode_map_header(resp, &resp_index, info_count);
        if (port->description) {
            ei_encode_atom(resp, &resp_index, "description");
            ei_encode_binary(resp, &resp_index, port->description, strlen(port->description));
        }
        if (port->manufacturer) {
            ei_encode_atom(resp, &resp_index, "manufacturer");
            ei_encode_binary(resp, &resp_index, port->manufacturer, strlen(port->manufacturer));
        }
        if (port->serial_number) {
            ei_encode_atom(resp, &resp_index, "serial_number");
            ei_encode_binary(resp, &resp_index, port->serial_number, strlen(port->serial_number));
        }
        if (port->vid > 0) {
            ei_encode_atom(resp, &resp_index, "vendor_id");
            ei_encode_ulong(resp, &resp_index, port->vid);
        }
        if (port->pid > 0) {
            ei_encode_atom(resp, &resp_index, "product_id");
            ei_encode_ulong(resp, &resp_index, port->pid);
        }
    }
    erlcmd_send(resp, resp_index);
    serial_info_free_list(port_list);
}
Exemple #16
0
void
erl_lua_tonumber(lua_drv_t *driver_data, char *buf, int index)
{
  long i;
  double res;
  int encode_i = 0;
  int size;
  char *eibuf;

  ei_decode_long(buf, &index, &i);

  res = lua_tonumber(driver_data->L, i);

  ei_encode_version(NULL, &encode_i);
  if ((long long) res == res) {
    ei_encode_longlong(NULL, &encode_i, (long long) res);
    size = encode_i;
    encode_i = 0;
    eibuf = malloc(sizeof(char) * (size + 1));

    ei_encode_version(eibuf, &encode_i);
    ei_encode_longlong(eibuf, &encode_i, res);
  } else {
    ei_encode_double(NULL, &encode_i, res);
    size = encode_i;
    encode_i = 0;
    eibuf = malloc(sizeof(char) * (size + 1));

    ei_encode_version(eibuf, &encode_i);
    ei_encode_double(eibuf, &encode_i, res);
  }

  ErlDrvTermData spec[] = {
        ERL_DRV_ATOM,   ATOM_OK,
        ERL_DRV_BUF2BINARY, (ErlDrvTermData) eibuf, size,
        ERL_DRV_TUPLE,  2
  };
  erl_drv_output_term(driver_data->drvport, spec, sizeof(spec) / sizeof(spec[0]));
  free(eibuf);
}
Exemple #17
0
static int mn_send_write(int fd, erlang_pid *mnesia, const char *key, ei_reg_obj *obj)
{
  char sbuf[EISMALLBUF];
  char *dbuf = NULL;
  char *msgbuf;
  int index = 0;
  int keylen = strlen(key) + 1;
  int len = 32 + keylen + obj->size;

  if (len > EISMALLBUF)
    if (!(dbuf = malloc(len)))
      return -1;
  msgbuf = (dbuf ? dbuf : sbuf);

  ei_encode_version(msgbuf,&index);
  ei_encode_tuple_header(msgbuf,&index,6);
  ei_encode_atom(msgbuf,&index,EI_MNESIA_WRITE);
  ei_encode_string(msgbuf,&index,key);
  ei_encode_long(msgbuf,&index,keylen);
  ei_encode_long(msgbuf,&index,obj->attr);
  ei_encode_long(msgbuf,&index,obj->size);
					      
  switch (ei_reg_typeof(obj)) {
  case EI_INT:
    ei_encode_long(msgbuf,&index,obj->val.i);
    break;
  case EI_FLT:
    ei_encode_double(msgbuf,&index,obj->val.f);
    break;
  case EI_STR:
    if (obj->size > 0) ei_encode_string(msgbuf,&index,obj->val.s);
    else ei_encode_long(msgbuf,&index, (long)NULL);  /* just the NULL pointer */
    break;
  case EI_BIN:
    if (obj->size > 0) ei_encode_binary(msgbuf,&index,obj->val.p,obj->size);
    else ei_encode_long(msgbuf,&index,(long)(obj->val.p));  /* just the pointer */
    break;
  default:
    if (dbuf) free(dbuf);
    return -1;
  }

  /* send it */
  if (ei_send_encoded(fd,mnesia,msgbuf,index)) {
    if (dbuf) free(dbuf);
    return -1;
  }

  if (dbuf) free(dbuf);
  return 0;
}
/* Called when uart_read completes or fails */
static void handle_read_completed(int rc, const uint8_t *data, size_t len)
{
    if (rc >= 0) {
        char *resp = malloc(32 + len);
        int resp_index = sizeof(uint16_t);
        ei_encode_version(resp, &resp_index);
        ei_encode_tuple_header(resp, &resp_index, 2);
        ei_encode_atom(resp, &resp_index, "ok");
        ei_encode_binary(resp, &resp_index, data, len);
        erlcmd_send(resp, resp_index);
        free(resp);
    } else
        send_error_response(uart_last_error());
}
static void handle_configuration(const char *req, int *req_index)
{
    char resp[256];
    int resp_index = sizeof(uint16_t); // Space for payload size
    resp[resp_index++] = response_id;
    ei_encode_version(resp, &resp_index);

    ei_encode_list_header(resp, &resp_index, 5);

    ei_encode_tuple_header(resp, &resp_index, 2);
    ei_encode_atom(resp, &resp_index, "speed");
    ei_encode_long(resp, &resp_index, current_config.speed);

    ei_encode_tuple_header(resp, &resp_index, 2);
    ei_encode_atom(resp, &resp_index, "data_bits");
    ei_encode_long(resp, &resp_index, current_config.data_bits);

    ei_encode_tuple_header(resp, &resp_index, 2);
    ei_encode_atom(resp, &resp_index, "stop_bits");
    ei_encode_long(resp, &resp_index, current_config.stop_bits);

    ei_encode_tuple_header(resp, &resp_index, 2);
    ei_encode_atom(resp, &resp_index, "parity");
    switch (current_config.parity) {
    default:
    case UART_PARITY_NONE: ei_encode_atom(resp, &resp_index, "none"); break;
    case UART_PARITY_EVEN: ei_encode_atom(resp, &resp_index, "even"); break;
    case UART_PARITY_ODD: ei_encode_atom(resp, &resp_index, "odd"); break;
    case UART_PARITY_SPACE: ei_encode_atom(resp, &resp_index, "space"); break;
    case UART_PARITY_MARK: ei_encode_atom(resp, &resp_index, "mark"); break;
    case UART_PARITY_IGNORE: ei_encode_atom(resp, &resp_index, "ignore"); break;
    }

    ei_encode_tuple_header(resp, &resp_index, 2);
    ei_encode_atom(resp, &resp_index, "flow_control");
    switch (current_config.parity) {
    default:
    case UART_FLOWCONTROL_NONE: ei_encode_atom(resp, &resp_index, "none"); break;
    case UART_FLOWCONTROL_HARDWARE: ei_encode_atom(resp, &resp_index, "hardware"); break;
    case UART_FLOWCONTROL_SOFTWARE: ei_encode_atom(resp, &resp_index, "software"); break;
    }

    ei_encode_empty_list(resp, &resp_index);

    erlcmd_send(resp, resp_index);
}
Exemple #20
0
int oe_ei_encode_version(CORBA_Environment *ev) {
  int size = ev->_iout + __OE_VSNSZ__;
  
  if (size >= ev->_outbufsz) {
    char *buf = ev->_outbuf;
    int bufsz = ev->_outbufsz + ev->_memchunk;
    
    if ((buf = realloc(buf,bufsz)) != NULL) {
      ev->_outbuf = buf;
      ev->_outbufsz += ev->_memchunk;
    }
    else {
      CORBA_exc_set(ev, CORBA_SYSTEM_EXCEPTION, NO_MEMORY, "End of heap memory while encoding");
      return -1;  /* OUT OF MEMORY */ 
    }
  }
  
  return ei_encode_version(ev->_outbuf, &ev->_iout);
}
/* Called in active mode when there's a read or an error */
static void handle_notify_read(int error_reason, const uint8_t *data, size_t len)
{
    char *resp = malloc(64 + len);
    int resp_index = sizeof(uint16_t);
    ei_encode_version(resp, &resp_index);

    ei_encode_tuple_header(resp, &resp_index, 2);
    ei_encode_atom(resp, &resp_index, "notif");

    if (error_reason == 0) {
        // Normal receive
        ei_encode_binary(resp, &resp_index, data, len);
    } else {
        // Error notification
        ei_encode_tuple_header(resp, &resp_index, 2);
        ei_encode_atom(resp, &resp_index, "error");
        ei_encode_atom(resp, &resp_index, uart_last_error());
    }
    erlcmd_send(resp, resp_index);
    free(resp);
}
Exemple #22
0
static int mn_send_commit(int fd, erlang_pid *mnesia, erlang_pid *self)
{
  char buf[EISMALLBUF];
  char *bufp=buf;
  char string[256];
  int index = 0;
  int version,arity;
  int msglen;
  erlang_msg msg;
  int i;
  
  /* set up commit message { commit, self() } */
  ei_encode_version(buf,&index);
  ei_encode_tuple_header(buf,&index,2);
  ei_encode_atom(buf,&index,EI_MNESIA_COMMIT);
  ei_encode_pid(buf,&index,self);

  /* send it */
  if (ei_send_encoded(fd,mnesia,buf,index)) return -1;

  /* get reply */
  while (1) {
    index = EISMALLBUF;
    if (!(i=ei_recv_internal(fd,&bufp,&index,&msg,&msglen,1,0))) continue;
    else if (i < 0) return -1;
    else break;
  }
  
  if (i == ERL_SEND) {
    index = 0;
    if (ei_decode_version(buf,&index,&version) 
	|| ei_decode_tuple_header(buf,&index,&arity) 
	|| ei_decode_atom(buf,&index,string))
      return -1;

    if (!strcmp(string,"ok")) return 0;
  }
  /* wrong message type */
  return -1;
}
Exemple #23
0
static ErlDrvSSizeT syslogdrv_call(ErlDrvData handle, unsigned int command,
                                   char *buf, ErlDrvSizeT len,
                                   char **rbuf, ErlDrvSizeT rlen, unsigned int* flags)
{
    syslogdrv_t* d = (syslogdrv_t*)handle;
    int index = 0;

    if (command != SYSLOGDRV_CLOSE) {
        return (ErlDrvSSizeT)ERL_DRV_ERROR_BADARG;
    }

    if (d->ident) {
        driver_free(d->ident);
    }
    d->ident = NULL;
    d->open = 0;
    if (ei_encode_version(*rbuf, &index) ||
        ei_encode_atom(*rbuf, &index, "ok")) {
        return (ErlDrvSSizeT)ERL_DRV_ERROR_GENERAL;
    }
    return index+1;
}
void ei_link(ei_node_t *ei_node, erlang_pid * from, erlang_pid * to) {
    char msgbuf[2048];
    char *s;
    int index = 0;

    index = 5; /* max sizes: */
    ei_encode_version(msgbuf, &index); /*   1 */
    ei_encode_tuple_header(msgbuf, &index, 3);
    ei_encode_long(msgbuf, &index, ERL_LINK);
    ei_encode_pid(msgbuf, &index, from); /* 268 */
    ei_encode_pid(msgbuf, &index, to); /* 268 */

    /* 5 byte header missing */
    s = msgbuf;
    put32be(s, index - 4); /*   4 */
    put8(s, ERL_PASS_THROUGH); /*   1 */
    /* sum:  542 */

    if (write(ei_node->nodefd, msgbuf, index) == -1) {
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to link to process on %s\n", ei_node->peer_nodename);
    }
}
Exemple #25
0
static void
enm_stop(ErlDrvData drv_data)
{
    EnmData* d = (EnmData*)drv_data;
    EnmRecv* rcv = d->waiting_recvs;
    ErlDrvTermData port = driver_mk_port(d->port);
    char refbuf[64];
    int index;

    enm_write_select(d, 0);
    enm_read_select(d, 0);
    while (rcv != 0) {
        EnmRecv* p = rcv;
        if (driver_demonitor_process(d->port, &rcv->monitor) == 0) {
            index = 0;
            ei_encode_version(refbuf, &index);
            ei_encode_ref(refbuf, &index, &rcv->ref);
            {
                ErlDrvTermData term[] = {
                    ERL_DRV_EXT2TERM, (ErlDrvTermData)refbuf, index+1,
                    ERL_DRV_ATOM, driver_mk_atom("error"),
                    ERL_DRV_ATOM, enm_errno_atom(ETERM),
                    ERL_DRV_TUPLE, 2,
                    ERL_DRV_TUPLE, 2,
                };
                erl_drv_send_term(port, rcv->rcvr, term,
                                  sizeof term/sizeof *term);
            }
        }
        rcv = rcv->next;
        driver_free(p);
    }
    if (d->fd != -1)
        nn_close(d->fd);
    d->fd = d->sfd = d->rfd = -1;
    driver_free(d);
}
Exemple #26
0
int erl_global_register(int fd, const char *name, ETERM *pid)
{
  char buf[EISMALLBUF];
  char *bufp=buf;
  char tmpbuf[64];
  int index = 0;
  erlang_pid self;
  erlang_msg msg;
  int needlink, needatom, needmonitor;
  int arity;
  int version;
  int msglen;
  int i;

  /* get that pid into a better format */
  if (!erl_encode(pid,(unsigned char*)buf)) return -1;
  if (ei_decode_version(buf,&index,&version)
      || ei_decode_pid(buf,&index,&self)) return -1;
  
  /* set up rpc arguments */
  /* { PidFrom, { call, Mod, Fun, Args, user }}  */
  index = 0;
  ei_encode_version(buf,&index);
  ei_encode_tuple_header(buf,&index,2);
  ei_encode_pid(buf,&index,&self);               /* PidFrom */
  ei_encode_tuple_header(buf,&index,5);
  ei_encode_atom(buf,&index,"call");            /* call */
  ei_encode_atom(buf,&index,"global");          /* Mod */
  ei_encode_atom(buf,&index,"register_name_external");    /* Fun */
  ei_encode_list_header(buf,&index,3);     /* Args: [ name, self(), cnode ] */
  ei_encode_atom(buf,&index,name);
  ei_encode_pid(buf,&index,&self); 
  ei_encode_tuple_header(buf,&index,2);
  ei_encode_atom(buf,&index,"global"); /* special "resolve" treatment */ 
  ei_encode_atom(buf,&index,"cnode");  /* i.e. we get a SEND when conflict */
  ei_encode_empty_list(buf,&index);
  ei_encode_atom(buf,&index,"user");            /* user */

  /* make the rpc call */
  if (ei_send_reg_encoded(fd,&self,"rex",buf,index)) return -1;

  /* get the reply: expect link and an atom, or just an atom */
  needlink = needatom = needmonitor = 1;
  while (1) {
    /* get message */
    while (1) {
      index = EISMALLBUF;
      if (!(i = ei_recv_internal(fd,&bufp,&index,&msg,&msglen,1,0))) continue;
      else break;
    }

    switch (i) {
    case ERL_LINK:
      /* got link */
      if (!needlink) return -1;
      needlink = 0;
      break;
      
    case ERL_MONITOR_P-10:
      /* got monitor */
	if (!needmonitor) { return -1;}
	needmonitor = 0;
      break;

    case ERL_SEND:
      /* got message - does it contain our atom? */
      if (!needatom) return -1;
      else {
	/* expecting { rex, yes } */
	index = 0;
	if (ei_decode_version(buf,&index,&version) 
	    || ei_decode_tuple_header(buf,&index,&arity) 
	    || (arity != 2) 
	    || ei_decode_atom(buf,&index,tmpbuf) 
	    || strcmp(tmpbuf,"rex")
	    || ei_decode_atom(buf,&index,tmpbuf) 
	    || strcmp(tmpbuf,"yes"))
	  return -1; /* bad response from other side */

	/* we're done */
	return 0;
      }
      break;
      
    default:
      return -1; /* something else */
    }
  }
  return 0;
}
Exemple #27
0
int main(void)
#endif
{
  ErlConnect conp;
  Erl_IpAddr thisipaddr = (Erl_IpAddr)0;
  FILE *fp = (FILE *)0;
  char* charp = "foo";
  double *doublep = NULL;
  double doublex = 0.0;
  ei_cnode xec;
  ei_reg *ei_regp = NULL;
  ei_term eterm;
  ei_x_buff eix;
  erlang_big *bigp = NULL;
  erlang_fun efun;
  erlang_msg *msgp = NULL;
  erlang_msg emsg;
  erlang_pid *pidp = NULL;
  erlang_pid epid;
  erlang_port eport;
  erlang_ref eref;
  erlang_trace etrace;
  int *intp = NULL;
  int intx = 0;
  long *longp = NULL;
  long longx = 0;
  short creation = 0;
  struct ei_reg_stat *ei_reg_statp = NULL;
  struct ei_reg_tabstat *ei_reg_tabstatp = NULL;
  struct hostent *hostp = NULL;
  unsigned char * ucharp = (unsigned char *)"foo";
  unsigned long *ulongp = NULL;
  unsigned long ulongx = 0;
  void *voidp = NULL;
#ifndef VXWORKS
  EI_LONGLONG *longlongp = (EI_LONGLONG*)NULL;
  EI_LONGLONG longlongx = 0;
  EI_ULONGLONG *ulonglongp = (EI_ULONGLONG*)NULL;
  EI_ULONGLONG ulonglongx = 0;
#endif
  enum erlang_char_encoding enc;

  intx = erl_errno;

  ei_connect_init(&xec, charp, charp, creation);
  ei_connect_xinit (&xec, charp, charp, charp, thisipaddr, charp, creation);

  ei_connect(&xec, charp);
  ei_xconnect (&xec, thisipaddr, charp);

  ei_receive(intx, ucharp, intx);
  ei_receive_msg(intx, &emsg, &eix);
  ei_xreceive_msg(intx, &emsg, &eix);

  ei_send(intx, &epid, charp, intx);
  ei_reg_send(&xec, intx, charp, charp, intx);

  ei_rpc(&xec, intx, charp, charp, charp, intx, &eix);
  ei_rpc_to(&xec, intx, charp, charp, charp, intx);
  ei_rpc_from(&xec, intx, intx, &emsg, &eix);

  ei_publish(&xec, intx);
  ei_accept(&xec, intx, &conp);
  ei_unpublish(&xec);

  ei_thisnodename(&xec);
  ei_thishostname(&xec);
  ei_thisalivename(&xec);

  ei_self(&xec);

  ei_gethostbyname(charp);
  ei_gethostbyaddr(charp, intx, intx);
  ei_gethostbyname_r(charp, hostp, charp, intx, intp);
  ei_gethostbyaddr_r(charp, intx, intx, hostp, charp, intx, intp);

  ei_encode_version(charp, intp);
  ei_x_encode_version(&eix);
  ei_encode_long(charp, intp, longx);
  ei_x_encode_long(&eix, longx);
  ei_encode_ulong(charp, intp, ulongx);
  ei_x_encode_ulong(&eix, ulongx);
  ei_encode_double(charp, intp, doublex);
  ei_x_encode_double(&eix, doublex);
  ei_encode_boolean(charp, intp, intx);
  ei_x_encode_boolean(&eix, intx);
  ei_encode_char(charp, intp, 'a');
  ei_x_encode_char(&eix, 'a');
  ei_encode_string(charp, intp, charp);
  ei_encode_string_len(charp, intp, charp, intx);
  ei_x_encode_string(&eix, charp);
  ei_x_encode_string_len(&eix, charp, intx);
  ei_encode_atom(charp, intp, charp);
  ei_encode_atom_as(charp, intp, charp, ERLANG_LATIN1, ERLANG_UTF8);
  ei_encode_atom_len(charp, intp, charp, intx);
  ei_encode_atom_len_as(charp, intp, charp, intx, ERLANG_ASCII, ERLANG_LATIN1);
  ei_x_encode_atom(&eix, charp);
  ei_x_encode_atom_as(&eix, charp, ERLANG_LATIN1, ERLANG_UTF8);
  ei_x_encode_atom_len(&eix, charp, intx);
  ei_x_encode_atom_len_as(&eix, charp, intx, ERLANG_LATIN1, ERLANG_UTF8);
  ei_encode_binary(charp, intp, (void *)0, longx);
  ei_x_encode_binary(&eix, (void*)0, intx);
  ei_encode_pid(charp, intp, &epid);
  ei_x_encode_pid(&eix, &epid);
  ei_encode_fun(charp, intp, &efun);
  ei_x_encode_fun(&eix, &efun);
  ei_encode_port(charp, intp, &eport);
  ei_x_encode_port(&eix, &eport);
  ei_encode_ref(charp, intp, &eref);
  ei_x_encode_ref(&eix, &eref);
  ei_encode_trace(charp, intp, &etrace);
  ei_x_encode_trace(&eix, &etrace);
  ei_encode_tuple_header(charp, intp, intx);
  ei_x_encode_tuple_header(&eix, longx);
  ei_encode_list_header(charp, intp, intx);
  ei_x_encode_list_header(&eix, longx);
/* #define ei_encode_empty_list(buf,i) ei_encode_list_header(buf,i,0) */
  ei_x_encode_empty_list(&eix);

  ei_get_type(charp, intp, intp, intp);
  ei_get_type_internal(charp, intp, intp, intp);

  ei_decode_version(charp, intp, intp);
  ei_decode_long(charp, intp, longp);
  ei_decode_ulong(charp, intp, ulongp);
  ei_decode_double(charp, intp, doublep);
  ei_decode_boolean(charp, intp, intp);
  ei_decode_char(charp, intp, charp);
  ei_decode_string(charp, intp, charp);
  ei_decode_atom(charp, intp, charp);
  ei_decode_atom_as(charp, intp, charp, MAXATOMLEN_UTF8, ERLANG_WHATEVER, &enc, &enc);
  ei_decode_binary(charp, intp, (void *)0, longp);
  ei_decode_fun(charp, intp, &efun);
  free_fun(&efun);
  ei_decode_pid(charp, intp, &epid);
  ei_decode_port(charp, intp, &eport);
  ei_decode_ref(charp, intp, &eref);
  ei_decode_trace(charp, intp, &etrace);
  ei_decode_tuple_header(charp, intp, intp);
  ei_decode_list_header(charp, intp, intp);

  ei_decode_ei_term(charp, intp, &eterm);

  ei_print_term(fp, charp, intp);
  ei_s_print_term(&charp, charp, intp);

  ei_x_format(&eix, charp);
  ei_x_format_wo_ver(&eix, charp);

  ei_x_new(&eix);
  ei_x_new_with_version(&eix);
  ei_x_free(&eix);
  ei_x_append(&eix, &eix);
  ei_x_append_buf(&eix, charp, intx);
  ei_skip_term(charp, intp);

  ei_reg_open(intx);
  ei_reg_resize(ei_regp, intx);
  ei_reg_close(ei_regp);

  ei_reg_setival(ei_regp, charp, longx);
  ei_reg_setfval(ei_regp, charp, doublex);
  ei_reg_setsval(ei_regp, charp, charp);
  ei_reg_setpval(ei_regp, charp, voidp, intx);

  ei_reg_setval(ei_regp, charp, intx);

  ei_reg_getival(ei_regp, charp);
  ei_reg_getfval(ei_regp, charp);
  ei_reg_getsval(ei_regp, charp);
  ei_reg_getpval(ei_regp, charp, intp);

  ei_reg_getval(ei_regp, charp, intx);

  ei_reg_markdirty(ei_regp, charp);

  ei_reg_delete(ei_regp, charp);

  ei_reg_stat(ei_regp, charp, ei_reg_statp);

  ei_reg_tabstat(ei_regp, ei_reg_tabstatp);

  ei_reg_dump(intx, ei_regp, charp, intx);
  ei_reg_restore(intx, ei_regp, charp);
  ei_reg_purge(ei_regp);

#if defined(HAVE_GMP_H) && defined(HAVE_LIBGMP)
  {
      mpz_t obj;
      ei_decode_bignum(charp, intp, obj);
      ei_encode_bignum(charp, intp, obj);
      ei_x_encode_bignum(&eix, obj);
  }
#endif /* HAVE_GMP_H && HAVE_LIBGMP */

#ifndef VXWORKS

  ei_decode_longlong(charp, intp, longlongp);
  ei_decode_ulonglong(charp, intp, ulonglongp);
  ei_encode_longlong(charp, intp, longlongx);
  ei_encode_ulonglong(charp, intp, ulonglongx);
  ei_x_encode_longlong(&eix, longlongx);
  ei_x_encode_ulonglong(&eix, ulonglongx);

#endif

#ifdef USE_EI_UNDOCUMENTED

  ei_decode_intlist(charp, intp, longp, intp);

  ei_receive_encoded(intx, &charp, intp, msgp, intp);
  ei_send_encoded(intx, pidp, charp, intx);
  ei_send_reg_encoded(intx, pidp, charp, charp, intx);

  ei_decode_big(charp, intp, bigp);
  ei_big_comp(bigp, bigp);
  ei_big_to_double(bigp, doublep);
  ei_small_to_big(intx, bigp);
  ei_alloc_big(intx);
  ei_free_big(bigp);

#endif /* USE_EI_UNDOCUMENTED */

  return
      BUFSIZ +
      EAGAIN +
      EHOSTUNREACH +
      EIO +
      EI_BIN +
      EI_DELET +
      EI_DIRTY +
      EI_FLT +
      EI_FORCE +
      EI_INT +
      EI_NOPURGE +
      EI_STR +
      EMSGSIZE +
      ENOMEM +
      ERL_ERROR +
      ERL_EXIT +
      ERL_LINK +
      ERL_MSG +
      ERL_NO_TIMEOUT +
      ERL_REG_SEND +
      ERL_SEND +
      ERL_TICK +
      ERL_TIMEOUT +
      ERL_UNLINK +
      ETIMEDOUT +
      MAXATOMLEN;
}
Exemple #28
0
int ei_send_encoded_tmo(int fd, const erlang_pid *to, 
			char *msg, int msglen, unsigned ms) 
{
    char *s, header[1200]; /* see size calculation below */
    erlang_trace *token = NULL;
    int index = 5; /* reserve 5 bytes for control message */
    int res;
#ifdef HAVE_WRITEV
    struct iovec v[2];
#endif

    /* are we tracing? */
    /* check that he can receive trace tokens first */
    if (ei_distversion(fd) > 0) token = ei_trace(0,NULL);
    
    /* header = SEND, cookie, to                      max sizes: */
    ei_encode_version(header,&index);		      /*   1 */
    if (token) {
	ei_encode_tuple_header(header,&index,4);      /*   2 */
	ei_encode_long(header,&index,ERL_SEND_TT);    /*   2 */
    } else {
	ei_encode_tuple_header(header,&index,3);
	ei_encode_long(header,&index,ERL_SEND); 
    }
    ei_encode_atom(header,&index,ei_getfdcookie(fd)); /* 258 */
    ei_encode_pid(header,&index,to);		      /* 268 */
    
    if (token) ei_encode_trace(header,&index,token);  /* 534 */
    
    /* control message (precedes header actually) */
    /* length = 1 ('p') + header len + message len */
    s = header;
    put32be(s, index + msglen - 4);		      /*   4 */
    put8(s, ERL_PASS_THROUGH);			      /*   1 */
				/*** sum: 1070 */

    if (ei_tracelevel >= 4)
	ei_show_sendmsg(stderr,header,msg);

#ifdef HAVE_WRITEV
    
    v[0].iov_base = (char *)header;
    v[0].iov_len = index;
    v[1].iov_base = (char *)msg;
    v[1].iov_len = msglen;
    
    if ((res = ei_writev_fill_t(fd,v,2,ms)) != index+msglen) {
	erl_errno = (res == -2) ? ETIMEDOUT : EIO;
	return -1;
    }
  
#else  /* !HAVE_WRITEV */
  
    if ((res = ei_write_fill_t(fd,header,index,ms)) != index) { 
	erl_errno = (res == -2) ? ETIMEDOUT : EIO;
	return -1;
    }
    if ((res = ei_write_fill_t(fd,msg,msglen,ms)) != msglen) { 
	erl_errno = (res == -2) ? ETIMEDOUT : EIO;
	return -1;
    }

#endif  /* !HAVE_WRITEV */

    return 0;
}
Exemple #29
0
int ei_reg_restore(int fd, ei_reg *reg, const char *mntab)
{
  int i,j;
  char tag[32];
  char sbuf[EISMALLBUF];
  char *dbuf = NULL;
  char *msgbuf = NULL;
  char *keybuf = NULL;
  erlang_pid self;
  erlang_pid mnesia = {"",0,0,0};
  erlang_msg msg;
  int index = 0;
  int len = 0;
  int msglen;
  int version = 0;
  int arity = 0;
  long count = 0;
  long maxkey = 0;
  long maxobj = 0;
  ei_cnode *ec;

  if (!reg || !mntab) return -1; /* return EI_BADARG; */

  /* make a self pid */

  if ((ec = ei_fd_to_cnode(fd)) == NULL) {
      return -1;
  }
  strcpy(self.node,ei_thisnodename(ec));
  self.num = fd;
  self.serial = 0;
  self.creation = ei_thiscreation(ec);

  
  if (mn_start_restore(fd,&self,&mnesia,mntab,&count,&maxkey,&maxobj)) {
    /* send exit *only* if we have pid */
    if (mnesia.node[0]) ei_send_exit(fd,&self,&mnesia,"bad response from rpc start");
    return -1;
  }

  if (count <= 0) {
    ei_send_exit(fd,&self,&mnesia,"nothing to do");
    return 0;
  }
  
  /* make sure receive buffer can handle largest expected message */
  len = maxkey + maxobj + 512; 
  if (len > EISMALLBUF)
    if (!(dbuf = malloc(len))) {
      ei_send_exit(fd,&self,&mnesia,"cannot allocate space for incoming data");
      return -1;
    }
  msgbuf = (dbuf ? dbuf : sbuf);

  /* allocate space for largest key */
  if (!(keybuf = malloc(maxkey+1))) goto restore_failure;
  
  /* get this ball rolling */
  index = 0;
  ei_encode_version(msgbuf,&index);
  ei_encode_tuple_header(msgbuf,&index,2);
  ei_encode_atom(msgbuf,&index,"send_records");
  ei_encode_pid(msgbuf,&index,&self);
  if (ei_send_encoded(fd,&mnesia,msgbuf,index)) goto restore_failure;

  /* read as much as possible, until count or EXIT */
  for (i=0; i<count; i++) {
    index = len;
    while ((j = ei_recv_internal(fd,&msgbuf,&index,&msg,&msglen,1,0)) == 0) index = len;
    if (j<0) goto restore_failure;
    
    /* decode the first part of the message */
    index = 0;
    if ((msg.msgtype != ERL_SEND) 
	|| ei_decode_version(msgbuf,&index,&version) 
	|| ei_decode_tuple_header(msgbuf,&index,&arity) 
	|| (arity != 6) 
	|| ei_decode_atom(msgbuf,&index,tag) 
	|| strcmp(tag,EI_MNESIA_RECV)) 
      goto restore_failure;

    /* decode the rest of the message and insert data into table */
    if (mn_decode_insert(reg,msgbuf,&index,keybuf)) goto restore_failure;
  }
  
  if (keybuf) free(keybuf);
  if (dbuf) free(dbuf);

  /* wait for unlink */
  if (mn_unlink(fd)) return -1;

  /* clear all the dirty bits */
  ei_hash_foreach(reg->tab,clean_obj);

  /* success */
  return 0;

restore_failure:
  ei_send_exit(fd,&self,&mnesia,"restore failure");
  if (keybuf) free(keybuf);
  if (dbuf) free(dbuf);
  return -1;
}
Exemple #30
0
static int mn_start_restore(int fd, const erlang_pid *self, erlang_pid *mnesia, const char *mntab, long *count, long *maxkey,long *maxobj)
{
  char buf[EISMALLBUF];
  char *bufp=buf;
  char tmpbuf[64];
  int index = 0;
  erlang_msg msg;
  int arity;
  int version;
  int i;
  int needlink;
  int needmsg;
  int msglen;
  
  /* set up rpc arguments */
  /* { PidFrom, { call, Mod, Fun, Args, user }}  */
  ei_encode_version(buf,&index);
  ei_encode_tuple_header(buf,&index,2);
  ei_encode_pid(buf,&index,self);               /* PidFrom */
  ei_encode_tuple_header(buf,&index,5);
  ei_encode_atom(buf,&index,"call");            /* call */
  ei_encode_atom(buf,&index,EI_MNESIA_MODULE);  /* Mod */
  ei_encode_atom(buf,&index,EI_MNESIA_RESTORE); /* Fun */
  ei_encode_list_header(buf,&index,2);          /* Args: [ table, self() ] */
  ei_encode_atom(buf,&index,mntab);
  ei_encode_pid(buf,&index,self); 
  ei_encode_empty_list(buf,&index);
  ei_encode_atom(buf,&index,"user");            /* user */

  /* make the rpc call */
  if (ei_send_reg_encoded(fd,self,"rex",buf,index)) return -1;

  /* get the reply: expect link and message (not sure which will come first though) */
  needlink = needmsg = 1;
  while (needlink || needmsg) {
    /* get message */
    index = EISMALLBUF;
    while (!(i = ei_recv_internal(fd,&bufp,&index,&msg,&msglen,1,0))) index = EISMALLBUF;

    switch (i) {
    case ERL_LINK:
      /* got link */
      if (!needlink) return -1;
      needlink = 0;
      break;
      
    case ERL_SEND:
      /* got message - is it the right one? */
      if (!needmsg) return -1;
      else {
	/* expecting { rex, { size, Pid, Count, MaxKey, MaxObj }} */
	index = 0;
	if (ei_decode_version(buf,&index,&version) 
	    || ei_decode_tuple_header(buf,&index,&arity)
	    || (arity != 2) 
	    || ei_decode_atom(buf,&index,tmpbuf)
	    || strcmp(tmpbuf,"rex")
	    || ei_decode_tuple_header(buf,&index,&arity)
	    || (arity != 5) 
	    || ei_decode_atom(buf,&index,tmpbuf)
	    || strcmp(tmpbuf,EI_MNESIA_SIZE)
	    || ei_decode_pid(buf,&index,mnesia)
	    || ei_decode_long(buf,&index,count)
	    || ei_decode_long(buf,&index,maxkey)
	    || ei_decode_long(buf,&index,maxobj))
	  return -1; /* bad response from other side */
      
	/* got msg */
	needmsg = 0;
      }
      break;
      
    default:
      return -1; /* wasn't link or pid */
    }
  }
  return 0;
}