PRIVATESTUFF int reply_bytes(descriptor *d, long id, char *b, int blen) { #define TMPSIZE (RESBUFSIZE+5) char tmp[TMPSIZE]; assert(blen < TMPSIZE); /* * Contents of buffer sent back: * * +------------------------------+ * | FILE_RESP_ERROR | ID | Bytes | * | 1 byte | 4 | {var} | * +------------------------------+ */ fprintf(DEBUGIO, "reply_bytes: gonna send %d total bytes\r\n", blen+1); *tmp = EXP1_RESP_BYTES; put_int32(id, tmp + 1); memcpy(tmp + 5, b, blen); driver_output2(d->port, tmp, blen + 5, NULL, 0); fprintf(DEBUGIO, "reply_bytes: done\r\n"); return 0; }
static void driver_ret32(ErlDrvPort port, unsigned int r) { char ch = XX_I32; unsigned char rbuf[4]; put_int32(r, rbuf); driver_output2(port, &ch, 1, rbuf, 4); }
static int driver_error(ErlDrvPort port, int err) { char response[256]; /* Response buffer. */ char* s; char* t; response[0] = XX_FERROR; for (s = erl_errno_id(err), t = response+1; *s; s++, t++) *t = tolower(*s); driver_output2(port, response, t-response, NULL, 0); return 0; }
PRIVATESTUFF int reply_error(descriptor *d, long id, int err) { char response[TMPSIZE]; /* Response buffer. */ char* s; char* t; /* * Contents of buffer sent back: * * +----------------------------------------------+ * | FILE_RESP_ERROR | ID | Posix error id string | * | 1 byte | 4 | {var} | * +----------------------------------------------+ */ response[0] = EXP1_RESP_ERROR; put_int32(id, response + 1); for (s = erl_errno_id(err), t = response+5; *s; s++, t++) *t = tolower(*s); driver_output2(d->port, response, t-response, NULL, 0); return 0; }
static void echo_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { EchoDrvData* data_p = (EchoDrvData *) drv_data; ErlDrvPort port = data_p->erlang_port; switch (buf[0]) { case ECHO_DRV_OUTPUT: { driver_output(port, buf+1, len-1); break; } case ECHO_DRV_OUTPUT2: { driver_output2(port, "a", 1, buf+1, len-1); break; } case ECHO_DRV_OUTPUT_BINARY: { ErlDrvBinary *bin = driver_alloc_binary(len-1); memcpy(&bin->orig_bytes, buf+1, len-1); driver_output_binary(port, "a", 1, bin, 1, len - 2); driver_free_binary(bin); break; } case ECHO_DRV_OUTPUTV: { ErlIOVec iov; ErlDrvSizeT sz; driver_enq(port, buf + 1, len - 1); sz = driver_peekqv(port, &iov); driver_outputv(port, "a", 1, &iov, 0); driver_deq(port, sz); break; } case ECHO_DRV_SET_TIMER: { driver_set_timer(port, 10); break; } case ECHO_DRV_FAILURE_EOF: { driver_failure_eof(port); break; } case ECHO_DRV_FAILURE_ATOM: { driver_failure_atom(port, buf+1); break; } case ECHO_DRV_FAILURE_POSIX: { driver_failure_posix(port, EAGAIN); break; } case ECHO_DRV_FAILURE: { driver_failure(port, buf[1]); break; } case ECHO_DRV_OUTPUT_TERM: case ECHO_DRV_DRIVER_OUTPUT_TERM: case ECHO_DRV_SEND_TERM: case ECHO_DRV_DRIVER_SEND_TERM: { ErlDrvTermData term[] = { ERL_DRV_ATOM, driver_mk_atom("echo"), ERL_DRV_PORT, driver_mk_port(port), ERL_DRV_BUF2BINARY, (ErlDrvTermData)(buf+1), (ErlDrvTermData)(len - 1), ERL_DRV_TUPLE, 3}; switch (buf[0]) { case ECHO_DRV_OUTPUT_TERM: erl_drv_output_term(driver_mk_port(port), term, sizeof(term) / sizeof(ErlDrvTermData)); break; case ECHO_DRV_DRIVER_OUTPUT_TERM: driver_output_term(port, term, sizeof(term) / sizeof(ErlDrvTermData)); break; case ECHO_DRV_SEND_TERM: driver_send_term(port, data_p->caller, term, sizeof(term) / sizeof(ErlDrvTermData)); break; case ECHO_DRV_DRIVER_SEND_TERM: erl_drv_send_term(driver_mk_port(port), data_p->caller, term, sizeof(term) / sizeof(ErlDrvTermData)); break; } break; } case ECHO_DRV_SAVE_CALLER: data_p->caller = driver_caller(port); break; default: break; } }
static void driver_eof(ErlDrvPort port) { char ch = XX_REOF; driver_output2(port, &ch, 1, NULL, 0); }
static void driver_ok(ErlDrvPort port) { char ch = XX_OK; driver_output2(port, &ch, 1, NULL, 0); }