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