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