Beispiel #1
0
void send_geometry(GEOSCommand *command, GEOSGeometry *geom) {
	//GEOSContextHandle_t context = command->driver_data->handle;
	//int type = GEOSGeomTypeId_r(context, geom);

	if(geom == NULL) {

		ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("ok"),
			   ERL_DRV_ATOM, driver_mk_atom("ggeom"),
			   ERL_DRV_ATOM, driver_mk_atom("empty"),
			   ERL_DRV_TUPLE, 2,
			   ERL_DRV_TUPLE, 2};

		driver_output_term(command->driver_data->port, spec, sizeof(spec) / sizeof(spec[0]));

		return;
	}
	ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("ok"),
			   ERL_DRV_ATOM, driver_mk_atom("ggeom"),
			 //  ERL_DRV_INT, (ErlDrvTermData) type,
			   ERL_DRV_INT, (ErlDrvTermData) geom,
			   ERL_DRV_TUPLE, 2,
			   ERL_DRV_TUPLE, 2};

  	driver_output_term(command->driver_data->port, spec, sizeof(spec) / sizeof(spec[0]));
}
Beispiel #2
0
static void process(ErlDrvData handle, ErlIOVec *ev) {
    baberl_drv_t* driver_data = (baberl_drv_t*) handle;
    ErlDrvBinary* args = ev->binv[1];
    char *data = args->orig_bytes;
    char *from_encoding, *to_encoding, *text;
    converted_text_t cv;

    from_encoding = read_string(&data);
    to_encoding = read_string(&data);
    text = read_string(&data);

    cv.error = 0;
    convert_text(from_encoding, to_encoding, text, strlen(text), &cv);

    if (cv.error == 0) {
        ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("ok"),
                                 ERL_DRV_BUF2BINARY, cv.text, cv.text_size,
                                 ERL_DRV_TUPLE, 2
                                };
        driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0]));
    }
    else {
        ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("error"),
                                 ERL_DRV_ATOM, driver_mk_atom("iconv_coding"),
                                 ERL_DRV_TUPLE, 2
                                };
        driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0]));
    }

    driver_free(from_encoding);
    driver_free(to_encoding);
    driver_free(text);
    driver_free(cv.text);
}
Beispiel #3
0
// Delete a record from the database
static void del(bdb_drv_t *bdb_drv, ErlIOVec *ev) {
  ErlDrvBinary* data = ev->binv[1];
  char *bytes = data->orig_bytes;
  char *key_bytes = bytes+1;
  
  DB *db = bdb_drv->db;
  DBT key;
  int status;
  
  bzero(&key, sizeof(DBT));
    
  key.data = key_bytes;
  key.size = KEY_SIZE;
  
  status = db->del(db, NULL, &key, 0);
  db->sync(db, 0);
  
  if(status == 0) {
  	// Delete went OK, return atom 'ok'
    ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("ok")};
    
    driver_output_term(bdb_drv->port, spec, sizeof(spec) / sizeof(spec[0]));
    
  } else {
  	// There was an error
    char *error_reason;

    switch(status) {
    case DB_NOTFOUND:
      error_reason = "not_found";
      break;
    case DB_LOCK_DEADLOCK:
      error_reason = "deadlock";
      break;
    case DB_SECONDARY_BAD:
      error_reason = "bad_secondary_index";
      break;
    case EINVAL:
      error_reason = "bad_flag";
      break;
    case EACCES:
      error_reason = "readonly";
      break;
    case DB_RUNRECOVERY:
      error_reason = "run_recovery";
      break;
    default:
      error_reason = "unknown";
    }
    
    // Return tuple {error, Reason}
    ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("error"),
			     ERL_DRV_ATOM, driver_mk_atom(error_reason),
			     ERL_DRV_TUPLE, 2};

    driver_output_term(bdb_drv->port, spec, sizeof(spec) / sizeof(spec[0]));
  }
}
Beispiel #4
0
static int reply_ok_binary(descriptor_t *desc, char *ptr, int beg_offset, int length)
{
    ErlDrvTermData      msg[24];
    int                 i = 0;
    int                 res;

    i = LOAD_PORT(msg, i, driver_mk_port(desc->port));
    i = LOAD_ATOM(msg, i, am_ok);
    i = LOAD_BINARY(msg, i, edtk_alloced_ptr2ErlDrvBinary(ptr),
                    beg_offset, length);
    i = LOAD_TUPLE(msg, i, 3);
    edtk_debug("%s: i = %d, ptr = 0x%lx, start = %d, end = %d",
    __FUNCTION__, i, ptr, beg_offset, length);
    res = driver_output_term(desc->port, msg, i);
    /* driver_output_term() incrs refc, and we're done, so decr refc */
    /*
    ** We _know_ that "ptr" points to memory allocated by
    ** edtk_driver_alloc_wrapper(), so edtk_alloced_ptr2ErlDrvBinary()
    ** is safe in this case.  If it weren't safe, then the binary
    ** must be returned by an xtra_return, which means we
    ** reply_ok_binary()) are never called!
    */
    driver_free_binary(edtk_alloced_ptr2ErlDrvBinary(ptr));
    edtk_debug("%s: res = %d", __FUNCTION__, res);
    return res;
}
Beispiel #5
0
static void DNSSD_API ResolveReply(DNSServiceRef sd_ref,
				   DNSServiceFlags flags,
				   uint32_t ifIndex,
				   DNSServiceErrorType err,
				   const char * fullname,
				   const char * hosttarget,
				   uint16_t port,
				   uint16_t txtLen,
				   const unsigned char * txtRecord,
				   void * context)
{
  dnssd_drv_t* dd = (dnssd_drv_t*) context;
  if (err != kDNSServiceErr_NoError) {
    send_error(context, err);
  } else {
    ErlDrvTermData spec[] = {ERL_DRV_PORT, dd->term_port,
			     ERL_DRV_ATOM, dd->term_resolve,
			     ERL_DRV_INT, flags,
			     ERL_DRV_INT, ifIndex,
			     ERL_DRV_BUF2BINARY, (ErlDrvTermData) fullname, strlen(fullname),
			     ERL_DRV_BUF2BINARY, (ErlDrvTermData) hosttarget, strlen(hosttarget),
			     ERL_DRV_INT, ntohs(port),
			     ERL_DRV_BUF2BINARY, (ErlDrvTermData) txtRecord, txtLen,
			     ERL_DRV_TUPLE, 6,
			     ERL_DRV_TUPLE, 3};
    driver_output_term(dd->erl_port, spec, sizeof(spec) / sizeof(spec[0]));
  }
}
Beispiel #6
0
void
testcase_printf(TestCaseState_t *tcs, char *frmt, ...)
{
    InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs;
    ErlDrvTermData msg[12];
    va_list va;
    va_start(va, frmt);
#if HAVE_VSNPRINTF
    vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va);
#else
    vsprintf(itcs->comment_buf, frmt, va);
#endif
    va_end(va);

    msg[0] = ERL_DRV_ATOM;
    msg[1] = (ErlDrvTermData) driver_mk_atom("print");

    msg[2] = ERL_DRV_PORT;
    msg[3] = driver_mk_port(itcs->port);

    msg[4] = ERL_DRV_ATOM;
    msg[5] = driver_mk_atom(itcs->visible.testcase_name);

    msg[6] = ERL_DRV_STRING;
    msg[7] = (ErlDrvTermData) itcs->comment_buf;
    msg[8] = (ErlDrvTermData) strlen(itcs->comment_buf);

    msg[9] = ERL_DRV_TUPLE;
    msg[10] = (ErlDrvTermData) 4;

    driver_output_term(itcs->port, msg, 11);
}
Beispiel #7
0
static void redis_drv_get(redis_drv_t *redis_drv, Reader *const reader)
{
  int rc;
  char *val;
  
  REDIS redis = redis_drv->redis;
  
  const uint64_t *keysize = NULL;
  const char *key = NULL;
  
  if(read_binary(reader, &key, &keysize)){
    rc = credis_get(redis, key, &val);
    if(rc > -1){
      ErlDrvTermData spec[] = {
        ERL_DRV_BINARY, 
        (ErlDrvTermData) val,
        strlen(val), 
        0
      };
      driver_output_term(redis_drv->port, spec, sizeof(spec) / sizeof(spec[0]));
    } else{
      return_error(redis_drv, REDIS_DRV_NIL);
    }
  } else{
    return_error(redis_drv, REDIS_DRV_ERROR);
  }
}
Beispiel #8
0
static int
get_pwnam (pwd_drv_t *drv, char *cmd)
{
  struct passwd *pwd = getpwnam (cmd);
  if (!pwd)
    {
      fprintf (drv->log, "getpwnam returns NULL for %s\n", cmd);
      fflush (drv->log);

      return send_error (drv, "error", "unknown_name");
    }

  size_t result_count = 0;
  ErlDrvTermData *result = make_passwd (drv, pwd, &result_count);
  if (!result)
    {
      return send_error (drv, "error", "Couldn't allocate memory");
    }

  int r = driver_output_term (drv->port,
                              result, 
                              result_count);

  driver_free (result);
  return r;
}
Beispiel #9
0
static int prepare(sqlite3_drv_t *drv, char *command, int command_size) {
  int result;
  const char *rest;
  sqlite3_stmt *statement;
  ErlDrvTermData spec[6];

#ifdef DEBUG
  fprintf(drv->log, "Preparing statement: %.*s\n", command_size, command);
  fflush(drv->log);
#endif
  result = sqlite3_prepare_v2(drv->db, command, command_size, &statement, &rest);
  if (result != SQLITE_OK) {
    return output_db_error(drv);
  } else if (statement == NULL) {
    return output_error(drv, SQLITE_MISUSE, "empty statement");
  }

  if (drv->prepared_count >= drv->prepared_alloc) {
    drv->prepared_alloc =
        (drv->prepared_alloc != 0) ? 2*drv->prepared_alloc : 4;
    drv->prepared_stmts =
        driver_realloc(drv->prepared_stmts,
                       drv->prepared_alloc * sizeof(sqlite3_stmt *));
  }
  drv->prepared_stmts[drv->prepared_count] = statement;
  drv->prepared_count++;

  spec[0] = ERL_DRV_PORT;
  spec[1] = driver_mk_port(drv->port);
  spec[2] = ERL_DRV_UINT;
  spec[3] = drv->prepared_count - 1;
  spec[4] = ERL_DRV_TUPLE;
  spec[5] = 2;
  return driver_output_term(drv->port, spec, sizeof(spec) / sizeof(spec[0]));
}
Beispiel #10
0
// Unkown Command
static void unkown(bdb_drv_t *bdb_drv, ErlIOVec *ev) {
  // Return {error, unkown_command}
  ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("error"),
			   ERL_DRV_ATOM, driver_mk_atom("uknown_command"),
			   ERL_DRV_TUPLE, 2};
  driver_output_term(bdb_drv->port, spec, sizeof(spec) / sizeof(spec[0]));
}
Beispiel #11
0
static void DNSSD_API BrowseReply(DNSServiceRef sd_ref,
				  DNSServiceFlags flags,
				  uint32_t ifIndex,
				  DNSServiceErrorType err,
				  const char * name,
				  const char * regtype,
				  const char * domain,
				  void * context
				  )
{
  dnssd_drv_t* dd = (dnssd_drv_t*) context;
  if (err != kDNSServiceErr_NoError) {
    send_error(context, err);
  } else {
    ErlDrvTermData spec[] = {ERL_DRV_PORT, dd->term_port,
			     ERL_DRV_ATOM, dd->term_browse,
			     ERL_DRV_INT, flags,
			     ERL_DRV_INT, ifIndex,
			     ERL_DRV_BUF2BINARY, (ErlDrvTermData) name, strlen(name),
			     ERL_DRV_BUF2BINARY, (ErlDrvTermData) regtype, strlen(regtype),
			     ERL_DRV_BUF2BINARY, (ErlDrvTermData) domain, strlen(domain),
			     ERL_DRV_TUPLE, 5,
			     ERL_DRV_TUPLE, 3};
    driver_output_term(dd->erl_port, spec, sizeof(spec) / sizeof(spec[0]));
  }
}
Beispiel #12
0
static void return_error(redis_drv_t *redis_drv, int errorno)
{
  ErlDrvTermData spec[] = {
      // ERL_DRV_ATOM, driver_mk_atom(error_msgs[errorno]),
      ERL_DRV_ATOM, driver_mk_atom("error")
  };
  driver_output_term(redis_drv->port, spec, sizeof(spec) / sizeof(spec[0]));
}
Beispiel #13
0
static void return_ok(redis_drv_t *redis_drv, int msgno)
{
  ErlDrvTermData spec[] = {
      // ERL_DRV_ATOM, driver_mk_atom(ok_msgs[msgno]),
      ERL_DRV_ATOM, driver_mk_atom("ok")
  };
  driver_output_term(redis_drv->port, spec, sizeof(spec) / sizeof(spec[0]));
}
Beispiel #14
0
void send_error(ErlDrvData edd, DNSServiceErrorType err) {
  dnssd_drv_t* dd = (dnssd_drv_t*) edd;
  ErlDrvTermData spec[] = {ERL_DRV_PORT, dd->term_port,
			   ERL_DRV_ATOM, dd->term_error,
			   ERL_DRV_INT, (ErlDrvTermData) errno,
			   ERL_DRV_TUPLE, 3};
  driver_output_term(dd->erl_port, spec, sizeof(spec) / sizeof(spec[0]));
}
Beispiel #15
0
void erl_send_error(GEOSCommand *command, char *atom) {
	
	ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("error"),
                           ERL_DRV_ATOM, driver_mk_atom(atom),
                           ERL_DRV_TUPLE, 2}; 
	driver_output_term(command->driver_data->port, spec, sizeof(spec) / sizeof(spec[0]));

}
Beispiel #16
0
static void return_empty_list(redis_drv_t *redis_drv)
{
  ErlDrvTermData spec[] = {
      ERL_DRV_NIL, ERL_DRV_LIST, 1
  };
  
  driver_output_term(redis_drv->port, spec, sizeof(spec) / sizeof(spec[0]));
}
Beispiel #17
0
static inline int output_done(sqlite3_drv_t *drv) {
  // Return {Port, ok}
  ErlDrvTermData spec[] = {
      ERL_DRV_PORT, driver_mk_port(drv->port),
      ERL_DRV_ATOM, drv->atom_done,
      ERL_DRV_TUPLE, 2
  };
  return driver_output_term(drv->port, spec, sizeof(spec) / sizeof(spec[0]));
}
Beispiel #18
0
void send_binary(GEOSCommand *command, unsigned char* content, long len) {

  ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("ok"),
                           ERL_DRV_BUF2BINARY, (ErlDrvTermData)content, len,
                           ERL_DRV_TUPLE, 2}; 

  driver_output_term(command->driver_data->port, spec, sizeof(spec) / sizeof(spec[0]));

}
Beispiel #19
0
void send_string(GEOSCommand *command, const char* content) {

  ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("ok"),
                           ERL_DRV_STRING, (ErlDrvTermData) content, strlen(content),
                           ERL_DRV_TUPLE, 2}; 

  driver_output_term(command->driver_data->port, spec, sizeof(spec) / sizeof(spec[0]));

}
Beispiel #20
0
void send_double(GEOSCommand *command, double content) {

  ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("ok"),
                           ERL_DRV_FLOAT, (ErlDrvTermData) &content,
                           ERL_DRV_TUPLE, 2}; 

  driver_output_term(command->driver_data->port, spec, sizeof(spec) / sizeof(spec[0]));

}
Beispiel #21
0
static int
get_pwall (pwd_drv_t *drv)
{
  size_t pwd_count = 0;
  setpwent ();
  while (getpwent ())
    pwd_count++;
  endpwent ();

  size_t term_count = passwd_term_count ();
  size_t result_count = pwd_count * term_count;
  ErlDrvTermData *result = (ErlDrvTermData *) driver_alloc (sizeof (ErlDrvTermData) * (result_count + 3));
  if (!result)
    {
      fprintf (drv->log, "Couldn't allocate memory for result\n");
      fflush (drv->log);

      return send_error (drv, "error", "Couldn't allocate memory for result");
    }

  char **names = (char **) driver_alloc (sizeof (char *) * pwd_count);
  char **pwds  = (char **) driver_alloc (sizeof (char *) * pwd_count);

  setpwent ();

  size_t result_idx = 0;
  struct passwd *pwd = getpwent ();
  while (pwd)
    {
      fill_passwd (&result[result_idx * term_count], pwd, &names[result_idx], &pwds[result_idx]);
      result_idx++;

      pwd = getpwent ();
    }

  endpwent ();

  result[result_count++] = ERL_DRV_NIL;
  result[result_count++] = ERL_DRV_LIST;
  result[result_count++] = pwd_count + 1;

  int r = driver_output_term (drv->port,
                              result,
                              result_count);

  size_t i = 0;
  for (; i < pwd_count; ++i)
    {
      driver_free (pwds[i]);
      driver_free (names[i]);
    }

  driver_free (pwds);
  driver_free (names);
  driver_free (result);
  return r;
}
Beispiel #22
0
static void av_exit(H264Decoder *d)
{
  ErlDrvTermData reply[] = {
    ERL_DRV_ATOM, driver_mk_atom("av_decoder_closed"),
    ERL_DRV_PORT, driver_mk_port(d->port),
    ERL_DRV_TUPLE, 2
  };
  driver_output_term(d->port, reply, sizeof(reply) / sizeof(reply[0]));
  driver_exit(d->port, 0);
}
Beispiel #23
0
int
send_undefined(emonk_drv_t* drv, emonk_req_t* req)
{
    ErlDrvTermData terms[] = {
        ERL_DRV_BUF2BINARY, (ErlDrvTermData) req->call_id, req->cid_len,
		ERL_DRV_ATOM, req->ok ? drv->ok : drv->error,
		ERL_DRV_ATOM, drv->undefined,
		ERL_DRV_TUPLE, 3
	};
    return driver_output_term(drv->port, terms, 9);    
}
Beispiel #24
0
int
send_response(emonk_drv_t* drv, emonk_req_t* req, void* data, int length)
{
    ErlDrvTermData terms[] = {
        ERL_DRV_BUF2BINARY, (ErlDrvTermData) req->call_id, req->cid_len,
		ERL_DRV_ATOM, req->ok ? drv->ok : drv->error,
		ERL_DRV_EXT2TERM, (ErlDrvTermData) data, length,
		ERL_DRV_TUPLE, 3
	};
    return driver_output_term(drv->port, terms, 10);
}
Beispiel #25
0
// Unknown Command
static int unknown(sqlite3_drv_t *drv, char *command, int command_size) {
  // Return {Port, error, unknown_command}
  ErlDrvTermData spec[] = {
      ERL_DRV_PORT, driver_mk_port(drv->port),
      ERL_DRV_ATOM, drv->atom_error,
      ERL_DRV_INT, (ErlDrvTermData) ((ErlDrvSInt) -1),
      ERL_DRV_ATOM, drv->atom_unknown_cmd,
      ERL_DRV_TUPLE, 4
  };
  return driver_output_term(drv->port, spec, sizeof(spec) / sizeof(spec[0]));
}
Beispiel #26
0
void send_pointer(GEOSCommand *command, char *name, void *pointer) {

  ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("ok"),
			   ERL_DRV_ATOM, driver_mk_atom(name),
                           ERL_DRV_INT, (ErlDrvTermData) pointer,
                           ERL_DRV_TUPLE, 2,
                           ERL_DRV_TUPLE, 2}; 

  driver_output_term(command->driver_data->port, spec, sizeof(spec) / sizeof(spec[0]));

}
static void return_ok(bdb_drv_t* pdrv) {

    ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("ok")};

#if ((ERL_DRV_EXTENDED_MAJOR_VERSION == 1) || ((ERL_DRV_EXTENDED_MAJOR_VERSION == 2) && (ERL_DRV_EXTENDED_MINOR_VERSION == 0)))
    driver_output_term(pdrv->port, spec, sizeof(spec) / sizeof(spec[0]));
#else
    ErlDrvTermData mkport = driver_mk_port(pdrv->port);
    erl_drv_output_term(mkport, spec, sizeof(spec) / sizeof(spec[0]));
#endif

}
Beispiel #28
0
static void av_decoder_decoded(ErlDrvData drv_data, ErlDrvThreadData thread_data)
{
  H264Decoder *decoder = (H264Decoder *)drv_data;
  H264Frame *frame = (H264Frame *)thread_data;
  
  // fprintf(stderr, "Decoding finished: %p %ld\r\n", frame->yuv, frame->yuv ? frame->yuv->orig_size : -1);
  
  if(frame->yuv) {
    //    av_log(NULL,AV_LOG_WARNING,"\nPORTyuv:: %i\n",decoder->port);
    ErlDrvTermData reply[] = {
      ERL_DRV_ATOM, driver_mk_atom("yuv"),
      ERL_DRV_PORT, driver_mk_port(decoder->port),
      ERL_DRV_BINARY, (ErlDrvTermData)frame->yuv, (ErlDrvTermData)frame->yuv->orig_size, 0,
      ERL_DRV_TUPLE, 3
    };
    driver_output_term(decoder->port, reply, sizeof(reply) / sizeof(reply[0]));
    driver_free_binary(frame->yuv);
  } else if(frame->sample){
    //    av_log(NULL,AV_LOG_WARNING,"\nPORTsample:: %i\n",decoder->port);
    ErlDrvTermData reply[] = {
      ERL_DRV_ATOM, driver_mk_atom("sample"),
      ERL_DRV_PORT, driver_mk_port(decoder->port),
      ERL_DRV_BINARY, (ErlDrvTermData)frame->sample, (ErlDrvTermData)frame->sample->orig_size, 0,
      ERL_DRV_TUPLE, 3
    };
    driver_output_term(decoder->port, reply, sizeof(reply) / sizeof(reply[0]));
    driver_free_binary(frame->sample);
  } else {
    //    av_log(decoder->dec,AV_LOG_ERROR,"NOT YUV");
    av_log(NULL,AV_LOG_WARNING,"\nPORTelse:: %i\n",decoder->port);
    ErlDrvTermData reply[] = {
      ERL_DRV_ATOM, driver_mk_atom("yuv"),
      ERL_DRV_PORT, driver_mk_port(decoder->port),
      ERL_DRV_TUPLE, 2
    };
    driver_output_term(decoder->port, reply, sizeof(reply) / sizeof(reply[0]));
  }
  driver_free(frame);
}
Beispiel #29
0
static inline int output_error(
    sqlite3_drv_t *drv, int error_code, const char *error) {
  int term_count = 2, term_allocated = 13;
  ErlDrvTermData *dataset = driver_alloc(sizeof(ErlDrvTermData) * term_allocated);
  dataset[0] = ERL_DRV_PORT;
  dataset[1] = driver_mk_port(drv->port);
  return_error(drv, error_code, error, &dataset, &term_count, &term_allocated, NULL);
  term_count += 2;
  dataset[11] = ERL_DRV_TUPLE;
  dataset[12] = 2;
  driver_output_term(drv->port, dataset, term_count);
  return 0;
}
Beispiel #30
0
void output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len)
{
    int res;
    ErlDrvPort port = (ErlDrvPort) drv_data;
    ErlDrvTermData msg[] = {
        ERL_DRV_PORT,	driver_mk_port(port),
        ERL_DRV_ATOM,	driver_mk_atom("caller"),
        ERL_DRV_PID,	driver_caller(port),
        ERL_DRV_TUPLE,	(ErlDrvTermData) 3
    };
    res = driver_output_term(port, msg, sizeof(msg)/sizeof(ErlDrvTermData));
    if (res <= 0)
        driver_failure_atom(port, "driver_output_term failed");
}