1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 1998-2016. All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * %CopyrightEnd%
19  */
20 #ifndef EI_H
21 #define EI_H
22 
23 #define EI_HAVE_TIMEOUT 1	/* Flag to user code that we have them */
24 #define USE_EI_UNDOCUMENTED     /* Want declarations for undocumented */
25 
26 /************************************************************************/
27 /*          This file defines the complete interface to ei              */
28 /************************************************************************/
29 
30 /* -------------------------------------------------------------------- */
31 /*                   Include types needed below                         */
32 /* -------------------------------------------------------------------- */
33 
34 #if defined(__WIN32__)
35 #include <winsock2.h>
36 #include <windows.h>
37 #include <winbase.h>
38 typedef LONG_PTR ssize_t; /* Sigh... */
39 #else
40 #include <sys/types.h>          /* ssize_t */
41 #endif
42 
43 #include <stdio.h>		/* Need type FILE */
44 #include <errno.h>		/* Need EHOSTUNREACH, ENOMEM, ... */
45 
46 #if !(defined(__WIN32__) || defined(_WIN32)) && !defined(VXWORKS) || (defined(VXWORKS) && defined(HAVE_SENS))
47 # include <netdb.h>
48 #endif
49 
50 
51 /* -------------------------------------------------------------------- */
52 /*                      Defines part of API                             */
53 /* -------------------------------------------------------------------- */
54 
55 /*
56  * Some error codes might be missing, so here's a backstop definitions
57  * of the ones we use with `erl_errno':
58  */
59 
60 #ifndef EMSGSIZE		/* Message too long */
61 #define EMSGSIZE        EIO
62 #endif
63 
64 #ifndef ETIMEDOUT		/* Connection timed out */
65 #define ETIMEDOUT       EIO
66 #endif
67 
68 #ifndef EHOSTUNREACH		/* No route to host */
69 #define EHOSTUNREACH    EIO
70 #endif
71 
72 /* FIXME just a few are documented, does it mean they can't be returned? */
73 
74 #define ERL_ERROR -1           /* Error of some kind */
75 #define ERL_NO_DAEMON -2       /* No contact with EPMD */
76 #define ERL_NO_PORT -3         /* No port received from EPMD */
77 #define ERL_CONNECT_FAIL -4    /* Connect to Erlang Node failed */
78 #define ERL_TIMEOUT -5         /* A timeout has expired */
79 #define ERL_NO_REMOTE -6       /* Cannot execute rsh */
80 
81 #define ERL_TICK 0
82 #define ERL_MSG 1
83 
84 #define ERL_NO_TIMEOUT -1
85 
86 /* these are the control message types */
87 #define ERL_LINK           1
88 #define ERL_SEND           2
89 #define ERL_EXIT           3
90 #define ERL_UNLINK         4
91 #define ERL_NODE_LINK      5
92 #define ERL_REG_SEND       6
93 #define ERL_GROUP_LEADER   7
94 #define ERL_EXIT2          8
95 #define ERL_PASS_THROUGH  'p'
96 
97 /* new ones for tracing, from Kenneth */
98 #define ERL_SEND_TT        12
99 #define ERL_EXIT_TT        13
100 #define ERL_REG_SEND_TT    16
101 #define ERL_EXIT2_TT       18
102 #define ERL_MONITOR_P      19
103 #define ERL_DEMONITOR_P    20
104 #define ERL_MONITOR_P_EXIT 21
105 
106 
107 /* -------------------------------------------------------------------- */
108 /*           Defines used for ei_get_type_internal() output             */
109 /* -------------------------------------------------------------------- */
110 /*
111  * these are the term type indicators used in
112  * the external (distribution) format
113  */
114 
115 /* FIXME we don't want to export these..... */
116 
117 #define ERL_SMALL_INTEGER_EXT 'a'
118 #define ERL_INTEGER_EXT       'b'
119 #define ERL_FLOAT_EXT         'c'
120 #define NEW_FLOAT_EXT         'F'
121 #define ERL_ATOM_EXT          'd'
122 #define ERL_SMALL_ATOM_EXT    's'
123 #define ERL_ATOM_UTF8_EXT     'v'
124 #define ERL_SMALL_ATOM_UTF8_EXT 'w'
125 #define ERL_REFERENCE_EXT     'e'
126 #define ERL_NEW_REFERENCE_EXT 'r'
127 #define ERL_NEWER_REFERENCE_EXT 'Z'
128 #define ERL_PORT_EXT          'f'
129 #define ERL_NEW_PORT_EXT      'Y'
130 #define ERL_PID_EXT           'g'
131 #define ERL_NEW_PID_EXT       'X'
132 #define ERL_SMALL_TUPLE_EXT   'h'
133 #define ERL_LARGE_TUPLE_EXT   'i'
134 #define ERL_NIL_EXT           'j'
135 #define ERL_STRING_EXT        'k'
136 #define ERL_LIST_EXT          'l'
137 #define ERL_BINARY_EXT        'm'
138 #define ERL_SMALL_BIG_EXT     'n'
139 #define ERL_LARGE_BIG_EXT     'o'
140 #define ERL_NEW_FUN_EXT	      'p'
141 #define ERL_MAP_EXT           't'
142 #define ERL_FUN_EXT	      'u'
143 
144 #define ERL_NEW_CACHE         'N' /* c nodes don't know these two */
145 #define ERL_CACHED_ATOM       'C'
146 
147 
148 /* -------------------------------------------------------------------- */
149 /*                     Define the erl_errno macro                       */
150 /* -------------------------------------------------------------------- */
151 
152 #ifdef __cplusplus
153 extern "C" {
154 #endif
155 
156 /*
157  * GCC's attributes are too useful to not use. Other compilers
158  * just lose opportunities to optimize and warn.
159  */
160 #if !defined(__GNUC__) || __GNUC__ < 2
161 # define __attribute__(foo) /* nothing */
162 #endif
163 
164 /*
165  * Define the 'erl_errno' facility. Unfortunately this lives on in
166  * the 'ei' interface as well.... :-(
167  */
168 
169 #if defined(_REENTRANT) || defined(VXWORKS) || defined(__WIN32__)
170 
171 /* 'erl_errno' as a function return value */
172 volatile int* __erl_errno_place(void) __attribute__ ((__const__));
173 
174 #define erl_errno (*__erl_errno_place ())
175 
176 #else /* !_REENTRANT && !VXWORKS && !__WIN32__ */
177 
178 extern volatile int __erl_errno;
179 
180 #define erl_errno __erl_errno
181 
182 #endif /* !_REENTRANT && !VXWORKS && !__WIN32__ */
183 
184 
185 /* -------------------------------------------------------------------- */
186 /*                      Type definitions                                */
187 /* -------------------------------------------------------------------- */
188 
189 /*
190  * To avoid confusion about the MAXHOSTNAMELEN when compiling the
191  * library and when using the library we set a value that we use
192  */
193 
194 #define EI_MAX_COOKIE_SIZE 512
195 #define MAXATOMLEN (255 + 1)
196 #define MAXATOMLEN_UTF8 (255*4 + 1)
197 #define EI_MAXHOSTNAMELEN (MAXATOMLEN - 2)
198 #define EI_MAXALIVELEN (MAXATOMLEN - 2)
199 #define MAXNODELEN MAXATOMLEN
200 
201 typedef enum {
202     ERLANG_ASCII = 1,
203     ERLANG_LATIN1 = 2,
204     ERLANG_UTF8 = 4
205 }erlang_char_encoding;
206 
207 /* a pid */
208 typedef struct {
209   char node[MAXATOMLEN_UTF8];
210   unsigned int num;
211   unsigned int serial;
212   unsigned int creation;
213 } erlang_pid;
214 
215 /* a port */
216 typedef struct {
217   char node[MAXATOMLEN_UTF8];
218   unsigned int id;
219   unsigned int creation;
220 } erlang_port;
221 
222 /* a ref */
223 typedef struct {
224   char node[MAXATOMLEN_UTF8];
225   int len;
226   unsigned int n[3];
227   unsigned int creation;
228 } erlang_ref;
229 
230 /* a trace token */
231 typedef struct {
232   long serial;
233   long prev;
234   erlang_pid from;
235   long label;
236   long flags;
237 } erlang_trace;
238 
239 /* a message */
240 typedef struct {
241   long msgtype;
242   erlang_pid from;
243   erlang_pid to;
244   char toname[MAXATOMLEN_UTF8];
245   char cookie[MAXATOMLEN_UTF8];
246   erlang_trace token;
247 } erlang_msg;
248 
249 /* a fun */
250 typedef struct {
251     long arity;
252     char module[MAXATOMLEN_UTF8];
253     erlang_char_encoding module_org_enc;
254     char md5[16];
255     long index;
256     long old_index;
257     long uniq;
258     long n_free_vars;
259     erlang_pid pid;
260     long free_var_len;
261     char* free_vars;
262 } erlang_fun;
263 
264 /* a big */
265 typedef struct {
266     unsigned int arity;
267     int is_neg;
268     void *digits;
269 } erlang_big;
270 
271 typedef struct {
272     char ei_type;
273     int arity;
274     int size;
275     union {
276 	long i_val;
277 	double d_val;
278 	char atom_name[MAXATOMLEN_UTF8];
279 	erlang_pid pid;
280 	erlang_port port;
281 	erlang_ref ref;
282     } value;
283 } ei_term;
284 
285 /* XXX */
286 
287 typedef struct {
288   char ipadr[4];             /* stored in network byte order */
289   char nodename[MAXNODELEN+1];
290 } ErlConnect;
291 
292 #define EI_SCLBK_INF_TMO (~((unsigned) 0))
293 
294 #define EI_SCLBK_FLG_FULL_IMPL (1 << 0)
295 
296 typedef struct {
297     int flags;
298 
299     int (*socket)(void **ctx, void *setup_ctx);
300     int	(*close)(void *ctx);
301     int (*listen)(void *ctx, void *addr, int *len, int backlog);
302     int (*accept)(void **ctx, void *addr, int *len, unsigned tmo);
303     int (*connect)(void *ctx, void *addr, int len, unsigned tmo);
304     int (*writev)(void *ctx, const void *iov, int iovcnt, ssize_t *len, unsigned tmo);
305     int (*write)(void *ctx, const char *buf, ssize_t *len, unsigned tmo);
306     int (*read)(void *ctx, char *buf, ssize_t *len, unsigned tmo);
307 
308     int (*handshake_packet_header_size)(void *ctx, int *sz);
309     int (*connect_handshake_complete)(void *ctx);
310     int (*accept_handshake_complete)(void *ctx);
311     int (*get_fd)(void *ctx, int *fd);
312 
313     /* end of version 1 */
314 
315 } ei_socket_callbacks;
316 
317 typedef struct ei_cnode_s {
318     char thishostname[EI_MAXHOSTNAMELEN+1];
319     char thisnodename[MAXNODELEN+1];
320     char thisalivename[EI_MAXALIVELEN+1];
321 /* Currently this_ipaddr isn't used */
322 /*    struct in_addr this_ipaddr; */
323     char ei_connect_cookie[EI_MAX_COOKIE_SIZE+1];
324     short creation;
325     erlang_pid self;
326     ei_socket_callbacks *cbs;
327     void *setup_context;
328 } ei_cnode;
329 
330 typedef struct in_addr *Erl_IpAddr;
331 
332 
333 /* A dynamic version of ei XX */
334 
335 typedef struct ei_x_buff_TAG {
336     char* buff;
337     int buffsz;
338     int index;
339 } ei_x_buff;
340 
341 /* -------------------------------------------------------------------- */
342 /*    Function definitions (listed in same order as documentation)      */
343 /* -------------------------------------------------------------------- */
344 
345 /* Handle the connection */
346 
347 int ei_connect_init(ei_cnode* ec, const char* this_node_name,
348 		    const char *cookie, short creation);
349 int ei_connect_xinit (ei_cnode* ec, const char *thishostname,
350 		      const char *thisalivename, const char *thisnodename,
351 		      Erl_IpAddr thisipaddr, const char *cookie,
352 		      const short creation);
353 
354 int ei_connect_init_ussi(ei_cnode* ec, const char* this_node_name,
355                          const char *cookie, short creation,
356                          ei_socket_callbacks *cbs, int cbs_sz,
357                          void *setup_context);
358 int ei_connect_xinit_ussi(ei_cnode* ec, const char *thishostname,
359                           const char *thisalivename, const char *thisnodename,
360                           Erl_IpAddr thisipaddr, const char *cookie,
361                           const short creation, ei_socket_callbacks *cbs,
362                           int cbs_sz, void *setup_context);
363 
364 int ei_connect(ei_cnode* ec, char *nodename);
365 int ei_connect_tmo(ei_cnode* ec, char *nodename, unsigned ms);
366 int ei_xconnect(ei_cnode* ec, Erl_IpAddr adr, char *alivename);
367 int ei_xconnect_tmo(ei_cnode* ec, Erl_IpAddr adr, char *alivename, unsigned ms);
368 
369 int ei_receive(int fd, unsigned char *bufp, int bufsize);
370 int ei_receive_tmo(int fd, unsigned char *bufp, int bufsize, unsigned ms);
371 int ei_receive_msg(int fd, erlang_msg* msg, ei_x_buff* x);
372 int ei_receive_msg_tmo(int fd, erlang_msg* msg, ei_x_buff* x, unsigned ms);
373 int ei_xreceive_msg(int fd, erlang_msg* msg, ei_x_buff* x);
374 int ei_xreceive_msg_tmo(int fd, erlang_msg* msg, ei_x_buff* x, unsigned ms);
375 
376 int ei_send(int fd, erlang_pid* to, char* buf, int len);
377 int ei_send_tmo(int fd, erlang_pid* to, char* buf, int len, unsigned ms);
378 int ei_reg_send(ei_cnode* ec, int fd, char *server_name, char* buf, int len);
379 int ei_reg_send_tmo(ei_cnode* ec, int fd, char *server_name, char* buf, int len, unsigned ms);
380 
381 int ei_rpc(ei_cnode* ec, int fd, char *mod, char *fun,
382 	   const char* inbuf, int inbuflen, ei_x_buff* x);
383 int ei_rpc_to(ei_cnode* ec, int fd, char *mod, char *fun,
384 	      const char* buf, int len);
385 int ei_rpc_from(ei_cnode* ec, int fd, int timeout, erlang_msg* msg,
386 		ei_x_buff* x);
387 
388 int ei_publish(ei_cnode* ec, int port);
389 int ei_publish_tmo(ei_cnode* ec, int port, unsigned ms);
390 int ei_listen(ei_cnode *ec, int *port, int backlog);
391 int ei_xlisten(ei_cnode *ec, Erl_IpAddr adr, int *port, int backlog);
392 int ei_accept(ei_cnode* ec, int lfd, ErlConnect *conp);
393 int ei_accept_tmo(ei_cnode* ec, int lfd, ErlConnect *conp, unsigned ms);
394 int ei_unpublish(ei_cnode* ec);
395 int ei_unpublish_tmo(const char *alive, unsigned ms);
396 
397 int ei_close_connection(int fd);
398 
399 const char *ei_thisnodename(const ei_cnode* ec);
400 const char *ei_thishostname(const ei_cnode* ec);
401 const char *ei_thisalivename(const ei_cnode* ec);
402 
403 erlang_pid *ei_self(ei_cnode* ec);
404 
405 /*
406  * settings
407  */
408 
409 void ei_set_compat_rel(unsigned rel);
410 void ei_set_tracelevel(int);
411 int ei_get_tracelevel(void);
412 
413 /*
414  * We have erl_gethost*() so we include ei versions as well.
415  */
416 
417 #if defined(VXWORKS)
418 
419 extern int h_errno;
420 
421 /*
422  * We need these definitions - if the user has SENS then he gets them
423  * from netdb.h, otherwise we define them ourselves.
424  *
425  * If you are getting "multiple definition" errors here,
426  * make sure you have included <netdb.h> BEFORE "erl_interface.h"
427  * or define HAVE_SENS in your CFLAGS.
428  */
429 
430 #if !defined(HAVE_SENS) && !defined(HOST_NOT_FOUND) /* just in case */
431 
432 struct	hostent {
433   char	*h_name;	/* official name of host */
434   char	**h_aliases;	/* alias list */
435   int	h_addrtype;	/* host address type */
436   int	h_length;	/* length of address */
437   char	**h_addr_list;	/* list of addresses from name server */
438 #define	h_addr	h_addr_list[0]	/* address, for backward compatiblity */
439   unsigned int unused;  /* SENS defines this as ttl */
440 };
441 
442 #define	HOST_NOT_FOUND	1 /* Authoritative Answer Host not found */
443 #define	TRY_AGAIN	2 /* Non-Authoritive Host not found, or SERVERFAIL */
444 #define	NO_RECOVERY	3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
445 #define	NO_DATA		4 /* Valid name, no data record of requested type */
446 #define	NO_ADDRESS	NO_DATA		/* no address, look for MX record */
447 
448 #endif /* !HAVE_SENS && !HOST_NOT_FOUND */
449 #endif /* VXWORKS */
450 
451 
452 struct hostent *ei_gethostbyname(const char *name);
453 struct hostent *ei_gethostbyaddr(const char *addr, int len, int type);
454 struct hostent *ei_gethostbyname_r(const char *name,
455 				   struct hostent *hostp,
456 				   char *buffer,
457 				   int buflen,
458 				   int *h_errnop);
459 struct hostent *ei_gethostbyaddr_r(const char *addr,
460 				   int length,
461 				   int type,
462 				   struct hostent *hostp,
463 				   char *buffer,
464 				   int buflen,
465 				   int *h_errnop);
466 
467 
468 /* Encode/decode functions */
469 
470 int ei_encode_version(char *buf, int *index);
471 int ei_x_encode_version(ei_x_buff* x);
472 int ei_encode_long(char *buf, int *index, long p);
473 int ei_x_encode_long(ei_x_buff* x, long n);
474 int ei_encode_ulong(char *buf, int *index, unsigned long p);
475 int ei_x_encode_ulong(ei_x_buff* x, unsigned long n);
476 int ei_encode_double(char *buf, int *index, double p);
477 int ei_x_encode_double(ei_x_buff* x, double dbl);
478 int ei_encode_boolean(char *buf, int *index, int p);
479 int ei_x_encode_boolean(ei_x_buff* x, int p);
480 int ei_encode_char(char *buf, int *index, char p);
481 int ei_x_encode_char(ei_x_buff* x, char p);
482 int ei_encode_string(char *buf, int *index, const char *p);
483 int ei_encode_string_len(char *buf, int *index, const char *p, int len);
484 int ei_x_encode_string(ei_x_buff* x, const char* s);
485 int ei_x_encode_string_len(ei_x_buff* x, const char* s, int len);
486 int ei_encode_atom(char *buf, int *index, const char *p);
487 int ei_encode_atom_as(char *buf, int *index, const char *p,
488 		    erlang_char_encoding from, erlang_char_encoding to);
489 int ei_encode_atom_len(char *buf, int *index, const char *p, int len);
490 int ei_encode_atom_len_as(char *buf, int *index, const char *p, int len,
491 			erlang_char_encoding from, erlang_char_encoding to);
492 int ei_x_encode_atom(ei_x_buff* x, const char* s);
493 int ei_x_encode_atom_as(ei_x_buff* x, const char* s,
494 		      erlang_char_encoding from, erlang_char_encoding to);
495 int ei_x_encode_atom_len(ei_x_buff* x, const char* s, int len);
496 int ei_x_encode_atom_len_as(ei_x_buff* x, const char* s, int len,
497 			  erlang_char_encoding from, erlang_char_encoding to);
498 int ei_encode_binary(char *buf, int *index, const void *p, long len);
499 int ei_x_encode_binary(ei_x_buff* x, const void* s, int len);
500 int ei_encode_pid(char *buf, int *index, const erlang_pid *p);
501 int ei_x_encode_pid(ei_x_buff* x, const erlang_pid* pid);
502 int ei_encode_fun(char* buf, int* index, const erlang_fun* p);
503 int ei_x_encode_fun(ei_x_buff* x, const erlang_fun* fun);
504 int ei_encode_port(char *buf, int *index, const erlang_port *p);
505 int ei_x_encode_port(ei_x_buff* x, const erlang_port *p);
506 int ei_encode_ref(char *buf, int *index, const erlang_ref *p);
507 int ei_x_encode_ref(ei_x_buff* x, const erlang_ref *p);
508 int ei_encode_term(char *buf, int *index, void *t); /* ETERM* actually */
509 int ei_x_encode_term(ei_x_buff* x, void* t);
510 int ei_encode_trace(char *buf, int *index, const erlang_trace *p);
511 int ei_x_encode_trace(ei_x_buff* x, const erlang_trace *p);
512 int ei_encode_tuple_header(char *buf, int *index, int arity);
513 int ei_x_encode_tuple_header(ei_x_buff* x, long n);
514 int ei_encode_list_header(char *buf, int *index, int arity);
515 int ei_x_encode_list_header(ei_x_buff* x, long n);
516 #define ei_encode_empty_list(buf,i) ei_encode_list_header(buf,i,0)
517 int ei_x_encode_empty_list(ei_x_buff* x);
518 int ei_encode_map_header(char *buf, int *index, int arity);
519 int ei_x_encode_map_header(ei_x_buff* x, long n);
520 
521 /*
522  * ei_get_type() returns the type and "size" of the item at
523  * buf[index]. For strings and atoms, size is the number of characters
524  * not including the terminating 0. For binaries, size is the number
525  * of bytes. For lists and tuples, size is the arity of the
526  * object. For other types, size is 0. In all cases, index is left
527  * unchanged.
528  */
529 
530 int ei_get_type(const char *buf, const int *index, int *type, int *size);
531 int ei_get_type_internal(const char *buf, const int *index, int *type,
532 			 int *size);
533 
534 /* Step through buffer, decoding the given type into the buffer
535  * provided. On success, 0 is returned and index is updated to point
536  * to the start of the next item in the buffer. If the type of item at
537  * buf[index] is not the requested type, -1 is returned and index is
538  * not updated. The buffer provided by the caller must be sufficiently
539  * large to contain the decoded object.
540  */
541 int ei_decode_version(const char *buf, int *index, int *version);
542 int ei_decode_long(const char *buf, int *index, long *p);
543 int ei_decode_ulong(const char *buf, int *index, unsigned long *p);
544 int ei_decode_double(const char *buf, int *index, double *p);
545 int ei_decode_boolean(const char *buf, int *index, int *p);
546 int ei_decode_char(const char *buf, int *index, char *p);
547 int ei_decode_string(const char *buf, int *index, char *p);
548 int ei_decode_atom(const char *buf, int *index, char *p);
549 int ei_decode_atom_as(const char *buf, int *index, char *p, int destlen, erlang_char_encoding want, erlang_char_encoding* was, erlang_char_encoding* result);
550 int ei_decode_binary(const char *buf, int *index, void *p, long *len);
551 int ei_decode_fun(const char* buf, int* index, erlang_fun* p);
552 void free_fun(erlang_fun* f);
553 int ei_decode_pid(const char *buf, int *index, erlang_pid *p);
554 int ei_decode_port(const char *buf, int *index, erlang_port *p);
555 int ei_decode_ref(const char *buf, int *index, erlang_ref *p);
556 int ei_decode_term(const char *buf, int *index, void *t); /* ETERM** actually */
557 int ei_decode_trace(const char *buf, int *index, erlang_trace *p);
558 int ei_decode_tuple_header(const char *buf, int *index, int *arity);
559 int ei_decode_list_header(const char *buf, int *index, int *arity);
560 int ei_decode_map_header(const char *buf, int *index, int *arity);
561 
562 /*
563  * ei_decode_ei_term() returns 1 if term is decoded, 0 if term is OK,
564  * but not decoded here and -1 if something is wrong.  ONLY changes
565  * index if term is decoded (return value 1)!
566  */
567 
568 int ei_decode_ei_term(const char* buf, int* index, ei_term* term);
569 
570 
571 /*
572  * ei_print_term to print out a binary coded term
573  */
574 
575 int ei_print_term(FILE *fp, const char* buf, int* index);
576 int ei_s_print_term(char** s, const char* buf, int* index);
577 
578 /*
579  * format to build binary format terms a bit like printf
580  */
581 
582 int ei_x_format(ei_x_buff* x, const char* fmt, ...);
583 int ei_x_format_wo_ver(ei_x_buff* x, const char *fmt, ...);
584 
585 int ei_x_new(ei_x_buff* x);
586 int ei_x_new_with_version(ei_x_buff* x);
587 int ei_x_free(ei_x_buff* x);
588 int ei_x_append(ei_x_buff* x, const ei_x_buff* x2);
589 int ei_x_append_buf(ei_x_buff* x, const char* buf, int len);
590 int ei_skip_term(const char* buf, int* index);
591 
592 /***************************************************************************
593  *
594  *  Hash types needed by registry types
595  *
596  ***************************************************************************/
597 
598 #define EI_SMALLKEY 32
599 
600 typedef struct bucket_s {
601   int rawhash;
602   const char *key;
603   char keybuf[EI_SMALLKEY];
604   const void *value;
605   struct bucket_s *next;
606 } ei_bucket;
607 
608 /* users of the package declare variables as pointers to this. */
609 typedef struct {
610   ei_bucket **tab;
611   int (*hash)(const char *); /* hash function for this table */
612   int size; /* size of table */
613   int nelem; /* nr elements */
614   int npos;  /* nr occupied positions */
615   ei_bucket *freelist; /* reuseable freed buckets */
616 } ei_hash;
617 
618 
619 /***************************************************************************
620  *
621  *  Registry defines, types, functions
622  *
623  ***************************************************************************/
624 
625 /* -------------------------------------------------------------------- */
626 /*                               XXXXXXXXXXX                            */
627 /* -------------------------------------------------------------------- */
628 
629 /* registry object attributes */
630 #define EI_DIRTY 0x01 /* dirty bit (object value differs from backup) */
631 #define EI_DELET 0x02 /* object is deleted */
632 #define EI_INT 0x10 /* object is an integer */
633 #define EI_FLT 0x20 /* object is a float */
634 #define EI_STR 0x40 /* object is a string */
635 #define EI_BIN 0x80 /* object is a binary, i.e. pointer to arbitrary type */
636 
637 
638 /* -------------------------------------------------------------------- */
639 /*                               XXXXXXXXXXX                            */
640 /* -------------------------------------------------------------------- */
641 
642 typedef struct ei_reg_inode {
643   int attr;
644   int size;
645   union {
646     long i;
647     double f;
648     char *s;
649     void *p;
650   } val;
651   struct ei_reg_inode *next;
652 } ei_reg_obj;
653 
654 typedef struct {
655   ei_reg_obj *freelist;
656   ei_hash *tab;
657 } ei_reg;
658 
659 struct ei_reg_stat {
660   int attr;             /* object attributes (see above) */
661   int size;             /* size in bytes (for STR and BIN) 0 for others */
662 };
663 
664 struct ei_reg_tabstat {
665   int size;   /* size of table */
666   int nelem; /* number of stored elements */
667   int npos;   /* number of occupied positions */
668   int collisions; /* number of positions with more than one element */
669 };
670 
671 
672 int ei_init(void);
673 
674 /* -------------------------------------------------------------------- */
675 /*                               XXXXXXXXXXX                            */
676 /* -------------------------------------------------------------------- */
677 
678 /* FIXME move comments to source */
679 
680 /* open / close registry. On open, a descriptor is returned that must
681  * be specified in all subsequent calls to registry functions. You can
682  * open as many registries as you like.
683  */
684 ei_reg *ei_reg_open(int size);
685 int ei_reg_resize(ei_reg *oldreg, int newsize);
686 int ei_reg_close(ei_reg *reg);
687 
688 /* set values... these routines assign values to keys. If the key
689  * exists, the previous value is discarded and the new one replaces
690  * it.
691  *
692  * BIN objects require an additional argument indicating the size in
693  * bytes of the stored object. This will be used when the object is
694  * backed up, since it will need to be copied at that time. Remember
695  * also that pointers are process-space specific and it is not
696  * meaningful to back them up for later recall. If you are storing
697  * binary objects for backup, make sure that they are self-contained
698  * (without references to other objects).
699  *
700  * On success the function returns 0, otherwise a value
701  * indicating the reason for failure will be returned.
702  */
703 int ei_reg_setival(ei_reg *reg, const char *key, long i);
704 int ei_reg_setfval(ei_reg *reg, const char *key, double f);
705 int ei_reg_setsval(ei_reg *reg, const char *key, const char *s);
706 int ei_reg_setpval(ei_reg *reg, const char *key, const void *p, int size);
707 
708 /* general set function (specifiy type via flags)
709  * optional arguments are as for equivalent type-specific function,
710  * i.e.:
711  * ei_reg_setval(fd, path, EI_INT, int i);
712  * ei_reg_setval(fd, path, EI_FLT, float f);
713  * ei_reg_setval(fd, path, EI_STR, const char *s);
714  * ei_reg_setval(fd, path, EI_BIN, const void *p, int size);
715  */
716 int ei_reg_setval(ei_reg *reg, const char *key, int flags, ...);
717 
718 /* get value of specific type object */
719 /* warning: it may be difficult to detect errors when using these
720  * functions, since the error values are returned "in band"
721  */
722 long ei_reg_getival(ei_reg *reg, const char *key);
723 double ei_reg_getfval(ei_reg *reg, const char *key);
724 const char *ei_reg_getsval(ei_reg *reg, const char *key);
725 const void *ei_reg_getpval(ei_reg *reg, const char *key, int *size);
726 
727 /* get value of any type object (must specify)
728  * Retrieve a value from an object. The type of value expected and a
729  * pointer to a large enough buffer must be provided. flags must be
730  * set to the appropriate type (see type constants above) and the
731  * object type must match. If (flags == 0) the pointer is *assumed* to
732  * be of the correct type for the object. In any case, the actual
733  * object type is always returned on success.
734  *
735  * The argument following flags must be one of int*, double*, const
736  * char** and const void**.
737  *
738  * for BIN objects an int* is needed to return the size of the object, i.e.
739  * int ei_reg_getval(ei_reg *reg, const char *path, int flags, void **p, int *size);
740  */
741 int ei_reg_getval(ei_reg *reg, const char *key, int flags, ...);
742 
743 /* mark the object as dirty. Normally this operation will not be
744  * necessary, as it is done automatically by all of the above 'set'
745  * functions. However, if you modify the contents of an object pointed
746  * to by a STR or BIN object, then the registry will not be aware of
747  * the change. As a result, the object may be missed on a subsequent
748  * backup operation. Use this function to set the dirty bit on the
749  * object.
750  */
751 int ei_reg_markdirty(ei_reg *reg, const char *key);
752 
753 /* remove objects. The value, if any, is discarded. For STR and BIN
754  * objects, the object itself is removed using free(). */
755 int ei_reg_delete(ei_reg *reg, const char *key);
756 
757 /* get information about an object */
758 int ei_reg_stat(ei_reg *reg, const char *key, struct ei_reg_stat *obuf);
759 
760 /* get information about table */
761 int ei_reg_tabstat(ei_reg *reg, struct ei_reg_tabstat *obuf);
762 
763 /* dump to / restore from backup */
764 /* fd is open descriptor to Erlang, mntab is Mnesia table name */
765 /* flags here: */
766 #define EI_FORCE 0x1 /* dump all records (not just dirty ones) */
767 #define EI_NOPURGE 0x2 /* don't purge deleted records */
768 int ei_reg_dump(int fd, ei_reg *reg, const char *mntab, int flags);
769 int ei_reg_restore(int fd, ei_reg *reg, const char *mntab);
770 int ei_reg_purge(ei_reg *reg);
771 
772 
773 /* -------------------------------------------------------------------- */
774 /*            Encoding/decoding bugnums to GNU MP format                */
775 /* -------------------------------------------------------------------- */
776 
777 /* If the user included <gmp.h> we supply some more functions */
778 
779 #if defined(__GNU_MP_VERSION) \
780 	&& __GNU_MP_VERSION == 4 && __GNU_MP_VERSION_MINOR >= 1
781 
782 int ei_decode_bignum(const char *buf, int *index, mpz_t obj);
783 int ei_encode_bignum(char *buf, int *index, mpz_t obj);
784 int ei_x_encode_bignum(ei_x_buff *x, mpz_t obj);
785 
786 #endif /* __GNU_MP_VERSION */
787 
788 /* -------------------------------------------------------------------- */
789 /*            Function definitions not documented FIXME                 */
790 /* -------------------------------------------------------------------- */
791 
792 /* FIXME replace this primitive type size code */
793 
794 #ifdef __WIN32__
795 #define EI_LONGLONG __int64
796 #define EI_ULONGLONG unsigned __int64
797 #else
798 #define EI_LONGLONG long long
799 #define EI_ULONGLONG unsigned long long
800 #endif
801 
802 #ifndef VXWORKS
803 int ei_decode_longlong(const char *buf, int *index, EI_LONGLONG *p);
804 int ei_decode_ulonglong(const char *buf, int *index, EI_ULONGLONG *p);
805 int ei_encode_longlong(char *buf, int *index, EI_LONGLONG p);
806 int ei_encode_ulonglong(char *buf, int *index, EI_ULONGLONG p);
807 int ei_x_encode_longlong(ei_x_buff* x, EI_LONGLONG n);
808 int ei_x_encode_ulonglong(ei_x_buff* x, EI_ULONGLONG n);
809 #endif
810 
811 #ifdef USE_EI_UNDOCUMENTED
812 
813 /*
814  * Decode a list of integers into an integer array (i.e. even if it is
815  * encoded as a string). count gets number of items in array.
816  * See "decode_intlist.c".
817  */
818 
819 int ei_decode_intlist(const char *buf, int *index, long *a, int *count);
820 
821 /*
822  * FIXME: used in IC, document?
823  * bufp = address of pointer to dynamically allocated buffer - may be reallocated by
824  * this function if it is too small for the message
825  * bufsz = in/out value: in=user buffer size, out=new buffer size
826  * msglen = nr bytes in received message
827  */
828 int ei_receive_encoded(int fd, char **bufp, int *bufsz, erlang_msg *to,
829 		       int *msglen);
830 int ei_receive_encoded_tmo(int fd, char **bufp, int *bufsz, erlang_msg *to,
831 			   int *msglen, unsigned ms);
832 int ei_send_encoded(int fd, const erlang_pid *to, char *msg, int msglen);
833 int ei_send_encoded_tmo(int fd, const erlang_pid *to, char *msg, int msglen,
834 			unsigned ms);
835 int ei_send_reg_encoded(int fd, const erlang_pid *from, const char *to,
836 			char *msg, int msglen);
837 int ei_send_reg_encoded_tmo(int fd, const erlang_pid *from, const char *to,
838 			    char *msg, int msglen, unsigned ms);
839 
840 /*
841  * Bacward compatibility with old undocumented but used interface...
842  * FIXME use wrapper function instead?!
843  */
844 #define ei_send_encoded_timeout(Fd,To,Msg,MsgLen,Ms) \
845     ei_send_encoded_tmo((Fd),(To),(Msg),(MsgLen),(Ms))
846 #define ei_send_reg_encoded_timeout(Fd,From,To,Msg,MsgLen,Ms) \
847     ei_send_reg_encoded_tmo((Fd),(From),(To),(Msg),(MsgLen),(Ms))
848 
849 
850 /* FIXME: is this really the best way to handle bignums? */
851 int ei_encode_big(char *buf, int *index, erlang_big* big);
852 int ei_x_encode_big(ei_x_buff* x, erlang_big* big);
853 int ei_decode_big(const char *buf, int *index, erlang_big* p);
854 int ei_big_comp(erlang_big *x, erlang_big *y);
855 int ei_big_to_double(erlang_big *b, double *resp);
856 int ei_small_to_big(int s, erlang_big *b);
857 erlang_big *ei_alloc_big(unsigned int arity);
858 void ei_free_big(erlang_big *b);
859 
860 #endif /* USE_EI_UNDOCUMENTED */
861 
862 #ifdef __cplusplus
863 }
864 #endif
865 
866 #endif /* EI_H */
867