// int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen); static ERL_NIF_TERM nif_getsockname(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { int s = -1; ErlNifBinary addr = {0}; socklen_t addrlen = 0; if (!enif_get_int(env, argv[0], &s)) return enif_make_badarg(env); if (!enif_inspect_binary(env, argv[1], &addr)) return enif_make_badarg(env); /* Make the binary mutable */ if (!enif_realloc_binary(&addr, addr.size)) return error_tuple(env, ENOMEM); addrlen = addr.size; if (getsockname(s, (struct sockaddr *)addr.data, (socklen_t *)&addrlen) < 0) return error_tuple(env, errno); PROCKET_REALLOC(addr, addrlen); return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &addr)); }
/* 0: procotol, 1: type, 2: family */ static ERL_NIF_TERM nif_socket(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { int s = -1; int family = 0; int type = 0; int protocol = 0; int flags = 0; if (!enif_get_int(env, argv[0], &family)) return enif_make_badarg(env); if (!enif_get_int(env, argv[1], &type)) return enif_make_badarg(env); if (!enif_get_int(env, argv[2], &protocol)) return enif_make_badarg(env); s = socket(family, type, protocol); if (s < 0) return error_tuple(env, errno); flags = fcntl(s, F_GETFL, 0); if (flags < 0) return error_tuple(env, errno); if (fcntl(s, F_SETFL, flags|O_NONBLOCK) < 0) return error_tuple(env, errno); return enif_make_tuple2(env, atom_ok, enif_make_int(env, s)); }
static ERL_NIF_TERM nif_setns(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { #ifdef HAVE_SETNS int fd; ErlNifBinary buf = {0}; int nstype = 0; int errnum = 0; if (!enif_inspect_iolist_as_binary(env, argv[0], &buf)) return enif_make_badarg(env); if (!enif_get_int(env, argv[1], &nstype)) return enif_make_badarg(env); PROCKET_REALLOC(buf, buf.size+1); buf.data[buf.size-1] = '\0'; fd = open((const char*)buf.data, O_RDONLY); /* Get descriptor for namespace */ if (fd < 0) return error_tuple(env, errno); if (setns(fd, nstype) == -1) { errnum = errno; (void)close(fd); return error_tuple(env, errnum); } (void)close(fd); return atom_ok; #else return error_tuple(env, ENOTSUP); #endif }
/* 0: socket, 1: length */ static ERL_NIF_TERM nif_read(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { int fd = -1; unsigned long len = 0; ErlNifBinary buf = {0}; ssize_t bufsz = 0; if (!enif_get_int(env, argv[0], &fd)) return enif_make_badarg(env); if (!enif_get_ulong(env, argv[1], &len)) return enif_make_badarg(env); if (!enif_alloc_binary(len, &buf)) return error_tuple(env, ENOMEM); if ( (bufsz = read(fd, buf.data, buf.size)) == -1) { int err = errno; enif_release_binary(&buf); switch (err) { case EAGAIN: case EINTR: return enif_make_tuple2(env, atom_error, atom_eagain); default: return error_tuple(env, err); } } PROCKET_REALLOC(buf, bufsz); return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &buf)); }
static ERL_NIF_TERM nif_open(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary dev; SRLY_STATE *sp = NULL; if (!enif_inspect_iolist_as_binary(env, argv[0], (ErlNifBinary *)&dev)) return enif_make_badarg(env); sp = enif_alloc_resource(SRLY_STATE_RESOURCE, sizeof(SRLY_STATE)); if (sp == NULL) return error_tuple(env, ENOMEM); if (!enif_realloc_binary(&dev, dev.size+1)) return enif_make_badarg(env); dev.data[dev.size-1] = '\0'; sp->fd = open((char *)dev.data, O_RDWR|O_NOCTTY|O_NONBLOCK); if (sp->fd < 0 || isatty(sp->fd) != 1) { int err = errno; enif_release_resource(sp); return error_tuple(env, err); } return enif_make_tuple2(env, atom_ok, enif_make_resource(env, sp)); }
static ERL_NIF_TERM nif_sendmsg(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { int s = -1; ErlNifBinary msg = {0}; int flags = 0; ssize_t n = 0; if (!enif_get_int(env, argv[0], &s)) return enif_make_badarg(env); if (!enif_inspect_binary(env, argv[1], &msg)) return enif_make_badarg(env); if (!enif_get_int(env, argv[2], &flags)) return enif_make_badarg(env); if (msg.size != sizeof(struct msghdr)) return enif_make_badarg(env); /* Make the binary mutable */ if (!enif_realloc_binary(&msg, msg.size)) return error_tuple(env, ENOMEM); n = sendmsg(s, (const struct msghdr *)msg.data, flags); if (n < 0) return error_tuple(env, errno); return enif_make_tuple3(env, atom_ok, enif_make_ulong(env, n), enif_make_binary(env, &msg)); }
static ERL_NIF_TERM nif_ioctl(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { SRLY_STATE *sp = NULL; unsigned long req = 0; ErlNifBinary arg = {0}; if (!enif_get_resource(env, argv[0], SRLY_STATE_RESOURCE, (void **)&sp)) return enif_make_badarg(env); if (!enif_get_ulong(env, argv[1], &req)) return enif_make_badarg(env); if (!enif_inspect_binary(env, argv[2], &arg)) return enif_make_badarg(env); /* Make the binary mutable for in/out args */ if (!enif_realloc_binary(&arg, arg.size)) return error_tuple(env, ENOMEM); if (ioctl(sp->fd, req, arg.data) < 0) return error_tuple(env, errno); return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &arg)); }
static ERL_NIF_TERM nif_tcgetattr(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { SRLY_STATE *sp = NULL; ErlNifBinary buf = {0}; int err = 0; if (!enif_get_resource(env, argv[0], SRLY_STATE_RESOURCE, (void **)&sp)) return enif_make_badarg(env); if (!enif_alloc_binary(sizeof(struct termios), &buf)) return error_tuple(env, ENOMEM); if (tcgetattr(sp->fd, (struct termios *)buf.data) < 0) { err = errno; enif_release_binary(&buf); return error_tuple(env, err); } return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &buf)); }
static ERL_NIF_TERM nif_read(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { SRLY_STATE *sp = NULL; unsigned long len = 0; ErlNifBinary buf = {0}; ssize_t bufsz = 0; if (!enif_get_resource(env, argv[0], SRLY_STATE_RESOURCE, (void **)&sp)) return enif_make_badarg(env); if (!enif_get_ulong(env, argv[1], &len)) return enif_make_badarg(env); if (!enif_alloc_binary(len, &buf)) return error_tuple(env, ENOMEM); if ( (bufsz = read(sp->fd, buf.data, buf.size)) < 0) { int err = errno; enif_release_binary(&buf); return error_tuple(env, err); } if (bufsz < buf.size && !enif_realloc_binary(&buf, bufsz)) { enif_release_binary(&buf); return error_tuple(env, ENOMEM); } return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &buf)); }
/* 0: socket, 1: length, 2: flags, 3: struct sockaddr length */ static ERL_NIF_TERM nif_recvfrom(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { int sockfd = -1; unsigned long len = 0; unsigned long salen = 0; int flags = 0; ErlNifBinary buf = {0}; ErlNifBinary sa = {0}; ssize_t bufsz = 0; if (!enif_get_int(env, argv[0], &sockfd)) return enif_make_badarg(env); if (!enif_get_ulong(env, argv[1], &len)) return enif_make_badarg(env); if (!enif_get_int(env, argv[2], &flags)) return enif_make_badarg(env); if (!enif_get_ulong(env, argv[3], &salen)) return enif_make_badarg(env); if (!enif_alloc_binary(len, &buf)) return error_tuple(env, ENOMEM); if (!enif_alloc_binary(salen, &sa)) return error_tuple(env, ENOMEM); if ( (bufsz = recvfrom(sockfd, buf.data, buf.size, flags, (sa.size == 0 ? NULL : (struct sockaddr *)sa.data), (socklen_t *)&salen)) == -1) { enif_release_binary(&buf); enif_release_binary(&sa); switch (errno) { case EAGAIN: case EINTR: return enif_make_tuple2(env, atom_error, atom_eagain); default: return error_tuple(env, errno); } } PROCKET_REALLOC(buf, bufsz); PROCKET_REALLOC(sa, salen); return enif_make_tuple3(env, atom_ok, enif_make_binary(env, &buf), enif_make_binary(env, &sa)); }
void encode_ok_reply(state *st, int code) { if (code == OK) { ok(st); } else { error_tuple(st, code); } }
/* 0: socket, 1: buffer, 2: flags, 3: struct sockaddr */ static ERL_NIF_TERM nif_sendto(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { int sockfd = -1; int flags = 0; ErlNifBinary buf = {0}; ErlNifBinary sa = {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_inspect_binary(env, argv[3], &sa)) return enif_make_badarg(env); if (sendto(sockfd, buf.data, buf.size, flags, (sa.size == 0 ? NULL : (struct sockaddr *)sa.data), sa.size) == -1) return error_tuple(env, errno); return atom_ok; }
// creates a new simple dataspace and opens it for access ERL_NIF_TERM h5screate_simple(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { hid_t dataspace_id; ERL_NIF_TERM ret; const ERL_NIF_TERM *terms; int rank; // number of dimensions of dataspace hsize_t* dimsf; // array specifiying the size of each dimension int arity; // parse arguments check(argc == 2, "Incorrent number of arguments"); check(enif_get_int(env, argv[0], &rank ), "Can't get rank from argv"); check(enif_get_tuple(env, argv[1], &arity, &terms), "Can't get terms from argv"); // make sure that rank is matching arity check(rank <= 2, "does not support > 2 dimensions"); // allocate array of size rank dimsf = (hsize_t*) malloc(arity * sizeof(hsize_t)); check(!convert_nif_to_hsize_array(env, arity, terms, dimsf), "can't convert dims arr"); // create a new file using default properties dataspace_id = H5Screate_simple(rank, dimsf, NULL); check(dataspace_id > 0, "Failed to create dataspace."); // cleanup free(dimsf); ret = enif_make_int(env, dataspace_id); return enif_make_tuple2(env, ATOM_OK, ret); error: if(dataspace_id) H5Sclose(dataspace_id); if(dimsf) free(dimsf); return error_tuple(env, "Can not create dataspace"); };
/* 0: int socket descriptor, 1: int level, * 2: int optname, 3: void *optval */ static ERL_NIF_TERM nif_setsockopt(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { int s = -1; int level = 0; int optname = 0; ErlNifBinary optval = {0}; if (!enif_get_int(env, argv[0], &s)) return enif_make_badarg(env); if (!enif_get_int(env, argv[1], &level)) return enif_make_badarg(env); if (!enif_get_int(env, argv[2], &optname)) return enif_make_badarg(env); if (!enif_inspect_binary(env, argv[3], &optval)) return enif_make_badarg(env); if (setsockopt(s, level, optname, optval.data, optval.size) < 0) return error_tuple(env, errno); return atom_ok; }
static ERL_NIF_TERM nif_write(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { SRLY_STATE *sp = NULL; ErlNifBinary buf = {0}; ssize_t n = -1; ERL_NIF_TERM rv = atom_ok; if (!enif_get_resource(env, argv[0], SRLY_STATE_RESOURCE, (void **)&sp)) return enif_make_badarg(env); if (!enif_inspect_iolist_as_binary(env, argv[1], (ErlNifBinary *)&buf)) return enif_make_badarg(env); n = write(sp->fd, buf.data, buf.size); if (n < 0) rv = error_tuple(env, errno); else if (n != buf.size) rv = enif_make_tuple2(env, atom_ok, enif_make_long(env, n)); return rv; }
static ERL_NIF_TERM add(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { PRIVDATA *data = NULL; int k = 0; int v = 0; int nelem = 0; data = (PRIVDATA *)enif_priv_data(env); nelem = NELEM(data); if ( !enif_get_int(env, argv[0], &k) || !enif_get_int(env, argv[1], &v)) return enif_make_badarg(env); if ( (k < 0) || (k >= nelem)) return error_tuple(env, "out_of_bounds"); enif_mutex_lock(data->lock); VAL(data, k) += v; v = VAL(data, k); enif_mutex_unlock(data->lock); return enif_make_int(env, v); }
/* 0: (int)socket descriptor, 1: (int)device dependent request, * 2: (char *)argp, pointer to structure | int */ static ERL_NIF_TERM nif_ioctl(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { int s = -1; unsigned long req = 0; ErlNifBinary arg = {0}; int n = 0; if (!enif_get_int(env, argv[0], &s)) return enif_make_badarg(env); if (!enif_get_ulong(env, argv[1], &req)) return enif_make_badarg(env); if (enif_inspect_binary(env, argv[2], &arg)) { /* Make the binary mutable */ if (!enif_realloc_binary(&arg, arg.size)) return error_tuple(env, ENOMEM); if (ioctl(s, req, arg.data) < 0) return error_tuple(env, errno); } else if (enif_get_int(env, argv[2], &n)) { /* XXX integer args allow the caller to * XXX pass in arbitrary pointers */ if (ioctl(s, req, n) < 0) return error_tuple(env, errno); /* return an empty binary */ if (!enif_alloc_binary(0, &arg)) return error_tuple(env, ENOMEM); } else return enif_make_badarg(env); return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &arg)); }
ERL_NIF_TERM vert_virNodeListDevices(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { VERT_RESOURCE *vp = NULL; ErlNifBinary cap = {0}; char **names = NULL; int maxnames = 0; u_int32_t flags = 0; int n = 0; int rv = 0; ERL_NIF_TERM dev = {0}; VERT_GET_RESOURCE(0, vp, VERT_RES_CONNECT); VERT_GET_IOLIST(1, cap); VERT_GET_INT(2, maxnames); VERT_GET_UINT(3, flags); if (cap.size > 0) VERT_BIN_APPEND_NULL(cap); names = calloc(maxnames, sizeof(char *)); if (names == NULL) return error_tuple(env, atom_enomem); rv = virNodeListDevices(vp->res, (cap.size == 0 ? NULL : (char *)cap.data), names, maxnames, flags); if (rv < 0) goto ERR; dev = enif_make_list(env, 0); for (n = 0; n < rv; n++) { dev = enif_make_list_cell(env, enif_make_string(env, names[n], ERL_NIF_LATIN1), dev); } free(names); return enif_make_tuple2(env, atom_ok, dev); ERR: free(names); return verterr(env); }
/* 0: socket, 1: struct sockaddr length */ static ERL_NIF_TERM nif_accept(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { int l = -1; int s = -1; unsigned long salen = 0; ErlNifBinary sa = {0}; int flags = 0; if (!enif_get_int(env, argv[0], &l)) return enif_make_badarg(env); if (!enif_get_ulong(env, argv[1], &salen)) return enif_make_badarg(env); if (!enif_alloc_binary(salen, &sa)) return error_tuple(env, ENOMEM); s = accept(l, (sa.size == 0 ? NULL : (struct sockaddr *)sa.data), (socklen_t *)&salen); if (s < 0) return error_tuple(env, errno); flags = fcntl(s, F_GETFL, 0); if (flags < 0) return error_tuple(env, errno); if (fcntl(s, F_SETFL, flags|O_NONBLOCK) < 0) return error_tuple(env, errno); PROCKET_REALLOC(sa, salen); return enif_make_tuple3(env, atom_ok, enif_make_int(env, s), enif_make_binary(env, &sa)); }
/* 0: int socket descriptor, 1: int level, * 2: int optname, 3: void *optval */ static ERL_NIF_TERM nif_getsockopt(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { int s = -1; int level = 0; int optname = 0; ErlNifBinary optval = {0}; socklen_t optlen = 0; if (!enif_get_int(env, argv[0], &s)) return enif_make_badarg(env); if (!enif_get_int(env, argv[1], &level)) return enif_make_badarg(env); if (!enif_get_int(env, argv[2], &optname)) return enif_make_badarg(env); if (!enif_inspect_binary(env, argv[3], &optval)) return enif_make_badarg(env); /* Make the binary mutable */ if (!enif_realloc_binary(&optval, optval.size)) return error_tuple(env, ENOMEM); optlen = optval.size; if (getsockopt(s, level, optname, (optval.size == 0 ? NULL : optval.data), &optlen) < 0) return error_tuple(env, errno); PROCKET_REALLOC(optval, optlen); return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &optval)); }
/* 0: connected Unix socket */ static ERL_NIF_TERM nif_fdrecv(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { int fd = -1; /* connected socket */ int s = -1; /* socket received from pipe */ if (!enif_get_int(env, argv[0], &fd)) return enif_make_badarg(env); if (ancil_recv_fd(fd, &s) < 0) { int err = errno; (void)close(fd); return error_tuple(env, err); } if (close(fd) < 0) return error_tuple(env, errno); return enif_make_tuple2(env, atom_ok, enif_make_int(env, s)); }
static ERL_NIF_TERM nif_fdopen(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { int fd = 0; SRLY_STATE *sp = NULL; if (!enif_get_int(env, argv[0], &fd)) return enif_make_badarg(env); if (fd < 0) return error_tuple(env, EINVAL); sp = enif_alloc_resource(SRLY_STATE_RESOURCE, sizeof(SRLY_STATE)); if (sp == NULL) return error_tuple(env, ENOMEM); sp->fd = fd; return enif_make_tuple2(env, atom_ok, enif_make_resource(env, sp)); }
// close ERL_NIF_TERM h5sclose(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { hid_t dataspace_id; // parse arguments check(argc == 1, "Incorrent number of arguments"); check(enif_get_int(env, argv[0], &dataspace_id), "Can't get resource from argv"); // close properties list check(!H5Sclose(dataspace_id), "Failed to close dataspace."); return ATOM_OK; error: return error_tuple(env, "Can not close dataspace"); };
/* 0: file descriptor */ static ERL_NIF_TERM nif_close(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { int sockfd = -1; if (!enif_get_int(env, argv[0], &sockfd)) return enif_make_badarg(env); if (close(sockfd) < 0) return error_tuple(env, errno); return atom_ok; }
// Retrieves dataspace dimension size and maximum size. ERL_NIF_TERM h5sget_simple_extent_dims(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { hid_t dataspace_id; hsize_t *dims = NULL; hsize_t *maxdims = NULL; int status; ERL_NIF_TERM dims_list; ERL_NIF_TERM maxdims_list; ERL_NIF_TERM* dims_arr; ERL_NIF_TERM* maxdims_arr; int rank; // parse arguments check(argc == 2, "Incorrent number of arguments"); check(enif_get_int(env, argv[0], &dataspace_id), "Can't get resource from argv"); check(enif_get_int(env, argv[1], &rank), "Can't get rank from argv"); // allocate space for dims array to store a number of dimensions dims = malloc(rank * sizeof(hsize_t)); maxdims = malloc(rank * sizeof(hsize_t)); // get a number of dims from dataspace status = H5Sget_simple_extent_dims(dataspace_id, dims, maxdims); check(status > 0, "Failed to get dims."); // allocate mem for arrays of ERL_NIF_TERM so we could convert dims_arr = (ERL_NIF_TERM*)enif_alloc(sizeof(ERL_NIF_TERM) * rank); maxdims_arr = (ERL_NIF_TERM*)enif_alloc(sizeof(ERL_NIF_TERM) * rank); // convert arrays into array of ERL_NIF_TERM check(!convert_array_to_nif_array(env, rank, dims, dims_arr), "can't convert array"); check(!convert_array_to_nif_array(env, rank, maxdims, maxdims_arr), "can't convert array"); // convert arrays to list dims_list = enif_make_list_from_array(env, dims_arr, rank); maxdims_list = enif_make_list_from_array(env, maxdims_arr, rank); // cleanup free(dims); free(maxdims); return enif_make_tuple3(env, ATOM_OK, dims_list, maxdims_list); error: if(dims) free(dims); if(maxdims) free(maxdims); return error_tuple(env, "Can not get dims"); };
// Determines the dimensionality of a dataspace. ERL_NIF_TERM h5sget_simple_extent_ndims(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { hid_t dataspace_id; int ndims; // parse arguments check(argc == 1, "Incorrent number of arguments"); check(enif_get_int(env, argv[0], &dataspace_id), "Can't get resource from argv"); // get ndims ndims = H5Sget_simple_extent_ndims(dataspace_id); check(ndims > 0, "Failed to determine dataspace dimensions."); return enif_make_tuple2(env, ATOM_OK, enif_make_int(env, ndims)); error: return error_tuple(env, "Failed to determine dataspace dimensions"); };
ERL_NIF_TERM vert_virStoragePoolGetInfo(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { VERT_RESOURCE *sp = NULL; ErlNifBinary info = {0}; VERT_GET_RESOURCE(0, sp, VERT_RES_STORAGEPOOL); if (!enif_alloc_binary(sizeof(virStoragePoolInfo), &info)) return error_tuple(env, atom_enomem); VERTERR(virStoragePoolGetInfo(sp->res, (virStoragePoolInfoPtr)info.data) < 0); return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &info)); }
/* 0: socket descriptor, 1: struct sockaddr */ static ERL_NIF_TERM nif_connect(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { int s = -1; ErlNifBinary sa = {0}; if (!enif_get_int(env, argv[0], &s)) return enif_make_badarg(env); if (!enif_inspect_binary(env, argv[1], &sa)) return enif_make_badarg(env); if (connect(s, (sa.size == 0 ? NULL : (struct sockaddr *)sa.data), sa.size) < 0) return error_tuple(env, errno); return atom_ok; }
/* 0: fd, 1: buffer */ static ERL_NIF_TERM nif_write(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { int fd = -1; ErlNifBinary buf = {0}; if (!enif_get_int(env, argv[0], &fd)) return enif_make_badarg(env); if (!enif_inspect_binary(env, argv[1], &buf)) return enif_make_badarg(env); if (write(fd, buf.data, buf.size) == -1) return error_tuple(env, errno); return atom_ok; }
/* 0: file descriptor, 1: backlog */ static ERL_NIF_TERM nif_listen(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { int s = -1; int backlog = 5; if (!enif_get_int(env, argv[0], &s)) return enif_make_badarg(env); if (!enif_get_int(env, argv[1], &backlog)) return enif_make_badarg(env); if (listen(s, backlog) < 0) return error_tuple(env, errno); return atom_ok; }