1 /* Copyright (c) 2001 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(SLFile_FD_Type * f,int cmd)28 static int do_fcntl_2 (SLFile_FD_Type *f, int cmd)
29 {
30    int ret;
31    int fd;
32 
33    if (-1 == SLfile_get_fd (f, &fd))
34      return -1;
35 
36    while ((-1 == (ret = fcntl (fd, cmd)))
37 	  && (0 == check_and_set_errno (errno)))
38      ;
39 
40    return ret;
41 }
42 
do_fcntl_3_int(SLFile_FD_Type * f,int cmd,int flags)43 static int do_fcntl_3_int (SLFile_FD_Type *f, int cmd, int flags)
44 {
45    int ret;
46    int fd;
47 
48 
49    if (-1 == SLfile_get_fd (f, &fd))
50      return -1;
51 
52    while ((-1 == (ret = fcntl (fd, cmd, flags)))
53 	  && (0 == check_and_set_errno (errno)))
54      ;
55 
56    return ret;
57 }
58 
fcntl_getfd(SLFile_FD_Type * f)59 static int fcntl_getfd (SLFile_FD_Type *f)
60 {
61    return do_fcntl_2 (f, F_GETFD);
62 }
63 
fcntl_setfd(SLFile_FD_Type * f,int * flags)64 static int fcntl_setfd (SLFile_FD_Type *f, int *flags)
65 {
66    return do_fcntl_3_int (f, F_SETFD, *flags);
67 }
68 
fcntl_getfl(SLFile_FD_Type * f)69 static int fcntl_getfl (SLFile_FD_Type *f)
70 {
71    return do_fcntl_2 (f, F_GETFL);
72 }
73 
fcntl_setfl(SLFile_FD_Type * f,int * flags)74 static int fcntl_setfl (SLFile_FD_Type *f, int *flags)
75 {
76    return do_fcntl_3_int (f, F_SETFL, *flags);
77 }
78 
79 #define F SLANG_FILE_FD_TYPE
80 #define I SLANG_INT_TYPE
81 static SLang_Intrin_Fun_Type Fcntl_Intrinsics [] =
82 {
83    MAKE_INTRINSIC_1("fcntl_getfd", fcntl_getfd, I, F),
84    MAKE_INTRINSIC_2("fcntl_setfd", fcntl_setfd, I, F, I),
85    MAKE_INTRINSIC_1("fcntl_getfl", fcntl_getfl, I, F),
86    MAKE_INTRINSIC_2("fcntl_setfl", fcntl_setfl, I, F, I),
87 
88    SLANG_END_INTRIN_FUN_TABLE
89 };
90 #undef I
91 #undef F
92 
93 static SLang_IConstant_Type Fcntl_Consts [] =
94 {
95    MAKE_ICONSTANT("FD_CLOEXEC", FD_CLOEXEC),
96    SLANG_END_ICONST_TABLE
97 };
98 
init_fcntl_module_ns(char * ns_name)99 int init_fcntl_module_ns (char *ns_name)
100 {
101    SLang_NameSpace_Type *ns;
102 
103    ns = SLns_create_namespace (ns_name);
104    if (ns == NULL)
105      return -1;
106 
107    if ((-1 == SLns_add_intrin_fun_table (ns, Fcntl_Intrinsics, "__FCNTL__"))
108        || (-1 == SLns_add_iconstant_table (ns, Fcntl_Consts, NULL)))
109      return -1;
110 
111    return 0;
112 }
113 
114 /* This function is optional */
deinit_fcntl_module(void)115 void deinit_fcntl_module (void)
116 {
117 }
118