1 /* ``Licensed under the Apache License, Version 2.0 (the "License");
2 * you may not use this file except in compliance with the License.
3 * You may obtain a copy of the License at
4 *
5 * http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software
8 * distributed under the License is distributed on an "AS IS" BASIS,
9 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 * See the License for the specific language governing permissions and
11 * limitations under the License.
12 *
13 * The Initial Developer of the Original Code is Ericsson Utvecklings AB.
14 * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
15 * AB. All Rights Reserved.''
16 *
17 * $Id$
18 */
19
20 #ifndef UNIX
21 #if !defined(__WIN32__)
22 #define UNIX 1
23 #endif
24 #endif
25
26 #include <stdio.h>
27 #include <string.h>
28 #ifdef UNIX
29 #include <unistd.h>
30 #endif
31 #include "erl_driver.h"
32
33 typedef struct {
34 ErlDrvPort port;
35 int fds[2];
36 } IOReadyExitDrvData;
37
38 static ErlDrvData io_ready_exit_drv_start(ErlDrvPort, char *);
39 static void io_ready_exit_drv_stop(ErlDrvData);
40 static void io_ready_exit_ready_input(ErlDrvData, ErlDrvEvent);
41 static void io_ready_exit_ready_output(ErlDrvData, ErlDrvEvent);
42 static void io_ready_exit_drv_output(ErlDrvData, char *, int);
43 static void io_ready_exit_drv_finish(void);
44 static ErlDrvSSizeT io_ready_exit_drv_control(ErlDrvData, unsigned int,
45 char *, ErlDrvSizeT,
46 char **, ErlDrvSizeT);
47
48 static ErlDrvEntry io_ready_exit_drv_entry = {
49 NULL, /* init */
50 io_ready_exit_drv_start,
51 io_ready_exit_drv_stop,
52 NULL /* output */,
53 io_ready_exit_ready_input,
54 io_ready_exit_ready_output,
55 "io_ready_exit_drv",
56 NULL /* finish */,
57 NULL, /* handle */
58 io_ready_exit_drv_control,
59 NULL, /* timeout */
60 NULL, /* outputv */
61 NULL, /* ready_async */
62 NULL, /* flush */
63 NULL, /* call */
64 NULL, /* event */
65 ERL_DRV_EXTENDED_MARKER,
66 ERL_DRV_EXTENDED_MAJOR_VERSION,
67 ERL_DRV_EXTENDED_MINOR_VERSION,
68 0, /* ERL_DRV_FLAGs */
69 NULL, /* handle2 */
70 NULL, /* process_exit */
71 NULL /* stop_select */
72 };
73
74 /* -------------------------------------------------------------------------
75 ** Entry functions
76 **/
77
DRIVER_INIT(io_ready_exit_drv)78 DRIVER_INIT(io_ready_exit_drv)
79 {
80 return &io_ready_exit_drv_entry;
81 }
82
83 static ErlDrvData
io_ready_exit_drv_start(ErlDrvPort port,char * command)84 io_ready_exit_drv_start(ErlDrvPort port, char *command) {
85 IOReadyExitDrvData *oeddp = driver_alloc(sizeof(IOReadyExitDrvData));
86 oeddp->port = port;
87 oeddp->fds[0] = -1;
88 oeddp->fds[1] = -1;
89 return (ErlDrvData) oeddp;
90 }
91
92 static void
io_ready_exit_drv_stop(ErlDrvData drv_data)93 io_ready_exit_drv_stop(ErlDrvData drv_data) {
94 IOReadyExitDrvData *oeddp = (IOReadyExitDrvData *) drv_data;
95 #ifdef UNIX
96 if (oeddp->fds[0] >= 0) {
97 driver_select(oeddp->port,
98 (ErlDrvEvent) (ErlDrvSInt) oeddp->fds[0],
99 DO_READ|DO_WRITE,
100 0);
101 close(oeddp->fds[0]);
102 }
103 if (oeddp->fds[1] >= 0)
104 close(oeddp->fds[1]);
105 #endif
106 driver_free((void *) oeddp);
107 }
108
109
110 static void
io_ready_exit_ready_output(ErlDrvData drv_data,ErlDrvEvent event)111 io_ready_exit_ready_output(ErlDrvData drv_data, ErlDrvEvent event)
112 {
113 IOReadyExitDrvData *oeddp = (IOReadyExitDrvData *) drv_data;
114 driver_failure_atom(oeddp->port, "ready_output_driver_failure");
115 }
116
117 static void
io_ready_exit_ready_input(ErlDrvData drv_data,ErlDrvEvent event)118 io_ready_exit_ready_input(ErlDrvData drv_data, ErlDrvEvent event)
119 {
120 IOReadyExitDrvData *oeddp = (IOReadyExitDrvData *) drv_data;
121 driver_failure_atom(oeddp->port, "ready_input_driver_failure");
122 }
123
124 static ErlDrvSSizeT
io_ready_exit_drv_control(ErlDrvData drv_data,unsigned int command,char * buf,ErlDrvSizeT len,char ** rbuf,ErlDrvSizeT rlen)125 io_ready_exit_drv_control(ErlDrvData drv_data,
126 unsigned int command,
127 char *buf, ErlDrvSizeT len,
128 char **rbuf, ErlDrvSizeT rlen)
129 {
130 char *abuf;
131 char *res_str;
132 ErlDrvSSizeT res_len;
133 IOReadyExitDrvData *oeddp = (IOReadyExitDrvData *) drv_data;
134 #ifndef UNIX
135 res_str = "nyiftos";
136 #else
137 if (pipe(oeddp->fds) < 0) {
138 res_str = "pipe failed";
139 }
140 else {
141 res_str = "ok";
142 (void) write(oeddp->fds[1], "!", 1);
143 driver_select(oeddp->port,
144 (ErlDrvEvent) (ErlDrvSInt) oeddp->fds[0],
145 DO_READ|DO_WRITE,
146 1);
147 }
148 #endif
149 res_len = strlen(res_str);
150 if (res_len > rlen) {
151 abuf = driver_alloc(sizeof(char)*res_len);
152 if (!abuf)
153 return 0;
154 *rbuf = abuf;
155 }
156
157 memcpy((void *) *rbuf, (void *) res_str, res_len);
158
159 return res_len;
160 }
161
162
163
164