1 /*
2 * wmslib/src/but/net.c, part of wmslib (Library functions)
3 * Copyright (C) 1995-1997 William Shubert.
4 * See "configure.h.in" for more copyright information.
5 */
6
7 #include <configure.h>
8
9 #if X11_DISP
10
11 #ifdef STDC_HEADERS
12 #include <stdlib.h>
13 #include <unistd.h>
14 #endif /* STDC_HEADERS */
15 #include <ctype.h>
16 #include <stdio.h>
17 #include <X11/Xlib.h>
18 #include <X11/Xutil.h>
19 #include <X11/cursorfont.h>
20 #include <X11/Xatom.h>
21 #include <X11/keysym.h>
22 #include <sys/time.h>
23 #ifdef HAVE_SYS_SELECT_H
24 #include <sys/select.h>
25 #endif
26 #include <sys/types.h>
27
28 #if HAVE_SOCKETS
29
30 #include <sys/socket.h>
31 #if HAVE_NETINET_IN_H
32 #include <netinet/in.h>
33 #endif
34 #if HAVE_SYS_IN_H
35 #include <sys/in.h>
36 #endif
37 #if HAVE_SYS_INET_H
38 #include <sys/inet.h>
39 #endif
40 #include <netdb.h>
41 #if HAVE_ARPA_NAMESER_H
42
43 #include <arpa/nameser.h>
44 #endif
45 #if HAVE_RESOLV_H
46 #include <resolv.h>
47 #endif
48 #if HAVE_SYS_UTSNAME_H
49 #include <sys/utsname.h>
50 #endif
51 #include <pwd.h>
52
53 #endif /* HAVE_SOCKETS */
54
55 #include <fcntl.h>
56 #include <wms.h>
57 #include <but/but.h>
58 #include <but/net.h>
59
60 #if HAVE_SOCKETS
61
62 /**********************************************************************
63 * Forward Declarations
64 **********************************************************************/
65
66 static ButOut newConn(void *packet, int fd);
67 static ButRnet *newRnet(ButEnv *env);
68 static ButOut getNetData(void *packet, int fd);
69 static ButOut finishWrite(void *packet, int fd);
70 static void putProtoWho(ButRnet *net);
71 static void butRnet_close(ButRnet *net, const char *reason, bool forced);
72 static bool butRnet_write(ButRnet *net, ButNetMsg *msg);
73 static void butRnet_sendMMove(ButRnet *net, int winId, int lx, int ly,
74 int lw, int lh, ButCur type);
75 static void newFlags(ButRnet *net, int id, uint newFlags);
76 static ButOut butSpec(ButEnv *env, int butId, void *buf, int bufLen);
77
78
79 /**********************************************************************
80 * Functions
81 **********************************************************************/
82
butLnet_create(ButEnv * env,int port,void * packet,ButOut ocallback (ButRnet * net),ButOut callback (ButRnet * net,void * cmd,int cmdLen),ButOut ccallback (ButRnet * net,const char * reason))83 ButLnet *butLnet_create(ButEnv *env, int port, void *packet,
84 ButOut ocallback(ButRnet *net),
85 ButOut callback(ButRnet *net, void *cmd, int cmdLen),
86 ButOut ccallback(ButRnet *net, const char *reason)) {
87 ButLnet *net = wms_malloc(sizeof(ButLnet));
88 struct sockaddr_in sa;
89
90 MAGIC_SET(net);
91 net->env = env;
92 net->packet = packet;
93 net->valid = net->error = FALSE;
94 net->fd = socket(AF_INET, SOCK_STREAM, 0);
95 net->ocallback = ocallback;
96 net->callback = callback;
97 net->ccallback = ccallback;
98 if (net->fd == -1) {
99 net->error = TRUE;
100 net->errNum = errno;
101 return(net);
102 }
103 sa.sin_family = AF_INET;
104 sa.sin_addr.s_addr = INADDR_ANY;
105 sa.sin_port = htons(port);
106 if (bind(net->fd, (struct sockaddr *)&sa, sizeof(sa)) != 0) {
107 net->error = TRUE;
108 net->errNum = errno;
109 close(net->fd);
110 return(net);
111 }
112 if (listen(net->fd, 2) != 0) {
113 net->error = TRUE;
114 net->errNum = errno;
115 close(net->fd);
116 return(net);
117 }
118 butEnv_addFile(env, BUT_READFILE, net->fd, net, newConn);
119 net->valid = TRUE;
120 return(net);
121 }
122
123
butRnet_create(ButEnv * env,const char * address,int port,void * packet,ButOut ocallback (ButRnet * net),ButOut callback (ButRnet * net,void * cmd,int cmdLen),ButOut ccallback (ButRnet * net,const char * reason))124 ButRnet *butRnet_create(ButEnv *env, const char *address, int port,
125 void *packet, ButOut ocallback(ButRnet *net),
126 ButOut callback(ButRnet *net, void *cmd, int cmdLen),
127 ButOut ccallback(ButRnet *net, const char *reason)) {
128 ButRnet *net;
129 struct sockaddr_in sa;
130 struct hostent *hp;
131
132 net = newRnet(env);
133 net->packet = packet;
134 net->state = butRnetState_closed;
135 net->error = net->lookupError = net->butNetError = FALSE;
136 net->ocallback = ocallback;
137 net->callback = callback;
138 net->ccallback = ccallback;
139 if ((net->fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
140 net->error = TRUE;
141 net->errNum = errno;
142 return(net);
143 }
144 sa.sin_family = AF_INET;
145 if ((hp = gethostbyname(address)) == NULL) {
146 net->lookupError = TRUE;
147 #if HAVE_H_ERRNO
148 net->errNum = h_errno;
149 #else
150 net->errNum = HOST_NOT_FOUND;
151 #endif
152 return(net);
153 }
154 memcpy(&sa.sin_addr, hp->h_addr, hp->h_length);
155 sa.sin_port = htons(port);
156 if (connect(net->fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
157 net->error = TRUE;
158 net->errNum = errno;
159 return(net);
160 }
161 net->state = butRnetState_pwWait;
162 fcntl(net->fd, F_SETFL, O_NONBLOCK);
163 putProtoWho(net);
164 butEnv_addFile(net->env, BUT_READFILE, net->fd, net, getNetData);
165 return(net);
166 }
167
168
butRnet_accept(ButRnet * net)169 void butRnet_accept(ButRnet *net) {
170 assert(net->state == butRnetState_accWait);
171 net->state = butRnetState_open;
172 net->lType = net->env->curlast;
173 net->env->curlast = butCur_bogus; /* Force the cursor type to be sent. */
174 putProtoWho(net);
175 }
176
177
butLnet_destroy(ButLnet * net)178 void butLnet_destroy(ButLnet *net) {
179 assert(MAGIC(net));
180 if (net->valid) {
181 close(net->fd);
182 butEnv_rmFile(net->env, BUT_READFILE, net->fd);
183 }
184 MAGIC_UNSET(net);
185 wms_free(net);
186 }
187
188
butRnet_destroy(ButRnet * net,const char * reason)189 void butRnet_destroy(ButRnet *net, const char *reason) {
190 ButNetMsg msgOut;
191
192 assert(MAGIC(net));
193 if (net->state < butRnetState_closing) {
194 msgOut.type = int_stdInt32(BUTNET_CLOSE);
195 msgOut.length = int_stdInt32(2*4+strlen(reason)+1);
196 strcpy(msgOut.perType.close, reason);
197 butRnet_write(net, &msgOut);
198 butRnet_close(net, NULL, FALSE);
199 }
200 }
201
202
newConn(void * packet,int fd)203 static ButOut newConn(void *packet, int fd) {
204 ButLnet *lnet = packet;
205 ButRnet *rnet;
206 struct sockaddr_in addr;
207 int addrlen = sizeof(addr);
208
209 assert(MAGIC(lnet));
210 rnet = newRnet(lnet->env);
211 rnet->fd = accept(lnet->fd, (struct sockaddr *)&addr, &addrlen);
212 if (rnet->fd < 0) {
213 rnet->env->partners[rnet->partner] = NULL;
214 MAGIC_UNSET(rnet);
215 wms_free(rnet);
216 return(0);
217 }
218 rnet->packet = lnet->packet;
219 rnet->ocallback = lnet->ocallback;
220 rnet->callback = lnet->callback;
221 rnet->ccallback = lnet->ccallback;
222 fcntl(rnet->fd, F_SETFL, O_NONBLOCK);
223 rnet->state = butRnetState_pwAccWait;
224 butEnv_addFile(rnet->env, BUT_READFILE, rnet->fd, rnet, getNetData);
225 return(0);
226 }
227
228
newRnet(ButEnv * env)229 static ButRnet *newRnet(ButEnv *env) {
230 ButRnet *net = wms_malloc(sizeof(ButRnet));
231 int newNumPartners, i, partner;
232 ButRnet **newPartners;
233
234 MAGIC_SET(net);
235 for (partner = 0; partner < env->numPartners; ++partner) {
236 if (!env->partners[partner])
237 break;
238 }
239 if (partner == env->numPartners) {
240 newNumPartners = (env->numPartners + 1) * 2;
241 newPartners = wms_malloc(newNumPartners * sizeof(ButRnet *));
242 for (i = 0; i < env->numPartners; ++i) {
243 newPartners[i] = env->partners[i];
244 }
245 for (; i < newNumPartners; ++i)
246 newPartners[i] = NULL;
247 if (env->partners)
248 wms_free(env->partners);
249 env->numPartners = newNumPartners;
250 env->partners = newPartners;
251 }
252 env->partners[partner] = net;
253 net->partner = partner;
254 net->env = env;
255 net->error = FALSE;
256 net->wBufSize = net->wBufStart = net->wBufLen = 0;
257 net->wBuffer = NULL;
258 net->rBufAmt = 0;
259 net->rBufLen = BUTNET_MAXCMD * 2 + 2;
260 net->fd = -1;
261 net->ackNeeded = net->mouseMove = FALSE;
262 net->who = "Unknown";
263 net->protocol = "Unknown";
264 if ((env->last_mwin) && (env->last_mx >= 0)) {
265 assert(MAGIC(env->last_mwin));
266 net->lWinId = env->last_mwin->id;
267 net->lx = env->last_mx;
268 net->ly = env->last_my;
269 net->lw = env->last_mwin->w;
270 net->lh = env->last_mwin->h;
271 net->lType = env->curnum;
272 } else
273 net->lWinId = -2;
274 net->lPress = net->lTwitch = -1;
275 butRcur_create(&net->rc, net->env);
276 return(net);
277 }
278
279
280 /* Returns TRUE if success. */
butRnet_write(ButRnet * net,ButNetMsg * msg)281 static bool butRnet_write(ButRnet *net, ButNetMsg *msg) {
282 int len = stdInt32_int(msg->length) + 8;
283 int amtWritten;
284 char *remainder = (char *)msg;
285
286 assert(MAGIC(net));
287 if (net->wBufLen == 0) {
288 /* Nothing queued up. Try to write directly! */
289 amtWritten = write(net->fd, msg, len);
290 if (amtWritten == len)
291 return(TRUE);
292 if (amtWritten < 0) {
293 butRnet_close(net, strerror(errno), TRUE);
294 return(FALSE);
295 }
296 remainder += amtWritten;
297 len -= amtWritten;
298 }
299 /* Not all got written. Put some into the wBuffer. */
300 if (len + net->wBufStart + net->wBufLen > net->wBufSize) {
301 char *newBuf;
302
303 newBuf = wms_malloc(net->wBufSize = len + net->wBufStart + net->wBufLen);
304 if (net->wBufLen)
305 memcpy(newBuf, net->wBuffer+net->wBufStart, net->wBufLen);
306 net->wBufStart = 0;
307 if (net->wBuffer)
308 wms_free(net->wBuffer);
309 net->wBuffer = newBuf;
310 }
311 memcpy(remainder, net->wBuffer + net->wBufStart + net->wBufLen, len);
312 net->wBufLen += len;
313 butEnv_addFile(net->env, BUT_WRITEFILE, net->fd, net, finishWrite);
314 return(TRUE);
315 }
316
317
finishWrite(void * packet,int fd)318 static ButOut finishWrite(void *packet, int fd) {
319 ButRnet *net = packet;
320 int amtWritten;
321
322 assert(MAGIC(net));
323 amtWritten = write(net->fd, net->wBuffer + net->wBufStart, net->wBufLen);
324 if (amtWritten == net->wBufLen) {
325 butEnv_rmFile(net->env, BUT_WRITEFILE, net->fd);
326 net->wBufLen = 0;
327 net->wBufStart = 0;
328 if (net->state == butRnetState_closing) {
329 close(net->fd);
330 net->fd = -1;
331 MAGIC_UNSET(net);
332 wms_free(net);
333 }
334 } else if (amtWritten < 0) {
335 butRnet_close(net, strerror(errno), TRUE);
336 return(0);
337 } else {
338 net->wBufStart += amtWritten;
339 net->wBufLen -= amtWritten;
340 }
341 return(0);
342 }
343
344
getNetData(void * packet,int fd)345 static ButOut getNetData(void *packet, int fd) {
346 ButRnet *net = packet;
347 int readLen, i, msgType;
348 ButOut res = 0;
349 char *temp;
350
351 assert(MAGIC(net));
352 if (net->rBufAmt < 4) {
353 /* Waiting for the length count. */
354 readLen = read(fd, (char *)&net->rBuffer + net->rBufAmt, 4 - net->rBufAmt);
355 if (readLen <= 0) {
356 if (readLen == 0)
357 butRnet_close(net, "Connection closed", TRUE);
358 else if ((readLen < 0) && (errno != EAGAIN))
359 butRnet_close(net, strerror(errno), TRUE);
360 return(res);
361 }
362 if ((net->rBufAmt += readLen) < 4)
363 return(0);
364 net->rBufMsgLen = stdInt32_int(net->rBuffer.length);
365 if (net->rBufMsgLen > BUTNET_MAXCMD) {
366 fprintf(stderr, "Bogus command\n");
367 for (;;);
368 }
369 net->rBufMsgLen += 8;
370 return(0);
371 }
372 if ((net->rBufMsgLen > BUTNET_MAXCMD+8) ||
373 (net->rBufMsgLen < 8)) {
374 butRnet_close(net, "Invalid data on connection", TRUE);
375 return(res);
376 }
377 readLen = read(fd, (char *)&net->rBuffer + net->rBufAmt,
378 net->rBufMsgLen - net->rBufAmt);
379 if (readLen <= 0) {
380 if (readLen == 0)
381 butRnet_close(net, "Connection closed", TRUE);
382 else if ((readLen < 0) && (errno != EAGAIN))
383 butRnet_close(net, strerror(errno), TRUE);
384 return(res);
385 }
386 net->rBufAmt += readLen;
387 if (net->rBufAmt == net->rBufMsgLen) {
388 msgType = stdInt32_int(net->rBuffer.type);
389 net->rBufAmt = 0;
390 switch(msgType) {
391 case BUTNET_PROTOWHO:
392 if (net->state == butRnetState_pwWait) {
393 net->state = butRnetState_open;
394 /* Force the cursor type to be sent. */
395 net->lType = net->env->curlast;
396 net->env->curlast = butCur_bogus;
397 } else if (net->state == butRnetState_pwAccWait) {
398 net->state = butRnetState_accWait;
399 } else {
400 butRnet_close(net, "Invalid data on connection", TRUE);
401 break;
402 }
403 if (net->rBufMsgLen != sizeof(net->rBuffer.perType.protoWho) + 8) {
404 butRnet_close(net, "Invalid data on connection", TRUE);
405 break;
406 }
407 net->rmtPartner = stdInt32_int(net->rBuffer.perType.protoWho.context);
408 temp = wms_malloc(i = (strlen(net->rBuffer.perType.protoWho.proto) + 1));
409 strcpy(temp, net->rBuffer.perType.protoWho.proto);
410 net->protocol = temp;
411 temp = wms_malloc(strlen(net->rBuffer.perType.protoWho.who) + 1);
412 strcpy(temp, net->rBuffer.perType.protoWho.who);
413 net->who = temp;
414 return(net->ocallback(net));
415 break;
416 case BUTNET_CLOSE:
417 butRnet_close(net, net->rBuffer.perType.close, FALSE);
418 break;
419 case BUTNET_USERDATA:
420 if (net->callback)
421 return(net->callback(net, net->rBuffer.perType.userData,
422 stdInt32_int(net->rBuffer.length)));
423 break;
424 case BUTNET_MOUSE:
425 if (net->rBufMsgLen != sizeof(net->rBuffer.perType.mouse) + 8) {
426 butRnet_close(net, "Invalid data on connection", TRUE);
427 break;
428 }
429 butRcur_move(&net->rc, stdInt32_int(net->rBuffer.perType.mouse.win),
430 stdInt32_int(net->rBuffer.perType.mouse.x),
431 stdInt32_int(net->rBuffer.perType.mouse.y),
432 stdInt32_int(net->rBuffer.perType.mouse.w),
433 stdInt32_int(net->rBuffer.perType.mouse.h),
434 stdInt32_int(net->rBuffer.perType.mouse.type));
435 net->rBuffer.length = int_stdInt32(0);
436 net->rBuffer.type = int_stdInt32(BUTNET_MOUSEACK);
437 butRnet_write(net, &net->rBuffer);
438 break;
439 case BUTNET_MOUSEACK:
440 if (net->rBufMsgLen != 8) {
441 butRnet_close(net, "Invalid data on connection", TRUE);
442 break;
443 }
444 net->ackNeeded = FALSE;
445 if (net->mouseMove) {
446 net->mouseMove = FALSE;
447 butRnet_sendMMove(net, -1, -1,-1, -1,-1, -1);
448 }
449 break;
450 case BUTNET_NEWFLAGS:
451 if (net->rBufMsgLen != sizeof(net->rBuffer.perType.newFlags) + 8) {
452 butRnet_close(net, "Invalid data on connection", TRUE);
453 break;
454 }
455 newFlags(net, stdInt32_int(net->rBuffer.perType.newFlags.butId),
456 stdInt32_int(net->rBuffer.perType.newFlags.newFlags));
457 break;
458 case BUTNET_BUTSPEC:
459 res |= butSpec(net->env,
460 stdInt32_int(net->rBuffer.perType.butSpec.butId),
461 net->rBuffer.perType.butSpec.butData,
462 stdInt32_int(net->rBuffer.length) - sizeof(StdInt32));
463 break;
464 default:
465 butRnet_close(net, "Invalid data on connection", TRUE);
466 break;
467 }
468 }
469 return(res);
470 }
471
472
newFlags(ButRnet * net,int id,uint newFlags)473 static void newFlags(ButRnet *net, int id, uint newFlags) {
474 ButEnv *env = net->env;
475 But *but;
476
477 if (id < env->maxButIds) {
478 but = env->id2But[id];
479 if (but) {
480 if (newFlags & BUT_PRESSED)
481 net->lPress = id;
482 else if (net->lPress == id)
483 net->lPress = -1;
484 if (newFlags & BUT_TWITCHED)
485 net->lTwitch = id;
486 else if (net->lTwitch == id)
487 net->lTwitch = -1;
488 but_newFlags(but, (newFlags & (BUT_NETMASK<<BUT_NETSHIFT)) |
489 (but->flags & ~(BUT_NETMASK<<BUT_NETSHIFT)));
490 }
491 }
492 }
493
494
putProtoWho(ButRnet * net)495 static void putProtoWho(ButRnet *net) {
496 #if HAVE_SYS_UTSNAME_H
497 struct utsname unameOut;
498 #endif
499 struct passwd *pw;
500 char *loginName;
501 ButEnv *env = net->env;
502 ButNetMsg protoOut;
503
504 assert(MAGIC(net));
505 protoOut.length = int_stdInt32(sizeof(protoOut.perType.protoWho));
506 protoOut.type = int_stdInt32(BUTNET_PROTOWHO);
507 #if HAVE_SYS_UTSNAME_H
508 uname(&unameOut);
509 #endif
510 if ((loginName = getlogin()) == NULL) {
511 pw = getpwuid(getuid());
512 loginName = pw->pw_name;
513 }
514 strcpy(protoOut.perType.protoWho.proto, env->protocol);
515 protoOut.perType.protoWho.proto[sizeof(protoOut.perType.protoWho.proto) -
516 1] = '\0';
517 sprintf(protoOut.perType.protoWho.who, "%s@%s",
518 loginName,
519 #if HAVE_SYS_UTSNAME_H
520 unameOut.nodename
521 #else
522 "unknown"
523 #endif
524 );
525 butRnet_write(net, &protoOut);
526 }
527
528
butRnet_close(ButRnet * net,const char * reason,bool force)529 static void butRnet_close(ButRnet *net, const char *reason, bool force) {
530 ButEnv *env = net->env;
531
532 assert(MAGIC(net));
533 if (net->lPress != -1) {
534 if (env->id2But[net->lPress]) {
535 but_newFlags(env->id2But[net->lPress], env->id2But[net->lPress]->flags &
536 ~BUT_NETPRESS);
537 }
538 }
539 if (net->lTwitch != -1) {
540 if (env->id2But[net->lTwitch]) {
541 but_newFlags(env->id2But[net->lTwitch],
542 env->id2But[net->lTwitch]->flags & ~BUT_NETTWITCH);
543 }
544 }
545 if (net->state < butRnetState_closing) {
546 if (reason && net->ccallback)
547 net->ccallback(net, reason);
548 net->state = butRnetState_closing;
549 butEnv_rmFile(net->env, BUT_READFILE, net->fd);
550 if (force || (net->wBufLen == 0)) {
551 close(net->fd);
552 net->fd = -1;
553 if (net->wBufLen != 0)
554 butEnv_rmFile(net->env, BUT_WRITEFILE, net->fd);
555 }
556 }
557 net->env->partners[net->partner] = NULL;
558 MAGIC_UNSET(net);
559 wms_free(net);
560 }
561
562
butRnet_send(ButRnet * net,void * buffer,int len)563 void butRnet_send(ButRnet *net, void *buffer, int len) {
564 ButNetMsg msg;
565
566 assert(len <= BUTNET_MAXCMD);
567 msg.length = int_stdInt32(len);
568 msg.type = int_stdInt32(BUTNET_USERDATA);
569 memcpy(msg.perType.userData, buffer, len);
570 butRnet_write(net, &msg);
571 }
572
573
butRnet_mMove(ButEnv * env,int winId,int lx,int ly,int lw,int lh,ButCur curnum)574 void butRnet_mMove(ButEnv *env, int winId, int lx,int ly, int lw,int lh,
575 ButCur curnum) {
576 int i;
577
578 for (i = 0; i < env->numPartners; ++i) {
579 if (env->partners[i]) {
580 if (butRnet_valid(env->partners[i]) &&
581 ((winId != -2) || (env->partners[i]->lWinId != -2)))
582 butRnet_sendMMove(env->partners[i], winId, lx,ly, lw,lh, curnum);
583 }
584 }
585 }
586
587
butRnet_sendMMove(ButRnet * net,int winId,int lx,int ly,int lw,int lh,ButCur curnum)588 static void butRnet_sendMMove(ButRnet *net, int winId, int lx, int ly,
589 int lw, int lh, ButCur curnum) {
590 ButNetMsg msg;
591
592 if (winId == -1)
593 winId = net->lWinId;
594 if (lx == -1)
595 lx = net->lx;
596 if (ly == -1)
597 ly = net->ly;
598 if (lw == -1)
599 lw = net->lw;
600 if (lh == -1)
601 lh = net->lh;
602 if (curnum == -1)
603 curnum = net->lType;
604 net->lWinId = winId;
605 net->lx = lx;
606 net->ly = ly;
607 net->lw = lw;
608 net->lh = lh;
609 net->lType = curnum;
610 if (net->ackNeeded)
611 net->mouseMove = TRUE;
612 else {
613 msg.length = int_stdInt32(sizeof(msg.perType.mouse));
614 msg.type = int_stdInt32(BUTNET_MOUSE);
615 msg.perType.mouse.context = int_stdInt32(0);
616 msg.perType.mouse.win = int_stdInt32(winId);
617 msg.perType.mouse.x = int_stdInt32(lx);
618 msg.perType.mouse.y = int_stdInt32(ly);
619 msg.perType.mouse.w = int_stdInt32(lw);
620 msg.perType.mouse.h = int_stdInt32(lh);
621 msg.perType.mouse.type = int_stdInt32(curnum);
622 assert((curnum == -1) ||
623 (curnum < butCur_bogus));
624 butRnet_write(net, &msg);
625 }
626 }
627
628
butRnet_newFlags(ButEnv * env,int butId,uint newFlags)629 void butRnet_newFlags(ButEnv *env, int butId, uint newFlags) {
630 int i;
631 ButNetMsg msg;
632
633 if ((butId != -2) && (env->numPartners > 0)) {
634 assert(butId >= 0);
635 assert(butId < env->maxButIds);
636 newFlags = (newFlags & ~(BUT_NETTWITCH|BUT_NETPRESS|BUT_NETKEY)) |
637 ((newFlags & BUT_NETMASK) << BUT_NETSHIFT);
638 msg.length = int_stdInt32(sizeof(msg.perType.newFlags));
639 msg.type = int_stdInt32(BUTNET_NEWFLAGS);
640 msg.perType.newFlags.butId = int_stdInt32(butId);
641 msg.perType.newFlags.newFlags = int_stdInt32(newFlags);
642 for (i = 0; i < env->numPartners; ++i) {
643 if (env->partners[i])
644 if (butRnet_valid(env->partners[i]))
645 butRnet_write(env->partners[i], &msg);
646 }
647 }
648 }
649
650
butSpec(ButEnv * env,int butId,void * buf,int bufLen)651 static ButOut butSpec(ButEnv *env, int butId, void *buf, int bufLen) {
652 But *but;
653
654 but = env->id2But[butId];
655 assert(but->action->netMessage);
656 return(but->action->netMessage(but, buf, bufLen));
657 }
658
659
660 #else /* !HAVE_SOCKETS */
661
butLnet_create(ButEnv * env,int port,void * packet,ButOut ocallback (ButRnet * net),ButOut callback (ButRnet * net,void * cmd,int cmdLen),ButOut ccallback (ButRnet * net,const char * reason))662 ButLnet *butLnet_create(ButEnv *env, int port, void *packet,
663 ButOut ocallback(ButRnet *net),
664 ButOut callback(ButRnet *net, void *cmd, int cmdLen),
665 ButOut ccallback(ButRnet *net, const char *reason)) {
666 ButLnet *net = wms_malloc(sizeof(ButLnet));
667
668 net->error = TRUE;
669 net->valid = FALSE;
670 net->errNum = EPERM;
671 return(net);
672 }
673
674
butRnet_create(ButEnv * env,char * address,int port,void * packet,ButOut ocallback (ButRnet * net),ButOut callback (ButRnet * net,void * cmd,int cmdLen),ButOut ccallback (ButRnet * net,const char * reason))675 ButRnet *butRnet_create(ButEnv *env, char *address, int port,
676 void *packet, ButOut ocallback(ButRnet *net),
677 ButOut callback(ButRnet *net, void *cmd, int cmdLen),
678 ButOut ccallback(ButRnet *net, const char *reason)) {
679 ButRnet *net = wms_malloc(sizeof(ButRnet));
680
681 net->error = TRUE;
682 net->errNum = EPERM;
683 net->state = butRnetState_closed;
684 return(net);
685 }
686
687
butLnet_destroy(ButLnet * net)688 void butLnet_destroy(ButLnet *net) { wms_free(net); }
butRnet_destroy(ButRnet * net,char * reason)689 void butRnet_destroy(ButRnet *net, char *reason) { wms_free(net); }
butRnet_write(ButRnet * net,ButNetMsg * msg)690 bool butRnet_write(ButRnet *net, ButNetMsg *msg) { return(FALSE); }
butRnet_send(ButRnet * net,void * buffer,int len)691 void butRnet_send(ButRnet *net, void *buffer, int len) {}
butRnet_mMove(ButEnv * env,int winId,int lx,int ly,int lw,int lh,ButCur curnum)692 void butRnet_mMove(ButEnv *env, int winId, int lx,int ly, int lw,int lh,
693 ButCur curnum) {}
butRnet_newFlags(ButEnv * env,int butId,uint newFlags)694 void butRnet_newFlags(ButEnv *env, int butId, uint newFlags) {}
butRnet_accept(ButRnet * net)695 void butRnet_accept(ButRnet *net) {}
696
697
698 #endif /* HAVE_SOCKETS */
699
700
but_setId(But * but,int id)701 void but_setId(But *but, int id) {
702 ButEnv *env = but->win->env;
703 int i;
704
705 assert(MAGIC(but));
706 if (id >= env->maxButIds) {
707 But **newId2But;
708 int newMaxButIds = (id + 1)*2;
709
710 newId2But = wms_malloc(newMaxButIds * sizeof(But *));
711 for (i = 0; i < env->maxButIds; ++i)
712 newId2But[i] = env->id2But[i];
713 for (; i < newMaxButIds; ++i)
714 newId2But[i] = NULL;
715 env->maxButIds = newMaxButIds;
716 if (env->id2But)
717 wms_free(env->id2But);
718 env->id2But = newId2But;
719 }
720 if (but->id != -1) {
721 assert(but->id < env->maxButIds);
722 env->id2But[id] = NULL;
723 }
724 env->id2But[id] = but;
725 but->id = id;
726 }
727
728
butWin_setId(ButWin * win,int id)729 void butWin_setId(ButWin *win, int id) {
730 ButEnv *env = win->env;
731 int i;
732
733 assert(MAGIC(win));
734 if (id >= env->maxWinIds) {
735 ButWin **newId2Win;
736 int newMaxWinIds = (id + 1)*2;
737
738 newId2Win = wms_malloc(newMaxWinIds * sizeof(ButWin *));
739 for (i = 0; i < env->maxWinIds; ++i)
740 newId2Win[i] = env->id2Win[i];
741 for (; i < newMaxWinIds; ++i)
742 newId2Win[i] = NULL;
743 env->maxWinIds = newMaxWinIds;
744 if (env->id2Win)
745 wms_free(env->id2Win);
746 env->id2Win = newId2Win;
747 }
748 if (win->id != -1) {
749 assert(win->id < env->maxWinIds);
750 env->id2Win[id] = NULL;
751 }
752 env->id2Win[id] = win;
753 win->id = id;
754 }
755
756
butRnet_butSpecSend(But * but,void * buffer,int len)757 void butRnet_butSpecSend(But *but, void *buffer, int len) {
758 ButEnv *env;
759 ButNetMsg msg;
760 int i;
761
762 assert(len < BUTNET_MAXCMD - sizeof(StdInt32));
763 if (but->id >= 0) {
764 env = but->win->env;
765 if (env->numPartners > 0) {
766 msg.length = int_stdInt32(len + 4);
767 msg.type = int_stdInt32(BUTNET_BUTSPEC);
768 msg.perType.butSpec.butId = int_stdInt32(but->id);
769 if (len > 0)
770 memcpy(msg.perType.butSpec.butData, buffer, len);
771 for (i = 0; i < env->numPartners; ++i) {
772 if (env->partners[i]) {
773 if (butRnet_valid(env->partners[i]))
774 butRnet_write(env->partners[i], &msg);
775 }
776 }
777 }
778 }
779 }
780
781
782 #endif /* X11_DISP */
783