Initial commit, 3-52-19 alpha
[cls.git] / Extras / sockets / xlsock.c
blob432240168876a55fbcba2cd4fcab5972d541dce2
1 #include "xlshlib.h"
2 #include <limits.h>
3 #include "sock.h"
5 #ifndef OPEN_MAX
6 # define OPEN_MAX 64
7 #endif
9 static int sock[OPEN_MAX];
10 static int sock_inited = FALSE;
12 #define SOCK_MAX OPEN_MAX
14 static void cleanup(void)
16 int i;
17 for (i = 0; i < SOCK_MAX; i++)
18 if (sock[i] != -1) {
19 Sock_close(sock[i], NULL);
20 sock[i] = -1;
24 static LVAL enter_sock(int fd)
26 if (fd == -1)
27 return NIL;
28 else {
29 int i;
30 for (i = 0; i < SOCK_MAX; i++)
31 if (sock[i] == -1) {
32 sock[i] = fd;
33 return cvfixnum((FIXTYPE) fd);
35 Sock_close(fd, NULL);
36 return NIL;
40 static LVAL close_sock(int fd)
42 int i;
43 for (i = 0; i < SOCK_MAX; i++)
44 if (sock[i] == fd) {
45 sock[i] = -1;
46 return Sock_close(fd, NULL) == -1 ? NIL : s_true;
48 return NIL;
51 static void check_init(void)
53 if (! sock_inited) {
54 int i;
55 for (i = 0; i < SOCK_MAX; i++)
56 sock[i] = -1;
57 Sock_init();
58 sock_inited = TRUE;
59 atexit(cleanup);
63 LVAL xsockopen()
65 int port = getfixnum(xlgafixnum());
66 xllastarg();
67 check_init();
68 return enter_sock(Sock_open(port, NULL));
71 LVAL xsocklisten()
73 int sock = getfixnum(xlgafixnum());
74 xllastarg();
75 check_init();
76 return enter_sock(Sock_listen(sock, NULL, 0, NULL));
79 LVAL xsockconnect()
81 int port = getfixnum(xlgafixnum());
82 char *serv = getstring(xlgastring());
83 xllastarg();
84 check_init();
85 return enter_sock(Sock_connect(port, serv, NULL));
88 LVAL xsockclose()
90 int sock = getfixnum(xlgafixnum());
91 xllastarg();
92 return close_sock(sock);
95 LVAL xsockread()
97 ssize_t n;
98 int port = getfixnum(xlgafixnum());
99 LVAL buf = xlgastring();
100 xllastarg();
101 check_init();
102 n = Sock_read(port, getstring(buf), getslength(buf), NULL);
103 return n == -1 ? NIL : cvfixnum((FIXTYPE) n);
106 LVAL xsockwrite()
108 ssize_t n;
109 int port, start, end, len;
110 LVAL buf;
111 port = getfixnum(xlgafixnum());
112 buf = xlgastring();
113 start = getfixnum(xlgafixnum());
114 end = getfixnum(xlgafixnum());
115 xllastarg();
116 check_init();
117 len = getslength(buf);
118 if (end > len)
119 end = len;
120 if (start < 0)
121 start = 0;
122 if (end < start)
123 return NIL;
124 n = Sock_write(port, getstring(buf) + start, end - start, NULL);
125 return n == -1 ? NIL : cvfixnum((FIXTYPE) n);
128 #ifdef UNIX
129 /* Under X11 after a fork() the next call to XSync() hangs. I'll try
130 to figure this out but for now if you want to use fork you can't
131 use graphics -- just undefine DISPLAY before tarting xlisp. I'm
132 sure it isn't the fork as such but rather something like the
133 attempt of both processes to wait on the display that is the
134 problem. But I don't know exactly what it is. */
135 #ifdef XLISP_STAT
136 #include "xlgraph.h"
137 #endif /* XLISP_STAT */
138 #include <signal.h>
139 #include <sys/wait.h>
140 static void sig_child(int sig)
142 int stat;
143 while (waitpid(-1, &stat, WNOHANG) > 0);
146 static int sig_fork_inited = FALSE;
148 LVAL xsockfork()
150 pid_t pid;
151 xllastarg();
152 #ifdef XLISP_STAT
153 if (StHasWindows())
154 xlfail("can't fork under X11 (at least for now)");
155 #endif /* XLISP_STAT */
156 if (! sig_fork_inited) {
157 struct sigaction sa;
158 sa.sa_handler = sig_child;
159 sa.sa_flags = 0;
160 sigaction(SIGCHLD, &sa, NULL);
161 sig_fork_inited = TRUE;
163 pid = fork();
164 return pid == -1 ? NIL : cvfixnum((FIXTYPE) pid);
166 #endif /* UNIX */
168 static FUNDEF myfuns[] = {
169 { "SOCKETS::SOCK-OPEN", SUBR, xsockopen },
170 { "SOCKETS::SOCK-LISTEN", SUBR, xsocklisten },
171 { "SOCKETS::SOCK-CONNECT", SUBR, xsockconnect },
172 { "SOCKETS::SOCK-CLOSE", SUBR, xsockclose },
173 { "SOCKETS::BASE-SOCK-READ", SUBR, xsockread },
174 { "SOCKETS::BASE-SOCK-WRITE", SUBR, xsockwrite },
175 #ifdef UNIX
176 { "SOCKETS::FORK", SUBR, xsockfork },
177 #endif
178 { NULL, 0, NULL }
181 static xlshlib_modinfo_t myinfo = {
182 XLSHLIB_VERSION_INFO(0,1,0,1),
183 myfuns,
184 NULL,
185 NULL,
186 NULL
189 xlshlib_modinfo_t *xlsock__init() { return &myinfo; }