1 /* Copyright (c) 2001-2017,2018 John E. Davis
2  * This file is part of the S-Lang library.
3  *
4  * You may distribute under the terms of either the GNU General Public
5  * License or the Perl Artistic License.
6  */
7 
8 #include <stdio.h>
9 #include <slang.h>
10 
11 #include <unistd.h>
12 #include <string.h>
13 #include <fcntl.h>
14 #include <errno.h>
15 
16 SLANG_MODULE(fcntl);
17 
check_and_set_errno(int e)18 static int check_and_set_errno (int e)
19 {
20 #ifdef EINTR
21    if (e == EINTR)
22      return 0;
23 #endif
24    (void) SLerrno_set_errno (e);
25    return -1;
26 }
27 
do_fcntl_2(int fd,int cmd)28 static int do_fcntl_2 (int fd, int cmd)
29 {
30    int ret;
31 
32    while ((-1 == (ret = fcntl (fd, cmd)))
33 	  && (0 == check_and_set_errno (errno)))
34      ;
35 
36    return ret;
37 }
38 
do_fcntl_3_int(int fd,int cmd,int flags)39 static int do_fcntl_3_int (int fd, int cmd, int flags)
40 {
41    int ret;
42 
43    while ((-1 == (ret = fcntl (fd, cmd, flags)))
44 	  && (0 == check_and_set_errno (errno)))
45      ;
46 
47    return ret;
48 }
49 
pop_fd(int * fdp)50 static int pop_fd (int *fdp)
51 {
52    SLFile_FD_Type *f;
53    int status;
54 
55    if (SLang_peek_at_stack () == SLANG_INT_TYPE)
56      return SLang_pop_int (fdp);
57 
58    if (-1 == SLfile_pop_fd (&f))
59      return -1;
60 
61    status = SLfile_get_fd (f, fdp);
62    SLfile_free_fd (f);
63    return status;
64 }
65 
fcntl_getfd(void)66 static int fcntl_getfd (void)
67 {
68    int fd;
69 
70    if (-1 == pop_fd (&fd))
71      return -1;
72 
73    return do_fcntl_2 (fd, F_GETFD);
74 }
75 
fcntl_setfd(int * flags)76 static int fcntl_setfd (int *flags)
77 {
78    int fd;
79 
80    if (-1 == pop_fd (&fd))
81      return -1;
82    return do_fcntl_3_int (fd, F_SETFD, *flags);
83 }
84 
fcntl_getfl(void)85 static int fcntl_getfl (void)
86 {
87    int fd;
88 
89    if (-1 == pop_fd (&fd))
90      return -1;
91 
92    return do_fcntl_2 (fd, F_GETFL);
93 }
94 
fcntl_setfl(int * flags)95 static int fcntl_setfl (int *flags)
96 {
97    int fd;
98 
99    if (-1 == pop_fd (&fd))
100      return -1;
101 
102    return do_fcntl_3_int (fd, F_SETFL, *flags);
103 }
104 
105 #define F SLANG_FILE_FD_TYPE
106 #define I SLANG_INT_TYPE
107 static SLang_Intrin_Fun_Type Fcntl_Intrinsics [] =
108 {
109    MAKE_INTRINSIC_0("fcntl_getfd", fcntl_getfd, I),
110    MAKE_INTRINSIC_1("fcntl_setfd", fcntl_setfd, I, I),
111    MAKE_INTRINSIC_0("fcntl_getfl", fcntl_getfl, I),
112    MAKE_INTRINSIC_1("fcntl_setfl", fcntl_setfl, I, I),
113 
114    SLANG_END_INTRIN_FUN_TABLE
115 };
116 #undef I
117 #undef F
118 
119 static SLang_IConstant_Type Fcntl_Consts [] =
120 {
121    MAKE_ICONSTANT("FD_CLOEXEC", FD_CLOEXEC),
122 #ifndef O_ACCMODE
123 # define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
124 #endif
125    MAKE_ICONSTANT("O_ACCMODE", O_ACCMODE),
126    SLANG_END_ICONST_TABLE
127 };
128 
init_fcntl_module_ns(char * ns_name)129 int init_fcntl_module_ns (char *ns_name)
130 {
131    SLang_NameSpace_Type *ns;
132 
133    ns = SLns_create_namespace (ns_name);
134    if (ns == NULL)
135      return -1;
136 
137    if ((-1 == SLns_add_intrin_fun_table (ns, Fcntl_Intrinsics, "__FCNTL__"))
138        || (-1 == SLns_add_iconstant_table (ns, Fcntl_Consts, NULL)))
139      return -1;
140 
141    return 0;
142 }
143 
144 /* This function is optional */
deinit_fcntl_module(void)145 void deinit_fcntl_module (void)
146 {
147 }
148