Пример #1
0
static ERL_NIF_TERM open_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
    posix_errno_t posix_errno;
    efile_data_t *d;

    ErlNifPid controlling_process;
    enum efile_modes_t modes;
    ERL_NIF_TERM result;
    efile_path_t path;

    if(argc != 2 || !enif_is_list(env, argv[1])) {
        return enif_make_badarg(env);
    }

    modes = efile_translate_modelist(env, argv[1]);

    if((posix_errno = efile_marshal_path(env, argv[0], &path))) {
        return posix_error_to_tuple(env, posix_errno);
    } else if((posix_errno = efile_open(&path, modes, efile_resource_type, &d))) {
        return posix_error_to_tuple(env, posix_errno);
    }

    result = enif_make_resource(env, d);
    enif_release_resource(d);

    enif_self(env, &controlling_process);

    if(enif_monitor_process(env, d, &controlling_process, &d->monitor)) {
        return posix_error_to_tuple(env, EINVAL);
    }

    return enif_make_tuple2(env, am_ok, result);
}
Пример #2
0
// fwrite implementation
static ERL_NIF_TERM
io_libc_fwrite(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
  char fmt[1024];
  int len = 0;

  if((len = enif_get_string(env, argv[0], fmt, sizeof(fmt), ERL_NIF_LATIN1)) <= 0) return enif_make_badarg(env);
  if(!enif_is_list(env, argv[1])) return enif_make_badarg(env);
  
  ERL_NIF_TERM items = argv[1];

  // At first, allocate result as empty binary
  ErlNifBinary result;
  enif_alloc_binary(0, &result);

  // Get escape sequences one-by-one from fmt with according values from items
  char *cur_fmt = fmt;
  int format_result;
  while ((format_result = format_first(env, &result, &cur_fmt, &items)) > 0) {
    // Nothing to do here, everything is ok
  }

  // good: return resulting binary
  if (format_result >= 0) return enif_make_binary(env, &result);

  // bad: make badarg. TODO: return something pointing to erroneous place
  return enif_make_badarg(env);
};
Пример #3
0
ERL_NIF_TERM
decode_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    Decoder* d;
    jiffy_st* st = (jiffy_st*) enif_priv_data(env);
    ERL_NIF_TERM tmp_argv[5];
    ERL_NIF_TERM opts;
    ERL_NIF_TERM val;

    if(argc != 2) {
        return enif_make_badarg(env);
    }

    d = dec_new(env);
    if(d == NULL) {
        return make_error(st, env, "internal_error");
    }

    tmp_argv[0] = argv[0];
    tmp_argv[1] = enif_make_resource(env, d);
    tmp_argv[2] = st->atom_error;
    tmp_argv[3] = enif_make_list(env, 0);
    tmp_argv[4] = enif_make_list(env, 0);

    enif_release_resource(d);

    opts = argv[1];
    if(!enif_is_list(env, opts)) {
        return enif_make_badarg(env);
    }

    while(enif_get_list_cell(env, opts, &val, &opts)) {
        if(get_bytes_per_iter(env, val, &(d->bytes_per_red))) {
            continue;
        } else if(get_bytes_per_red(env, val, &(d->bytes_per_red))) {
            continue;
        } else if(enif_compare(val, d->atoms->atom_return_maps) == 0) {
#if MAP_TYPE_PRESENT
            d->return_maps = 1;
#else
            return enif_make_badarg(env);
#endif
        } else if(enif_compare(val, d->atoms->atom_return_trailer) == 0) {
            d->return_trailer = 1;
        } else if(enif_compare(val, d->atoms->atom_dedupe_keys) == 0) {
            d->dedupe_keys = 1;
        } else if(enif_compare(val, d->atoms->atom_use_nil) == 0) {
            d->null_term = d->atoms->atom_nil;
        } else if(get_null_term(env, val, &(d->null_term))) {
            continue;
        } else {
            return enif_make_badarg(env);
        }
    }

    return decode_iter(env, 5, tmp_argv);
}
Пример #4
0
/*
 * argv[0] an atom
 * argv[1] a binary
 * argv[2] a ref
 * argv[3] 'ok'
 * argv[4] a fun
 * argv[5] a pid
 * argv[6] a port
 * argv[7] an empty list
 * argv[8] a non-empty list
 * argv[9] a tuple
 */
static ERL_NIF_TERM check_is(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    ERL_NIF_TERM ok_atom = enif_make_atom(env, "ok");

    if (!enif_is_atom(env, argv[0])) return enif_make_badarg(env);
    if (!enif_is_binary(env, argv[1])) return enif_make_badarg(env);
    if (!enif_is_ref(env, argv[2])) return enif_make_badarg(env);
    if (!enif_is_identical(argv[3], ok_atom)) return enif_make_badarg(env);
    if (!enif_is_fun(env, argv[4])) return enif_make_badarg(env);
    if (!enif_is_pid(env, argv[5])) return enif_make_badarg(env);
    if (!enif_is_port(env, argv[6])) return enif_make_badarg(env);
    if (!enif_is_empty_list(env, argv[7])) return enif_make_badarg(env);
    if (!enif_is_list(env, argv[7])) return enif_make_badarg(env);
    if (!enif_is_list(env, argv[8])) return enif_make_badarg(env);
    if (!enif_is_tuple(env, argv[9])) return enif_make_badarg(env);

    return ok_atom;
}
Пример #5
0
static ERL_NIF_TERM
create_worker_data(ErlNifEnv *env, int32_t argc, const ERL_NIF_TERM *argv) {
  BundlePaths  *bundle_paths;
  ERL_NIF_TERM  list, head, tail, result;
  unsigned int  index, length, string_length;
  char         *new_path;
  WorkerData   *worker_data;

  (void)(argc);

  list = argv[0];
  if (!enif_is_list(env, list)) return enif_make_badarg(env);

  enif_get_list_length(env, list, &length);
  bundle_paths = bundle_paths_new(length);

  index = 0;
  tail  = list;
  while (enif_get_list_cell(env, tail, &head, &tail)) {
    if (!enif_is_list(env, head)) return enif_make_badarg(env);

    enif_get_list_length(env, head, &string_length);
    new_path = malloc(sizeof(char) * string_length + 1);

    if (!enif_get_string(env, head, new_path, string_length + 1, ERL_NIF_LATIN1))
      return enif_make_badarg(env);

    bundle_paths->paths[index] = new_path;

    index += 1;
  }

  worker_data = enif_alloc_resource(WORKER_DATA, sizeof(WorkerData));
  worker_data_initialize(worker_data, length);
  worker_data_read(bundle_paths, worker_data);

  result = enif_make_resource(env, worker_data);
  enif_release_resource(&worker_data);

  bundle_paths_free(&bundle_paths);

  return result;
}
Пример #6
0
ERL_NIF_TERM
encode_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    jiffy_st* st = (jiffy_st*) enif_priv_data(env);
    Encoder* e;

    ERL_NIF_TERM opts;
    ERL_NIF_TERM val;
    ERL_NIF_TERM tmp_argv[3];

    if(argc != 2) {
        return enif_make_badarg(env);
    }

    e = enc_new(env);
    if(e == NULL) {
        return make_error(st, env, "internal_error");
    }

    tmp_argv[0] = enif_make_resource(env, e);
    tmp_argv[1] = enif_make_list(env, 1, argv[0]);
    tmp_argv[2] = enif_make_list(env, 0);

    enif_release_resource(e);

    opts = argv[1];
    if(!enif_is_list(env, opts)) {
        return enif_make_badarg(env);
    }

    while(enif_get_list_cell(env, opts, &val, &opts)) {
        if(enif_compare(val, e->atoms->atom_uescape) == 0) {
            e->uescape = 1;
        } else if(enif_compare(val, e->atoms->atom_pretty) == 0) {
            e->pretty = 1;
        } else if(enif_compare(val, e->atoms->atom_escape_forward_slashes) == 0) {
            e->escape_forward_slashes = 1;
        } else if(enif_compare(val, e->atoms->atom_use_nil) == 0) {
            e->use_nil = 1;
        } else if(enif_compare(val, e->atoms->atom_force_utf8) == 0) {
            // Ignore, handled in Erlang
        } else if(get_bytes_per_iter(env, val, &(e->bytes_per_red))) {
            continue;
        } else if(get_bytes_per_red(env, val, &(e->bytes_per_red))) {
            continue;
        } else {
            return enif_make_badarg(env);
        }
    }

    return encode_iter(env, 3, tmp_argv);
}
Пример #7
0
static ERL_NIF_TERM eval2(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
  ErlNifBinary script_binary;

  if (!enif_inspect_binary(env, argv[0], &script_binary)){
    return enif_make_badarg(env);
  }

  if (!enif_is_list(env, argv[1])) {
    enif_release_binary(&script_binary);
    return enif_make_badarg(env);
  }

  mrb_state *mrb;
  mrbc_context *cxt;

  mrb = mrb_open();

  if (mrb == NULL) {
    return enif_make_atom(env, "error");
  }

  unsigned int mrb_argv_len;
  enif_get_list_length(env, argv[1], &mrb_argv_len);
  mrb_value mrb_argv = mrb_ary_new(mrb);
  ERL_NIF_TERM cur;
  for(cur = argv[1]; !enif_is_empty_list(env, cur); ) {
    ERL_NIF_TERM head, tail;
    enif_get_list_cell(env, cur, &head, &tail);
    mrb_ary_push(mrb, mrb_argv, erl2mruby(env, mrb, head));
    cur = tail;
  }
  mrb_define_global_const(mrb, "ARGV", mrb_argv);

  char *script = malloc(script_binary.size+1);
  strncpy(script, (const char *)script_binary.data, (int)script_binary.size);
  script[script_binary.size] = '\0';

  cxt = mrbc_context_new(mrb);
  struct mrb_parser_state* st = mrb_parse_string(mrb, (const char *)script, cxt);
  int n = mrb_generate_code(mrb, st);
  mrb_pool_close(st->pool);
  mrb_value result = mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_nil_value());
  ERL_NIF_TERM erl_result = mruby2erl(env, mrb, result);

  free(script);
  mrbc_context_free(mrb, cxt);
  mrb_close(mrb);
  enif_release_binary(&script_binary);

  return erl_result;
}
Пример #8
0
static ERL_NIF_TERM open_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
    posix_errno_t posix_errno;
    efile_data_t *d;

    ErlNifPid controlling_process;
    enum efile_modes_t modes;
    ERL_NIF_TERM result;
    efile_path_t path;

    ASSERT(argc == 2);
    if(!enif_is_list(env, argv[1])) {
        return enif_make_badarg(env);
    }

    modes = efile_translate_modelist(env, argv[1]);

    if((posix_errno = efile_marshal_path(env, argv[0], &path))) {
        return posix_error_to_tuple(env, posix_errno);
    } else if((posix_errno = efile_open(&path, modes, efile_resource_type, &d))) {
        return posix_error_to_tuple(env, posix_errno);
    }

    enif_self(env, &controlling_process);

    if(enif_monitor_process(env, d, &controlling_process, &d->monitor)) {
        /* We need to close the file manually as we haven't registered a
         * destructor. */
        posix_errno_t ignored;

        erts_atomic32_set_acqb(&d->state, EFILE_STATE_CLOSED);
        efile_close(d, &ignored);

        return posix_error_to_tuple(env, EINVAL);
    }

    /* Note that we do not call enif_release_resource at this point. While it's
     * normally safe to leave resource management to the GC, efile_close is a
     * blocking operation which must not be done in the GC callback, and we
     * can't defer it as the resource is gone as soon as it returns.
     *
     * We instead keep the resource alive until efile_close is called, after
     * which it's safe to leave things to the GC. If the controlling process
     * were to die before the user had a chance to close their file, the above
     * monitor will tell the erts_prim_file process to close it for them. */
    result = enif_make_resource(env, d);

    return enif_make_tuple2(env, am_ok, result);
}
Пример #9
0
static ERL_NIF_TERM
elua_gencall_sync(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    elua_t *res;

    // first arg: ref
    if(!enif_get_resource(env, argv[0], RES_SYNC, (void**) &res)) {
        return enif_make_badarg(env);
    }

    if(!enif_is_list(env, argv[3])) {
        return enif_make_badarg(env);
    }

    return gencall(env, res->L, argv[1], argv[2], argv[3]);
}
Пример #10
0
static ERL_NIF_TERM
nif_scheduler_reconcileTasks(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    unsigned int length ;

    state_ptr state = (state_ptr) enif_priv_data(env);
    
    if(state->initilised == 0 ) 
    {
        return enif_make_tuple2(env, 
            enif_make_atom(env, "state_error"), 
            enif_make_atom(env, "scheduler_not_inited"));
    }

    if(!enif_is_list(env, argv[0])) 
    {
        return enif_make_tuple3(env, 
                    enif_make_atom(env, "argument_error"), 
                    enif_make_atom(env, "invalid_or_corrupted_parameter"),
                    enif_make_atom(env, "task_status_array"));
    };

    if(!enif_get_list_length(env, argv[0], &length))
    {
        return enif_make_tuple3(env, 
                    enif_make_atom(env, "argument_error"), 
                    enif_make_atom(env, "invalid_or_corrupted_parameter"),
                    enif_make_atom(env, "task_status_array"));

    }
    
    ErlNifBinary binary_arr[length];
    if(!inspect_array_of_binary_objects(env, argv[0], &binary_arr ))
    {
        return enif_make_tuple3(env, 
                    enif_make_atom(env, "argument_error"), 
                    enif_make_atom(env, "invalid_or_corrupted_parameter"),
                    enif_make_atom(env, "task_status_array"));
    }   

    BinaryNifArray binaryNifArrayHolder ;
    binaryNifArrayHolder.length = length;
    binaryNifArrayHolder.obj = &binary_arr[0];

    SchedulerDriverStatus status =  scheduler_reconcileTasks( state->scheduler_state, &binaryNifArrayHolder);
    return get_return_value_from_status(env, status);
}
Пример #11
0
static ERL_NIF_TERM
elua_gencall_async(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    elua_t *res;
    msg_t *msg;
    ErlNifPid pid;

    if(argc != 6) {
        return enif_make_badarg(env);
    }

    // first arg: ref
    if(!enif_get_resource(env, argv[0], RES_SYNC, (void**) &res)) {
        return enif_make_badarg(env);
    }

    // ref
    if(!enif_is_ref(env, argv[1])) {
        return make_error_tuple(env, "invalid_ref");
    }

    // dest pid
    if(!enif_get_local_pid(env, argv[2], &pid)) {
        return make_error_tuple(env, "invalid_pid");
    }

    // fourth arg: list of input args
    if(!enif_is_list(env, argv[5])) {
        return enif_make_badarg(env);
    }

    msg = msg_create();
    if(!msg) {
        return make_error_tuple(env, "command_create_failed");
    }

    msg->type = msg_gencall;
    msg->ref = enif_make_copy(msg->env, argv[1]);
    msg->pid = pid;
    msg->arg1 = enif_make_copy(msg->env, argv[3]);
    msg->arg2 = enif_make_copy(msg->env, argv[4]);
    msg->arg3 = enif_make_copy(msg->env, argv[5]);
    msg->res = res;

    return push_command(env, res, msg);
}
Пример #12
0
static ERL_NIF_TERM open_1(ErlNifEnv *env, int argc,
                                     const ERL_NIF_TERM argv[])
{
    char *device;
    unsigned int length;
    uint8_t tmp8;
    uint32_t tmp32;
    
    state.env = env;
    state.fd = -1;
    state.mode = 0;
    state.bits_per_word = 0;
    state.max_speed_hz = 0;
    if (argc != 1 || !enif_is_list(env, argv[0]))
        return enif_make_badarg(env);
    if (!enif_get_list_length(env, argv[0], &length))
        return enif_make_badarg(env);
    device = (char *) enif_alloc(length + 1);
    enif_get_string(env, argv[0], device, length + 1, ERL_NIF_LATIN1);
    if ((state.fd = open(device, O_RDWR, 0)) == -1) {
        return enif_make_badarg(env);
    }
    if (ioctl(state.fd, SPI_IOC_RD_MODE, &tmp8) == -1) {
        close(state.fd);
        enif_free(device);
        return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_string(env, "read mode", ERL_NIF_LATIN1));
    }
    state.mode = tmp8;
    if (ioctl(state.fd, SPI_IOC_RD_BITS_PER_WORD, &tmp8) == -1) {
        close(state.fd);
        enif_free(device);
        return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_string(env, "read bits per word", ERL_NIF_LATIN1));
    }
    state.bits_per_word = tmp8;
    if (ioctl(state.fd, SPI_IOC_RD_MAX_SPEED_HZ, &tmp32) == -1) {
        close(state.fd);
        enif_free(device);
        return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_string(env, "read max speed hz", ERL_NIF_LATIN1));
    }
    state.max_speed_hz = tmp32;
    enif_free(device);
    
    return enif_make_atom(env, "ok");
}
Пример #13
0
static ERL_NIF_TERM xfer2_1(ErlNifEnv *env, int argc,
                                     const ERL_NIF_TERM argv[])
{
    int status, val, i;
    struct spi_ioc_transfer xfer;
    uint8_t *txbuf, *rxbuf;
    unsigned int length;
    ERL_NIF_TERM cell, head, tail, res, list;
    
    if (state.fd == -1)
        return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_string(env, "device closed", ERL_NIF_LATIN1));
    if (argc != 1 || !enif_is_list(env, argv[0]))
        return enif_make_badarg(env);
    if (!enif_get_list_length(env, argv[0], &length))
        return enif_make_badarg(env);
    txbuf = (uint8_t *) enif_alloc(sizeof(uint8_t) * length);
    rxbuf = (uint8_t *) enif_alloc(sizeof(uint8_t) * length);
    list = argv[0];
    for (i = 0; enif_get_list_cell(env, list, &head, &tail); ++i, list = tail) {
        if (!enif_get_int(env, head, &val)) {
            return enif_make_badarg(env);
        }
        txbuf[i] = val;
    }
    xfer.tx_buf = (unsigned long) txbuf;
    xfer.rx_buf = (unsigned long) rxbuf;
    xfer.len = length;
    status = ioctl(state.fd, SPI_IOC_MESSAGE(1), &xfer);
    if (status < 0) {
        enif_free(txbuf);
        enif_free(rxbuf);
        return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_string(env, "spi ioc message", ERL_NIF_LATIN1));
    }
    list = enif_make_list(env, 0);
    for (i = length - 1; i >= 0; --i) {
        cell = enif_make_uint(env, (unsigned int) rxbuf[i]);
        list = enif_make_list_cell(env, cell, list);
    }
    res = enif_make_tuple2(env, enif_make_atom(env, "ok"), list);
    enif_free(txbuf);
    enif_free(rxbuf);
    
    return res;
}
Пример #14
0
int
enc_init(Encoder* e, ErlNifEnv* env, ERL_NIF_TERM opts, ErlNifBinary* bin)
{
    ERL_NIF_TERM val;

    e->env = env;
    e->atoms = enif_priv_data(env);
    e->uescape = 0;
    e->pretty = 0;
    e->shiftcnt = 0;
    e->count = 0;

    if(!enif_is_list(env, opts)) {
        return 0;
    }

    while(enif_get_list_cell(env, opts, &val, &opts)) {
        if(enif_compare(val, e->atoms->atom_uescape) == 0) {
            e->uescape = 1;
        } else if(enif_compare(val, e->atoms->atom_pretty) == 0) {
            e->pretty = 1;
        } else if(enif_compare(val, e->atoms->atom_force_utf8) == 0) {
            // Ignore, handled in Erlang
        } else {
            return 0;
        }
    }

    e->iolen = 0;
    e->iolist = enif_make_list(env, 0);
    e->curr = bin;
    if(!enif_alloc_binary(BIN_INC_SIZE, e->curr)) {
        return 0;
    }

    memset(e->curr->data, 0, e->curr->size);

    e->p = (char*) e->curr->data;
    e->u = (unsigned char*) e->curr->data;
    e->i = 0;

    return 1;
}
Пример #15
0
static void push_nif_list(lua_State* lua, ERL_NIF_TERM list, ErlNifEnv* env, ErlNifResourceType* resource_type)
{
	const int top = lua_gettop(lua);

	int map_count = 0;
	int array_count = 0;
	if(enif_is_list(env, list))
	{
		ERL_NIF_TERM head;
		ERL_NIF_TERM tail = list;
		while(enif_get_list_cell(env, tail, &head, &tail))
		{
			if(push_table_iskvp(env, head, NULL))
			{
				++map_count;
			}
			else
			{
				++array_count;
			}
		}

		luaL_checkstack(lua, 1, ERROR_STACK_MESSAGE);
		lua_createtable(lua, array_count, map_count);

		ERL_NIF_TERM array_items[array_count + map_count];

		tail = list;
		int index = 0;
		while(enif_get_list_cell(env, tail, &head, &tail))
		{
			if(!push_table_set(lua, env, head, resource_type))
			{
				array_items[index++] = head;
			}
		}

		push_table_append(lua, env, resource_type, array_items, index);
	}

	assert(lua_gettop(lua) == top+1);
}
Пример #16
0
ERL_NIF_TERM meter_new(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    meter_handle *handle = 
        (meter_handle *)enif_alloc_resource(meter_RESOURCE,
                                            sizeof(meter_handle));
    if (enif_is_list(env, argv[0]))
    {
        memset(handle, '\0', sizeof(meter_handle));
        pthread_mutex_init(&(handle->m), NULL);
        handle->tick_interval = DEFAULT_METER_TICK_INTERVAL;
        fold(env, argv[0], parse_meter_option, *handle);
        handle->p = new meter<>(handle->tick_interval);
        ERL_NIF_TERM result = enif_make_resource(env, handle);
        enif_release_resource(handle);
        return enif_make_tuple2(env, ATOM_OK, result);
    }
    else
    {
        return enif_make_badarg(env);
    }
}
Пример #17
0
ERL_NIF_TERM histogram_new(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    histogram_handle *handle = 
        (histogram_handle *)enif_alloc_resource(histogram_RESOURCE,
                                                sizeof(histogram_handle));
    if (enif_is_list(env, argv[0]))
    {
        memset(handle, '\0', sizeof(histogram_handle));
        pthread_mutex_init(&(handle->m), NULL);
        handle->size = DEFAULT_RESERVOIR_SIZE;
        handle->width = DEFAULT_WINDOW_WIDTH;
        fold(env, argv[0], parse_histogram_option, *handle);
        handle->p = new histogram<>(handle->size, handle->width);
        ERL_NIF_TERM result = enif_make_resource(env, handle);
        enif_release_resource(handle);
        return enif_make_tuple2(env, ATOM_OK, result);
    }
    else 
    {
        return enif_make_badarg(env);
    }
}
Пример #18
0
static ERL_NIF_TERM xfer_2(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
    unsigned int channel, length;
    int result, i, val;
    uint8_t *buffer;
    ERL_NIF_TERM cell, head, tail, list;

	if (argc < 2 || !enif_is_number(env, argv[0]) || !enif_is_list(env, argv[1])) {
    	return enif_make_badarg(env);
    }
    if (!enif_get_uint(env, argv[0], &channel) || channel < 0 || channel > 1) {
    	return enif_make_badarg(env);
    }
    if (!enif_get_list_length(env, argv[1], &length) || length == 0) {
    	return enif_make_badarg(env);
    }
    buffer = (uint8_t *) enif_alloc(sizeof(uint8_t) * length);
    list = argv[1];
	for (i = 0; enif_get_list_cell(env, list, &head, &tail); ++i, list = tail) {
		if (!enif_get_int(env, head, &val)) {
			return enif_make_badarg(env);
		}
		buffer[i] = val;
	}
	result = wiringPiSPIDataRW(channel, buffer, length);
	if (result == -1) {
		result = errno;
		enif_free(buffer);
		return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_int(env, result));
	}
	list = enif_make_list(env, 0);
	for (i = length - 1; i >= 0; --i) {
		cell = enif_make_uint(env, (unsigned int) buffer[i]);
		list = enif_make_list_cell(env, cell, list);
	}
	enif_free(buffer);

	return enif_make_tuple2(env, enif_make_atom(env, "ok"), list);
}
Пример #19
0
static ERL_NIF_TERM exec_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
  unsigned path_length, args_count, arg_length;
  ERL_NIF_TERM head, tail;
  int i = 0;

  enif_get_list_length(env, argv[0], &path_length);
  enif_get_list_length(env, argv[1], &args_count);

  char* exec_argv[args_count + 2];
  char path[path_length + 1];

  if (!enif_get_string(env, argv[0], path, path_length + 1, ERL_NIF_LATIN1) || !enif_is_list(env, argv[1])) {
    return enif_make_badarg(env);
  }

  tail = argv[1];
  while(enif_get_list_cell(env, tail, &head, &tail) != 0) {
    enif_get_list_length(env, head, &arg_length);

    char* arg = (char*) malloc(sizeof(char) * (arg_length + 1));

    if (!enif_get_string(env, head, arg, arg_length + 1, ERL_NIF_LATIN1)) {
      return enif_make_badarg(env);
    }

    exec_argv[i + 1] = arg;

    i++;
  }

  exec_argv[0] = path;
  exec_argv[args_count + 1] = NULL;

  execv(path, exec_argv);

  return enif_make_atom(env, "ok");
}
Пример #20
0
    static ERL_NIF_TERM
nif_notify(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    ErlNifBinary summary;
    ErlNifBinary body;
    ErlNifBinary icon;

    ErlNifBinary category;
    int urgency = NOTIFY_URGENCY_NORMAL;
    int timeout = 0;

    gchar *s_summary = NULL;
    gchar *s_body = NULL;
    gchar *s_icon = NULL;
    gchar *s_category = NULL;

    ERL_NIF_TERM hints;
    ERL_NIF_TERM head;
    ERL_NIF_TERM tail;
    const ERL_NIF_TERM *array;
    int arity = 0;

    NotifyNotification *notify = NULL;

    ERL_NIF_TERM rv = atom_ok;


    if (!enif_inspect_iolist_as_binary(env, argv[0], &summary))
        return enif_make_badarg(env);

    if (!enif_inspect_iolist_as_binary(env, argv[1], &body))
        return enif_make_badarg(env);

    if (!enif_inspect_iolist_as_binary(env, argv[2], &icon))
        return enif_make_badarg(env);

    if (!enif_inspect_iolist_as_binary(env, argv[3], &category))
        return enif_make_badarg(env);

    if (!enif_get_int(env, argv[4], &urgency))
        return enif_make_badarg(env);

    if (!enif_get_int(env, argv[5], &timeout))
        return enif_make_badarg(env);

    if (!enif_is_list(env, argv[6]))
        return enif_make_badarg(env);

    hints = argv[6];

    s_summary = stralloc(&summary);
    s_body = stralloc(&body);
    s_icon = stralloc(&icon);
    s_category = stralloc(&category);

    if ( (s_summary == NULL) || (s_body == NULL) ||
            (s_icon == NULL) || (s_category == NULL)) {
        rv = enif_make_tuple2(env, atom_error, atom_nomem);
        goto ERR;
    }


    notify = notify_notification_new(s_summary, s_body, s_icon);

    notify_notification_set_category(notify, s_category);
    notify_notification_set_urgency(notify, urgency);
    notify_notification_set_timeout(notify, timeout);

    while (enif_get_list_cell(env, hints, &head, &tail)) {
        ERL_NIF_TERM key;
        ERL_NIF_TERM value = atom_undefined;


        if (enif_get_tuple(env, head, &arity, &array)) {
            switch (arity) {
                case 2:
                    value = array[1];
                    key = array[0];
                    break;
                default:
                    rv = enif_make_badarg(env);
                    goto ERR;
            }
        }
        else if (enif_is_list(env, head)) {
            arity = 0;
            key = head;
        }
        else {
            rv = enif_make_badarg(env);
            goto ERR;
        }

        if (notify_hints_type(env, notify, arity, key, value) < 0) {
            rv = enif_make_badarg(env);
            goto ERR;
        }

        hints = tail;
    }

    notify_notification_show(notify, NULL);

ERR:
    if (notify)
        g_object_unref(G_OBJECT(notify));

    strfree(s_summary);
    strfree(s_body);
    strfree(s_icon);
    strfree(s_category);

    return rv;
}
Пример #21
0
static void push_nif_term(lua_State* lua, ERL_NIF_TERM message, ErlNifEnv* env, ErlNifResourceType* resource_type)
{
	const int top = lua_gettop(lua);

	if(enif_is_atom(env, message))
	{
		push_nif_atom(lua, message, env);
	}
	else if(enif_is_binary(env, message))
	{
		// TODO @@@ binary also seems to be the custom types
		// that erlang makes. This may be OK, but maybe we should
		// think about putting a special type for them in lua
		push_nif_binary(lua, message, env);
	}
	else if(enif_is_list(env, message))
	{
		if(enif_is_empty_list(env, message))
		{
			luaL_checkstack(lua, 1, ERROR_STACK_MESSAGE);
			lua_newtable(lua);
		}
		else
		{
			// TODO @@@ try to send it as an IO list first and
			// if that fails send it as a regular list
			push_nif_list(lua, message, env, resource_type);
		}
	}
	else if(enif_is_tuple(env, message))
	{	
		push_nif_tuple(lua, message, env, resource_type);
	}
	else if(enif_is_pid(env, message))
	{
		push_nif_pid(lua, message, env);
	}
	else if(enif_is_ref(env, message))
	{
		push_nif_ref(lua, message, env);
	}
	else if(enif_is_exception(env, message))
	{
		//printf("#exception\n");
		luaL_checkstack(lua, 1, ERROR_STACK_MESSAGE);
		lua_pushliteral(lua, "sending an exception is not supported");
	}
	else if(enif_is_fun(env, message))
	{
		//printf("#fun\n");
		luaL_checkstack(lua, 1, ERROR_STACK_MESSAGE);
		lua_pushliteral(lua, "sending a function reference is not supported");
	}
	else if(enif_is_port(env, message))
	{
		//printf("#port\n");
		luaL_checkstack(lua, 1, ERROR_STACK_MESSAGE);
		lua_pushliteral(lua, "sending a port is not supported");
	}
	else
	{
		// thank you r14 -- must be a number
		push_nif_number(lua, message, env);
	}
	assert(lua_gettop(lua) == top+1);
}
Пример #22
0
static ERL_NIF_TERM
gencall(ErlNifEnv *env, lua_State *L,
        const ERL_NIF_TERM arg_func,
        const ERL_NIF_TERM arg_fmt,
        const ERL_NIF_TERM arg_list)
{
    char buff_str[STACK_STRING_BUFF];
    char buff_fmt[STACK_STRING_BUFF];
    char buff_fun[STACK_STRING_BUFF/2];
    unsigned input_len=0;
    unsigned output_len=0;

    if(enif_get_string(env, arg_func, buff_fun, STACK_STRING_BUFF/2, ERL_NIF_LATIN1)<=0){
        return enif_make_badarg(env);
    }

    if(enif_get_string(env, arg_fmt, buff_fmt, STACK_STRING_BUFF, ERL_NIF_LATIN1)<=0){
        return enif_make_badarg(env);
    }

    if(!enif_is_list(env, arg_list)){
        return enif_make_badarg(env);
    }

    input_len = strchr(buff_fmt, ':') - buff_fmt;
    output_len = strlen(buff_fmt) - input_len -1;

    // printf("input args %d output args %d fun %s\n", input_len, output_len, buff_fun);
    ERL_NIF_TERM head,tail,list;
    list=arg_list;

    int i=0, status = 0, ret;
    ERL_NIF_TERM return_list = enif_make_list(env, 0);
    lua_getglobal(L, buff_fun);
    const char *error;

    while(buff_fmt[i]!='\0') {
        // printf("i:%d %c\n", i, buff_fmt[i]);

        if(status==0 && buff_fmt[i]!=':') {
            ret = enif_get_list_cell(env, list, &head, &tail);
            if(!ret) {
                error = FMT_AND_LIST_NO_MATCH;
                goto error;
            }
            list=tail;
        }

        switch(buff_fmt[i]) {
        case ':' :
            status=1;
            if(lua_pcall(L, input_len, output_len,0) != LUA_OK) {
                error = lua_tostring(L, -1);
                lua_pop(L,1);
                return enif_make_tuple2(env, atom_error, enif_make_string(env, error, ERL_NIF_LATIN1));
            }
            //output_len = - 1;
            break;
        case 'i':
            if( status == 0) {
                int input_int;
                ret = enif_get_int(env, head, &input_int);
                // printf("input %d\n", input_int);
                if(!ret) {
                    error = FMT_AND_LIST_NO_MATCH;
                    goto error;
                }

                lua_pushinteger(L, input_int);
            } else if ( status==1 ){
                int isnum;
                int n = lua_tointegerx(L, -1, &isnum);
                if(!isnum){
                    error = FMT_AND_LIST_NO_MATCH;
                    goto error;
                }
                // printf("output %d %d\n", output_len, n);
                return_list = enif_make_list_cell(env, enif_make_int(env, n), return_list);
                lua_pop(L,1);
                output_len--;
            }
            break;
        case 's':
            if( status == 0) {
                ret = enif_get_string(env, head, buff_str, STACK_STRING_BUFF, ERL_NIF_LATIN1);
                if(ret<=0) {
                    error = FMT_AND_LIST_NO_MATCH;
                    goto error;
                }
                lua_pushstring(L, buff_str);

            } else if ( status==1 ) {
                const char *s = lua_tostring(L, -1);
                if (s==NULL) {
                    error = FMT_AND_RET_NO_MATCH;
                    goto error;
                }
                // printf("output %d %s\n", output_len, s);
                return_list = enif_make_list_cell(env, enif_make_string(env, s, ERL_NIF_LATIN1), return_list);
                lua_pop(L,1);
                output_len--;
            }
            break;
            /* case 'd': */
            /*     break; */
            /* case 'b': */
            /*     break; */
        default:
            error = FMT_WRONG;
            goto error;
            break;
        }

        i++;
    }
    return enif_make_tuple2(env, atom_ok, return_list);

 error:
    // printf("in error \n");
    // @fix clean the heap var.
    // before call, pop the call
    if(status ==0 ) {
        lua_pop(L, 1);
    }
    else if(output_len>0) {
        lua_pop(L, output_len);
    }

    return make_error_tuple(env, error);
}
Пример #23
0
static ERL_NIF_TERM trace_call(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    lttng_decl_procbuf(pid);
    unsigned int len;
    char undef[] = "undefined";

    lttng_pid_to_str(argv[2], pid);

    if (argv[0] == atom_call) {
        const ERL_NIF_TERM* tuple;
        int arity;
        lttng_decl_mfabuf(mfa);

        if (enif_get_tuple(env, argv[3], &arity, &tuple)) {
            if (enif_is_list(env, tuple[2])) {
                enif_get_list_length(env, tuple[2], &len);
            } else {
                enif_get_uint(env, tuple[2], &len);
            }
            lttng_mfa_to_str(tuple[0], tuple[1], len, mfa);
            LTTNG3(function_call, pid, mfa, 0);
        } else {
            LTTNG3(function_call, pid, undef, 0);
        }
    } else if (argv[0] == atom_return_from) {
        const ERL_NIF_TERM* tuple;
        int arity;
        lttng_decl_mfabuf(mfa);

        if (enif_get_tuple(env, argv[3], &arity, &tuple)) {
            enif_get_uint(env, tuple[2], &len);
            lttng_mfa_to_str(tuple[0], tuple[1], len, mfa);
            LTTNG3(function_return, pid, mfa, 0);
        } else {
            LTTNG3(function_return, pid, undef, 0);
        }
    } else if (argv[0] == atom_return_to) {
        const ERL_NIF_TERM* tuple;
        int arity;
        lttng_decl_mfabuf(mfa);

        if (enif_get_tuple(env, argv[3], &arity, &tuple)) {
            enif_get_uint(env, tuple[2], &len);
            lttng_mfa_to_str(tuple[0], tuple[1], len, mfa);
            LTTNG3(function_return, pid, mfa, 0);
        } else {
            LTTNG3(function_return, pid, undef, 0);
        }
    } else if (argv[0] == atom_exception_from) {
        const ERL_NIF_TERM* tuple;
        int arity;
        lttng_decl_mfabuf(mfa);
        char class[LTTNG_BUFFER_SZ];

        enif_get_tuple(env, argv[4], &arity, &tuple);
        erts_snprintf(class, LTTNG_BUFFER_SZ, "%T", tuple[0]);

        if (enif_get_tuple(env, argv[3], &arity, &tuple)) {
            enif_get_uint(env, tuple[2], &len);
            lttng_mfa_to_str(tuple[0], tuple[1], len, mfa);
            LTTNG3(function_exception, pid, mfa, class);
        } else {
Пример #24
0
ERL_NIF_TERM
encode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    Encoder enc;
    Encoder* e = &enc;

    ErlNifBinary bin;
    ERL_NIF_TERM ret;

    ERL_NIF_TERM stack;
    ERL_NIF_TERM curr;
    ERL_NIF_TERM item;
    const ERL_NIF_TERM* tuple;
    int arity;
    ErlNifSInt64 lval;
    double dval;

    if(argc != 2) {
        return enif_make_badarg(env);
    }

    if(!enc_init(e, env, argv[1], &bin)) {
        return enif_make_badarg(env);
    }

    stack = enif_make_list(env, 1, argv[0]);

    while(!enif_is_empty_list(env, stack)) {
        if(!enif_get_list_cell(env, stack, &curr, &stack)) {
            ret = enc_error(e, "internal_error");
            goto done;
        }
        if(enif_is_identical(curr, e->atoms->ref_object)) {
            if(!enif_get_list_cell(env, stack, &curr, &stack)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(enif_is_empty_list(env, curr)) {
                if(!enc_end_object(e)) {
                    ret = enc_error(e, "internal_error");
                    goto done;
                }
                continue;
            }
            if(!enif_get_list_cell(env, curr, &item, &curr)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(!enif_get_tuple(env, item, &arity, &tuple)) {
                ret = enc_error(e, "invalid_object_pair");
                goto done;
            }
            if(arity != 2) {
                ret = enc_error(e, "invalid_object_pair");
                goto done;
            }
            if(!enc_comma(e)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(!enc_string(e, tuple[0])) {
                ret = enc_error(e, "invalid_object_key");
                goto done;
            }
            if(!enc_colon(e)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            stack = enif_make_list_cell(env, curr, stack);
            stack = enif_make_list_cell(env, e->atoms->ref_object, stack);
            stack = enif_make_list_cell(env, tuple[1], stack);
        } else if(enif_is_identical(curr, e->atoms->ref_array)) {
            if(!enif_get_list_cell(env, stack, &curr, &stack)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(enif_is_empty_list(env, curr)) {
                if(!enc_end_array(e)) {
                    ret = enc_error(e, "internal_error");
                    goto done;
                }
                continue;
            }
            if(!enc_comma(e)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(!enif_get_list_cell(env, curr, &item, &curr)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            stack = enif_make_list_cell(env, curr, stack);
            stack = enif_make_list_cell(env, e->atoms->ref_array, stack);
            stack = enif_make_list_cell(env, item, stack);
        } else if(enif_compare(curr, e->atoms->atom_null) == 0) {
            if(!enc_literal(e, "null", 4)) {
                ret = enc_error(e, "null");
                goto done;
            }
        } else if(enif_compare(curr, e->atoms->atom_true) == 0) {
            if(!enc_literal(e, "true", 4)) {
                ret = enc_error(e, "true");
                goto done;
            }
        } else if(enif_compare(curr, e->atoms->atom_false) == 0) {
            if(!enc_literal(e, "false", 5)) {
                ret = enc_error(e, "false");
                goto done;
            }
        } else if(enif_is_binary(env, curr)) {
            if(!enc_string(e, curr)) {
                ret = enc_error(e, "invalid_string");
                goto done;
            }
        } else if(enif_is_atom(env, curr)) {
            if(!enc_string(e, curr)) {
                ret = enc_error(e, "invalid_string");
                goto done;
            }
        } else if(enif_get_int64(env, curr, &lval)) {
            if(!enc_long(e, lval)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
        } else if(enif_get_double(env, curr, &dval)) {
            if(!enc_double(e, dval)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
        } else if(enif_get_tuple(env, curr, &arity, &tuple)) {
            if(arity != 1) {
                ret = enc_error(e, "invalid_ejson");
                goto done;
            }
            if(!enif_is_list(env, tuple[0])) {
                ret = enc_error(e, "invalid_object");
                goto done;
            }
            if(!enc_start_object(e)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(enif_is_empty_list(env, tuple[0])) {
                if(!enc_end_object(e)) {
                    ret = enc_error(e, "internal_error");
                    goto done;
                }
                continue;
            }
            if(!enif_get_list_cell(env, tuple[0], &item, &curr)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(!enif_get_tuple(env, item, &arity, &tuple)) {
                ret = enc_error(e, "invalid_object_member");
                goto done;
            }
            if(arity != 2) {
                ret = enc_error(e, "invalid_object_member_arity");
                goto done;
            }
            if(!enc_string(e, tuple[0])) {
                ret = enc_error(e, "invalid_object_member_key");
                goto done;
            }
            if(!enc_colon(e)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            stack = enif_make_list_cell(env, curr, stack);
            stack = enif_make_list_cell(env, e->atoms->ref_object, stack);
            stack = enif_make_list_cell(env, tuple[1], stack);
        } else if(enif_is_list(env, curr)) {
            if(!enc_start_array(e)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            if(enif_is_empty_list(env, curr)) {
                if(!enc_end_array(e)) {
                    ret = enc_error(e, "internal_error");
                    goto done;
                }
                continue;
            }
            if(!enif_get_list_cell(env, curr, &item, &curr)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
            stack = enif_make_list_cell(env, curr, stack);
            stack = enif_make_list_cell(env, e->atoms->ref_array, stack);
            stack = enif_make_list_cell(env, item, stack);
        } else {
            if(!enc_unknown(e, curr)) {
                ret = enc_error(e, "internal_error");
                goto done;
            }
        }
    }

    if(!enc_done(e, &item)) {
        ret = enc_error(e, "internal_error");
        goto done;
    }

    if(e->iolen == 0) {
        ret = item;
    } else {
        ret = enif_make_tuple2(env, e->atoms->atom_partial, item);
    }

done:
    enc_destroy(e);
    return ret;
}
Пример #25
0
/* 0: list */
    static ERL_NIF_TERM
nif_alloc(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    ERL_NIF_TERM head = {0};
    ERL_NIF_TERM tail = {0};

    int arity = 0;
    char key[MAXATOMLEN+1];  /* Includes terminating NULL */
    const ERL_NIF_TERM *array = NULL;

    ERL_NIF_TERM resources = {0};
    ErlNifBinary req = {0};


    if (!enif_is_list(env, argv[0]) || enif_is_empty_list(env, argv[0]))
        return enif_make_badarg(env);

    resources = enif_make_list(env, 0);
    if (!enif_alloc_binary(0, &req))
        return error_tuple(env, ENOMEM);

    tail = argv[0];

    /* [binary(), {ptr, integer()}, {ptr, binary()}, ...] */
    while (enif_get_list_cell(env, tail, &head, &tail)) {
        int index = req.size;
        ErlNifBinary bin = {0};

        if (enif_inspect_binary(env, head, &bin)) {
            enif_realloc_binary(&req, req.size+bin.size);
            (void)memcpy(req.data+index, bin.data, bin.size);
        }
        else if (enif_get_tuple(env, head, &arity, &array)) {
            ALLOC_STATE *p = NULL;
            ERL_NIF_TERM res = {0};
            size_t val = 0;
            ErlNifBinary initial = {0};

            if ( (arity != 2) ||
                !enif_get_atom(env, array[0], key, sizeof(key), ERL_NIF_LATIN1) ||
                (strcmp(key, "ptr") != 0))
                return enif_make_badarg(env);

            if ( !(enif_get_ulong(env, array[1], (unsigned long *)&val) && val > 0) &&
                !(enif_inspect_binary(env, array[1], &initial) && initial.size > 0))
                return enif_make_badarg(env);

            val = (initial.size > 0) ? initial.size : val;

            p = enif_alloc_resource(PROCKET_ALLOC_RESOURCE, sizeof(ALLOC_STATE));

            if (p == NULL)
                return error_tuple(env, ENOMEM);

            p->size = val;
            p->buf = calloc(val, 1);

            if (p->buf == NULL) {
                enif_release_resource(p);
                return error_tuple(env, ENOMEM);
            }

            if (initial.size > 0)
                (void)memcpy(p->buf, initial.data, p->size);

            if (!enif_realloc_binary(&req, req.size+sizeof(void *)))
                return error_tuple(env, ENOMEM);

            (void)memcpy(req.data+index, &p->buf, sizeof(void *));

            res = enif_make_resource(env, p);
            enif_release_resource(p);

            resources = enif_make_list_cell(env, res, resources);
        }
        else
            return enif_make_badarg(env);
    }

    return enif_make_tuple3(env, atom_ok,
            enif_make_binary(env, &req),
            resources);
}
Пример #26
0
static mrb_value erl2mruby(ErlNifEnv* env, mrb_state* mrb, ERL_NIF_TERM term) {
  if (enif_is_atom(env, term)) {
    unsigned len;
    enif_get_atom_length(env, term, &len, ERL_NIF_LATIN1);
    char * atom_str = (char *)malloc(sizeof(char)*(len+1));
    int r = enif_get_atom(env, term, atom_str, len+1, ERL_NIF_LATIN1);
    mrb_value value;
    if(strncmp(atom_str, "nil", r) == 0){
      value = mrb_nil_value();
    }else if(strncmp(atom_str, "true", r) == 0){
      value = mrb_true_value();
    }else if(strncmp(atom_str, "false", r) == 0){
      value = mrb_false_value();
    }else{
      value = mrb_symbol_value(mrb_intern_cstr(mrb, atom_str));
    }
    free(atom_str);
    return value;
  } else if (enif_is_binary(env, term)) {
    ErlNifBinary bin;
    enif_inspect_binary(env, term, &bin);
    return mrb_str_new(mrb, (const char *)bin.data, bin.size);
  } else if (enif_is_number(env, term)) {
    double d;
    if (enif_get_double(env, term, &d)) {
      return mrb_float_value(mrb, (mrb_float)d);
    } else {
      ErlNifSInt64 i;
      enif_get_int64(env, term, &i);
      return mrb_fixnum_value((mrb_int)i);
    }
  } else if (enif_is_empty_list(env, term)) {
    return mrb_ary_new(mrb);
  } else if (enif_is_list(env, term)) {
    unsigned len;
    enif_get_list_length(env, term, &len);
    mrb_value ary = mrb_ary_new(mrb);
    ERL_NIF_TERM cur;
    for (cur = term; !enif_is_empty_list(env, cur); ) {
      ERL_NIF_TERM head, tail;
      enif_get_list_cell(env, cur, &head, &tail);

      mrb_ary_push(mrb, ary, erl2mruby(env, mrb, head));
      cur = tail;
    }
    return ary;
  } else if (enif_is_tuple(env, term)) {
    int arity;
    const ERL_NIF_TERM * array;
    enif_get_tuple(env, term, &arity, &array);

    unsigned len = 0;
    enif_get_list_length(env, array[0], &len);
    mrb_value hash = mrb_hash_new(mrb);

    ERL_NIF_TERM cur;
    for(cur = array[0]; !enif_is_empty_list(env, cur); ){
      ERL_NIF_TERM head, tail;
      enif_get_list_cell(env, cur, &head, &tail);
      const ERL_NIF_TERM * array0;
      int arity0;
      enif_get_tuple(env, head, &arity0, &array0);

      mrb_hash_set(mrb, hash, erl2mruby(env, mrb, array0[0]), erl2mruby(env, mrb, array0[1]));

      cur = tail;
    }
    return hash;
  } else {
    return mrb_nil_value();
  }
}
Пример #27
0
ERL_NIF_TERM _hi_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    hi_ctx_t* ctx = NULL;
    hh_ctx_t* hdr = NULL;
    hi_opts_t* opts = NULL;

    ErlNifResourceType* hh_ctx_type = get_hh_ctx_type(env);
    ErlNifResourceType* hi_ctx_type = get_hi_ctx_type(env);
    if (argc != 3 ||
        hh_ctx_type == NULL ||
        hi_ctx_type == NULL ||
        !enif_get_resource(env, argv[0], hi_ctx_type, (void **)&ctx) ||
        !enif_get_resource(env, argv[1], hh_ctx_type, (void **)&hdr) ||
        !enif_is_list(env, argv[2]))
    {
        return enif_make_badarg(env);
    }

    opts = (hi_opts_t *)enif_alloc(sizeof(hi_opts_t));
    parse_opts(env, argv[2], opts, (void *)parse_opt);
    uint32_t iterator_type = ctx->type;

    void* it = NULL;

    if (iterator_type == HDR_ITER_REC)
    {
        struct hdr_recorded_iter * iter =
            enif_alloc(sizeof(struct hdr_recorded_iter));
        hdr_recorded_iter_init(iter, hdr->data);
        it = iter;
    }

    if (iterator_type == HDR_ITER_LIN)
    {
        if (opts->linear_value_units_per_bucket <= 0)
        {
            return make_error(env, "bad_linear_value_unit");
        }
        struct hdr_linear_iter * iter =
            enif_alloc(sizeof(struct hdr_linear_iter));
        hdr_linear_iter_init(
            iter,
            hdr->data,
            opts->linear_value_units_per_bucket);
        it = iter;
    }

    if (iterator_type == HDR_ITER_LOG)
    {
        if (opts->log_value_units_first_bucket <= 0)
        {
            return make_error(env, "bad_log_value_unit");
        }
        if (opts->log_base <= 0)
        {
            return make_error(env, "bad_log_base");
        }
        struct hdr_log_iter * iter =
            enif_alloc(sizeof(struct hdr_log_iter));
        hdr_log_iter_init(
            iter,
            hdr->data,
            opts->log_value_units_first_bucket,
            opts->log_base);
        it = iter;
    }

    if (iterator_type == HDR_ITER_PCT)
    {
        if (opts->percentile_ticks_per_half_distance <= 0)
        {
            return make_error(env, "bad_percentile_half_ticks");
        }
        struct hdr_percentile_iter * iter =
            enif_alloc(sizeof(struct hdr_percentile_iter));
        hdr_percentile_iter_init(
            iter,
            hdr->data,
            opts->percentile_ticks_per_half_distance);
        it = iter;
    }

    ctx->type = iterator_type;
    ctx->opts = opts;
    ctx->iter = it;

    return ATOM_OK;
}
Пример #28
0
static void
ks_selector_arg(ks_returner_t *ret, ks_pattern_t *pattern, ERL_NIF_TERM arg)
{
	unsigned	size;
	char		*string;
	int		result;
	ErlNifSInt64	integer;

	if (ret->ready != B_TRUE) {
		if (enif_is_atom(ret->env, arg)) {
			enif_get_atom_length(ret->env, arg, &size, ERL_NIF_LATIN1);
			string = (char *)(malloc(sizeof (char) * (size + 1)));
			if (string == NULL) {
				ret->term = EKSTAT_ERROR("atom malloc");
				ret->ready = B_TRUE;
				return;
			}
			result = enif_get_atom(ret->env, arg, string, size + 1, ERL_NIF_LATIN1);
			if (result == 0) {
				ret->term = enif_make_badarg(ret->env);
				ret->ready = B_TRUE;
			} else {
				if (strncmp(string, "_", result) == 0) {
					pattern->pstr = "*";
					pattern->free = B_FALSE;
				} else {
					ret->term = enif_make_badarg(ret->env);
					ret->ready = B_TRUE;
				}
				free(string);
			}
		} else if (enif_is_list(ret->env, arg)) {
			enif_get_list_length(ret->env, arg, &size);
			string = (char *)(malloc(sizeof (char) * (size + 1)));
			if (string == NULL) {
				ret->term = EKSTAT_ERROR("list malloc");
				ret->ready = B_TRUE;
				return;
			}
			result = enif_get_string(ret->env, arg, string, size + 1, ERL_NIF_LATIN1);
			if (result == 0) {
				ret->term = enif_make_badarg(ret->env);
				ret->ready = B_TRUE;
			} else {
				pattern->pstr = (char *)(ks_safe_strdup(ret, string));
				pattern->free = B_TRUE;
			}
			free(string);
		} else if (enif_is_number(ret->env, arg)) {
			if (enif_get_int64(ret->env, arg, &integer)) {
				(void) asprintf(&string, "%d", integer);
				pattern->pstr = (char *)(ks_safe_strdup(ret, string));
				pattern->free = B_TRUE;
			} else {
				ret->term = enif_make_badarg(ret->env);
				ret->ready = B_TRUE;
			}
			free(string);
		} else {
			ret->term = enif_make_badarg(ret->env);
			ret->ready = B_TRUE;
		}
	}
}
Пример #29
0
static ERL_NIF_TERM
mmap_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
  Mmap *desc;
  ERL_NIF_TERM f;
  ErlNifBinary bin_path;
  char path[PATH_SIZE];
  int fd;
  struct stat st;
  int debug = 0;
  ERL_NIF_TERM opt, opts;
  
  
  if (!enif_inspect_binary(env, argv[0], &bin_path)) {
    return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_string(env, "Should pass binary filename", ERL_NIF_LATIN1));
  }
  if (!enif_is_list(env, argv[1])) {
    return enif_make_badarg(env);
  }
  
  bzero(path, PATH_SIZE);
  strncpy(path, (const char *)bin_path.data, bin_path.size >= PATH_SIZE ? PATH_SIZE - 1 : bin_path.size);
  
  opts = argv[1];
  while(enif_get_list_cell(env, opts, &opt, &opts)) {
    if(!enif_compare(opt, enif_make_atom(env, "debug"))) {
      debug = 1;
    }
  }
  
  
  fd = open(path, O_RDONLY);
  if(fd == -1) {
    return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_string(env, strerror(errno), ERL_NIF_LATIN1));
  }
  if(fstat(fd, &st)) {
    close(fd);
    return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_string(env, strerror(errno), ERL_NIF_LATIN1));
  }
  
  if (debug) fprintf(stderr, "Opened file %s %ld\r\n", path, (ssize_t)st.st_size);
  
  desc = (Mmap *)enif_alloc_resource(MmapResource, sizeof(Mmap));
  if(!desc) {
    close(fd);
    return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_string(env, "Couldn't allocate mmap resource", ERL_NIF_LATIN1));
  }
  desc->fd = fd;
  desc->size = st.st_size;
  if (debug) fprintf(stderr, "Mmaping file: %p\r\n", desc);
  desc->ptr = mmap(NULL, desc->size, PROT_READ, MAP_FILE | MAP_PRIVATE, desc->fd, 0);
  close(fd);
  if(desc->ptr == MAP_FAILED) {
    enif_release_resource(desc);
    return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_string(env, "Couldn't mmap", ERL_NIF_LATIN1));
  }
  if (debug) fprintf(stderr, "Mmaped file to %p\r\n", desc->ptr);
  f = enif_make_resource_binary(env, (void *)desc, desc->ptr, desc->size);
  enif_release_resource(desc);
  desc->debug = debug;
  
  return enif_make_tuple2(env, enif_make_atom(env, "ok"), f);
}
Пример #30
0
    static ERL_NIF_TERM
nif_sendmsg(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    int sockfd = -1;
    int flags = 0;

    ssize_t n = 0;

    ErlNifBinary buf = {0};
    ErlNifBinary sa = {0};

    ERL_NIF_TERM cdata_list, head, tail;

    char *cdata = NULL;
    struct iovec iov[1];
    struct msghdr message;
    struct cmsghdr *cmsg;
    size_t cdata_size = 0;

    if (!enif_get_int(env, argv[0], &sockfd))
        return enif_make_badarg(env);

    if (!enif_inspect_binary(env, argv[1], &buf))
        return enif_make_badarg(env);

    if (!enif_get_int(env, argv[2], &flags))
        return enif_make_badarg(env);

    if (!enif_is_list(env, argv[3]))
        return enif_make_badarg(env);

    if (!enif_inspect_binary(env, argv[4], &sa))
        return enif_make_badarg(env);

    cdata_list = argv[3];

    // figure out how much control data we'll need to send
    while(enif_get_list_cell(env, cdata_list, &head, &tail)) {
        const ERL_NIF_TERM* fields;
        int arity;
        int level, type;
        ErlNifBinary cdata_field = {0};
        if (!enif_get_tuple(env, head, &arity, &fields) || arity != 3) {
            return enif_make_badarg(env);
        }

        if (!enif_get_int(env, fields[0], &level)) {
            return enif_make_badarg(env);
        }

        if (!enif_get_int(env, fields[1], &type)) {
            return enif_make_badarg(env);
        }

        if (!enif_inspect_binary(env, fields[2], &cdata_field)) {
            return enif_make_badarg(env);
        }

        cdata_size += CMSG_SPACE(cdata_field.size);

        cdata_list = tail;
    }

    if (cdata_size > 0) {
        // allocate enough control data space, if any
        // freebsd throws einval if the cdata length is 0
        // but the pointer isn't NULL
        if (!(cdata = malloc(cdata_size))) {
            return error_tuple(env, ENOMEM);
        }
    }

    // set up the iov and msghdr stuff
    iov[0].iov_base=(buf.size == 0 ? NULL : buf.data);
    iov[0].iov_len=buf.size;

    message.msg_name=(sa.size == 0 ? NULL : sa.data);
    message.msg_namelen=sa.size;
    message.msg_iov=iov;
    message.msg_iovlen=1;
    message.msg_control=cdata;
    message.msg_controllen=cdata_size;


    // loop over the control data again, this time filling in the data in the
    // msghdr
    cdata_list = argv[3];

    cmsg = CMSG_FIRSTHDR(&message);

    while(cmsg && enif_get_list_cell(env, cdata_list, &head, &tail)) {
        const ERL_NIF_TERM* fields;
        int arity;
        unsigned char *cmsg_data;
        ErlNifBinary cdata_field = {0};
        // don't need to check here, we'd have crashed in the last loop if
        // things were wrong
        enif_get_tuple(env, head, &arity, &fields);
        enif_get_int(env, fields[0], &cmsg->cmsg_level);
        enif_get_int(env, fields[1], &cmsg->cmsg_type);
        enif_inspect_binary(env, fields[2], &cdata_field);
        cmsg_data = CMSG_DATA(cmsg);
        // copy the control data into the cdata struct
        memcpy(cmsg_data, cdata_field.data, cdata_field.size);

        // set the length
        cmsg->cmsg_len=CMSG_LEN(cdata_field.size);

        cdata_list = tail;
        cmsg = CMSG_NXTHDR(&message,cmsg);
    }

    n = sendmsg(sockfd, &message, flags);

    if (n < 0)
        return error_tuple(env, errno);

    return enif_make_tuple2(env, atom_ok, enif_make_int64(env, n));
}