2 * Created: klacke@erix.ericsson.se
11 #include <sys/types.h>
12 #include <sys/socket.h>
16 #include "erl_driver.h"
18 #include "erl_driver_compat.h"
23 /* forward declarations */
24 static ErlDrvData
start(ErlDrvPort port
, char *buf
);
25 static void stop(ErlDrvData drv_data
);
26 static void from_erlang(ErlDrvData drv_data
, char* buf
, int len
);
28 /* driver global variables */
29 static int instance
= -1;
31 static ErlDrvEntry fdsend_drv_entry
;
45 static int find_free_slave()
48 for(i
=0; i
<MAXSLAVES
; i
++) {
49 if (slaves
[i
].fd
== -1)
55 static int find_slave(int fd
)
58 for(i
=0; i
<MAXSLAVES
; i
++) {
59 if (slaves
[i
].fd
== fd
)
65 DRIVER_INIT(fdsend_drv
)
67 fdsend_drv_entry
.init
= NULL
;
68 fdsend_drv_entry
.start
= start
;
69 fdsend_drv_entry
.stop
= stop
;
70 fdsend_drv_entry
.output
= from_erlang
;
71 fdsend_drv_entry
.ready_input
= NULL
;
72 fdsend_drv_entry
.ready_output
= NULL
;
73 fdsend_drv_entry
.driver_name
= "fdsend_drv";
74 fdsend_drv_entry
.finish
= NULL
;
75 fdsend_drv_entry
.outputv
= NULL
;
76 return &fdsend_drv_entry
;
81 * Called when erlang side does "open_port()".
83 static ErlDrvData
start(ErlDrvPort port
, char *buf
)
86 if (instance
!= -1) /* only allow one copy at the time */
87 return (ErlDrvData
) -1;
88 for (i
=0; i
< MAXSLAVES
; i
++) {
90 slaves
[i
].path
= NULL
;
92 return (ErlDrvData
)port
;
96 static void from_erlang(ErlDrvData drv_data
, char* buf
, int n
)
98 ErlDrvPort port
= (ErlDrvPort
) drv_data
;
101 int slavefd
, fd
, afd
;
104 case 'L': /* Bind and listen to new af_unix socket to path */
105 fd
= fd_listen_path(port
, buf
);
107 if ((i
= find_free_slave()) == -1) {
113 if ((tp
= (char*) driver_alloc(n
)) != NULL
) {
114 slaves
[i
].type
= LISTEN
;
116 strcpy(slaves
[i
].path
, buf
);
125 case 'A': /* accept the af_unix path socket */
128 if ((i
= find_slave(fd
)) == -1) {
132 if ((j
= find_free_slave()) == -1) {
137 if ((afd
= fd_accept_path(port
, fd
, tp
)) > 0) {
140 slaves
[j
].type
= ACCEPT
;
142 reply_int(port
, afd
);
149 case 'S': /* send a socket to slave */
151 slavefd
= get_int32(buf
+4);
153 if (send_fd(&fd
, slavefd
) == -1)
159 case 'C': /* close */
161 if ((i
= find_slave(fd
)) == -1) {
165 if (slaves
[i
].path
&& slaves
[i
].type
== LISTEN
)
166 driver_free(slaves
[i
].path
);
167 slaves
[i
].path
= NULL
;
179 * Called when the Erlang port is closed.
181 static void stop(ErlDrvData drv_data
)
184 for (i
=0; i
< MAXSLAVES
; i
++) {
185 if (slaves
[i
].fd
> 0) {
186 if (slaves
[i
].type
== LISTEN
)
187 driver_free(slaves
[i
].path
);
188 slaves
[i
].path
= NULL
;