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