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 AB. Portions
14 * created by Ericsson are Copyright 2008, Ericsson Utvecklings AB. All
15 * Rights Reserved.''
16 *
17 * $Id$
18 */
19
20 #ifndef UNIX
21 #if !defined(__WIN32__)
22 #define UNIX 1
23 #endif
24 #endif
25
26 #ifdef UNIX
27 #include <errno.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #ifdef HAVE_POLL_H
35 # include <poll.h>
36 #endif
37 #endif /* UNIX */
38
39 #include "erl_driver.h"
40
41 typedef struct {
42 int ofd;
43 int ifd;
44 } mcd_data_t;
45
46 static ErlDrvData start(ErlDrvPort port, char *command);
47 static void stop(ErlDrvData data);
48
49 static ErlDrvEntry missing_callback_drv_entry = {
50 NULL /* init */,
51 start,
52 stop,
53 NULL /* output */,
54 NULL /* ready_input */,
55 NULL /* ready_output */,
56 "missing_callback_drv",
57 NULL /* finish */,
58 NULL /* handle */,
59 NULL /* control */,
60 NULL /* timeout */,
61 NULL /* outputv */,
62 NULL /* ready_async */,
63 NULL /* flush */,
64 NULL /* call */,
65 NULL /* event */,
66 ERL_DRV_EXTENDED_MARKER,
67 ERL_DRV_EXTENDED_MAJOR_VERSION,
68 ERL_DRV_EXTENDED_MINOR_VERSION,
69 ERL_DRV_FLAG_USE_PORT_LOCKING,
70 NULL, /* handle2 */
71 NULL /* process_exit */
72 };
73
DRIVER_INIT(missing_callback_drv)74 DRIVER_INIT(missing_callback_drv)
75 {
76 return &missing_callback_drv_entry;
77 }
78
79 static ErlDrvData
start(ErlDrvPort port,char * command)80 start(ErlDrvPort port, char *command)
81 {
82 mcd_data_t *mcd = driver_alloc(sizeof(mcd_data_t));
83
84 if (!mcd)
85 goto error;
86
87 mcd->ofd = -1;
88 mcd->ifd = -1;
89
90 #ifdef UNIX
91
92 mcd->ofd = open("/dev/null", O_WRONLY);
93 if (mcd->ofd < 0)
94 goto error;
95 if (driver_select(port, (ErlDrvEvent) (long) mcd->ofd, DO_WRITE, 1) != 0)
96 goto error;
97
98 mcd->ifd = open("/dev/zero", O_RDONLY);
99 if (mcd->ifd < 0)
100 goto error;
101 if (driver_select(port, (ErlDrvEvent) (long) mcd->ifd, DO_READ, 1) != 0)
102 goto error;
103 #endif
104
105 driver_set_timer(port, 0);
106
107 return (ErlDrvData) mcd;
108
109 error:
110 stop((ErlDrvData) mcd);
111 return ERL_DRV_ERROR_GENERAL;
112 }
113
114 static void
stop(ErlDrvData data)115 stop(ErlDrvData data)
116 {
117 mcd_data_t *mcd = (mcd_data_t *) data;
118 if (mcd) {
119 #ifdef UNIX
120 if (mcd->ofd >= 0)
121 close(mcd->ofd);
122 if (mcd->ifd >= 0)
123 close(mcd->ifd);
124 #endif
125 driver_free(mcd);
126 }
127 }
128