1 /* $NCDId: @(#)Astreams.c,v 1.2 1994/04/20 22:34:53 greg Exp $ */
2 /*
3 * $XConsortium: Xstreams.c,v 1.26 91/07/23 12:15:13 rws Exp $
4 */
5
6 #ifdef STREAMSCONN
7
8 /*
9 * Copyright 1991 USL, Inc.
10 * Copyright 1991 Massachusetts Institute of Technology
11 * Copyright 1988, 1989 AT&T, Inc.
12 *
13 * Permission to use, copy, modify, and distribute this software and
14 * its documentation for any purpose and without fee is hereby
15 * granted, provided that the above copyright notice appear in all
16 * copies and that both that copyright notice and this permission
17 * notice appear in supporting documentation, and that the name of
18 * AT&T, USL, or MIT not be used in advertising or publicity
19 * pertaining to distribution of the software without specific,
20 * written prior permission. AT&T, USL, and MIT make no
21 * representations about the suitability of this software for any
22 * purpose. It is provided "as is" without express or implied
23 * warranty.
24 *
25 * AT&T, USL, AND MIT DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
26 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
27 * NO EVENT SHALL AT&T, USL, OR MIT BE LIABLE FOR ANY SPECIAL,
28 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
29 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
30 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
31 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32 */
33
34 #define _USHORT_H /* prevent conflicts between BSD sys/types.h and
35 interlan/il_types.h */
36
37 #define NEED_REPLIES
38 #include <audio/Alibint.h>
39 #include <audio/Aos.h>
40 #include "Alibnet.h"
41 #include <X11/Xauth.h>
42
43
44 #include <stdio.h>
45 #include <tiuser.h> /* TLI user defs */
46 #include <sys/param.h>
47 #include <sys/utsname.h>
48 #include <signal.h>
49
50 #include <sys/stat.h>
51 #include <errno.h>
52 #include <sys/stropts.h>
53
54 /* stolen from <X11/Xproto.h> */
55 typedef struct {
56 CARD8 family;
57 BYTE pad;
58 CARD16 length B16;
59 } xHostEntry;
60
61 #define sz_xReply 32
62 /* --- */
63
64
65
66 #ifdef SVR4
67 #include <netdir.h>
68 #include <netconfig.h>
69 #ifndef __STDC__
70 /* buggy SVR4 include file */
71 char *setnetpath();
72 struct netconfig *getnetconfigent();
73 struct netconfig *getnetpath();
74 int endnetpath();
75 #endif
76 #endif
77
78
79 #include "Astreams.h"
80
81
82 #ifdef DEBUG
83 #define PRMSG(x,a,b) fprintf(stderr, x,a,b); fflush(stderr)
84 #else
85 #define PRMSG(x,a,b)
86 #endif
87
88
89 #define LISTEN_QUE_SIZE 8 /* maximum # of connections for gen. listen */
90 #define CLEAR 1
91 /*
92 * Ridiculously high value for maximum number of connects per stream.
93 * Transport Provider will determine actual maximum to be used.
94 */
95
96 #define MAXCONNECTIONS 100 /* maximum # of connections for gen. listen */
97
98
99 #define MAXLEN 80
100 #define BUFFERSIZE 2048
101 #define NOBUFFERNEEDED 512
102
103 /* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
104 * systems are broken and return EWOULDBLOCK when they should return EAGAIN
105 */
106 #if defined(EAGAIN) && defined(EWOULDBLOCK)
107 #define ETEST(err) (err == EAGAIN || err == EWOULDBLOCK)
108 #else
109 #ifdef EAGAIN
110 #define ETEST(err) (err == EAGAIN)
111 #else
112 #define ETEST(err) (err == EWOULDBLOCK)
113 #endif
114 #endif
115
116 typedef struct {
117 char *DataBuffer;
118 int FirstBytePtr;
119 int LastBytePtr;
120 } InputBuffer;
121
122 #ifdef SVR4
123 InputBuffer _AusInputBuffer[MAXCONNECTIONS] = {NULL};
124 #else
125 #ifndef NOFILES_MAX
126 #define NOFILES_MAX 128
127 #endif
128 InputBuffer _AusInputBuffer[NOFILES_MAX] = {NULL};
129 #endif /* SVR4*/
130
131
132 static char *ptmx = "/dev/ptmx";
133 static char *dispno = "0";
134
135 #ifdef att
136 extern char *GetAuWINHome ();
137 #endif
138
139 static char _dispno[MAX_DISP_DIGITS];
140
141 extern int t_errno;
142
143 static char ** addheader();
144 static char ** addtliheader();
145
146 static struct t_bind bind_ret, bind_req;
147 static struct t_call call;
148 static char ret_buf[MAXLEN], req_buf[MAXLEN], call_buf[MAXLEN];
149
150
151 static int named = 0; /* not using named streams connection */
152
153 #ifdef USL_SHARELIB
154 #define fopen (*_libX_fopen)
155 extern FILE *fopen();
156 #define t_bind (*_libX_t_bind)
157 extern int t_bind();
158 #undef t_bind
159 #define _iob (*_libX__iob)
160 extern FILE _iob[];
161 #endif /* USL_SHARELIB */
162
163 extern int t_errno;
164
165 #define SIGNAL_T void
166 typedef SIGNAL_T (*PFV)();
167 #ifndef SVR4
168 extern PFV signal();
169 #endif
170
171 #define SUCCESS "1"
172
173 extern char _AusTypeOfStream[];
174 extern Austream _AusStream[];
175
176 static networkInfo Network;
177 static int NameServer = -1;
178 static int CallTheNameServer();
179 static void checkNewEvent();
180 static int OpenVirtualCircuit();
181 static void LookForEvents();
182 static int CheckListenQue();
183 static void ClearCall(), RemoveCall();
184 static int OpenLocalServer();
185 static int OpenNamedServer();
186 static int nameserver();
187
188 /* Routines everybody shares */
189
190
191
_AusErrorCall()192 _AusErrorCall()
193 {
194 fprintf(stderr, "ErrorCall: invalid or unsupported subroutine call\n");
195 return(-1);
196 }
197
198 /*
199 * Following are some general queueing routines. The call list head contains
200 * a pointer to the head of the queue and to the tail of the queue. Normally,
201 * calls are added to the tail and removed from the head to ensure they are
202 * processed in the order received, however, because of the possible interruption
203 * of an acceptance with the resulting requeueing, it is necessary to have a
204 * way to do a "priority queueing" which inserts at the head of the queue for
205 * immediate processing
206 */
207
208 /*
209 * Que:
210 *
211 * add calls to tail of queue
212 */
213
214
215 static void
Que(struct listenQue * head,struct listenCall * lc,char flag)216 Que(struct listenQue *head, struct listenCall *lc, char flag)
217 {
218 if(flag == CLEAR)
219 ClearCall(lc->CurrentCall);
220
221 if (head->QueTail == (struct listenCall *) NULL) {
222 lc->NextCall = (struct listenCall *) NULL;
223 head->QueHead = head->QueTail = lc;
224 }
225 else {
226 lc->NextCall = head->QueTail->NextCall;
227 head->QueTail->NextCall = lc;
228 head->QueTail = lc;
229 }
230 }
231
232
233 /*
234 * pQue:
235 *
236 * priority queuer, add calls to head of queue
237 */
238
239 static void
pQue(struct listenQue * head,struct listenCall * lc)240 pQue(struct listenQue *head, struct listenCall *lc)
241 {
242 if (head->QueHead == (struct listenCall *) NULL) {
243 lc->NextCall = (struct listenCall *) NULL;
244 head->QueHead = head->QueTail = lc;
245 }
246 else {
247 lc->NextCall = head->QueHead;
248 head->QueHead = lc;
249 }
250 }
251
252
253 /*
254 * dequeue:
255 *
256 * remove a call from the head of queue
257 */
258
259
260 static struct listenCall *
deQue(struct listenQue * head)261 deQue(struct listenQue *head)
262 {
263 struct listenCall *ret;
264
265 if (head->QueHead == (struct listenCall *) NULL){
266 PRMSG("Fatal error. Queue is empty (shouldn't happen)\n",0,0);
267 exit(1);
268 }
269 ret = head->QueHead;
270 head->QueHead = ret->NextCall;
271 if (head->QueHead == (struct listenCall *) NULL)
272 head->QueTail = (struct listenCall *) NULL;
273 return(ret);
274 }
275
276 /* Routines for handling local Named streams */
277
278 #ifdef SVR4
_AusSetupNamedStream(char * display,char * stype)279 _AusSetupNamedStream(char *display, char *stype)
280 {
281 int munix, sunix;
282 char * slave;
283 char buf[MAX_AUTO_BUF_LEN];
284 int type = Au_NAMED_STREAM;
285 int fld[2], ret;
286 struct stat sbuf;
287
288 PRMSG("Calling SetupNamedStream()\n",0,0);
289
290 /* if file not there create it, depends on SetupLocalStream to decide whether
291 server already running , no checking is done here */
292
293 munix = atoi(display);
294 sprintf(buf, "%s.%d", NAMED_LISTENER, munix);
295 PRMSG("Calling SetupNamedStream()-(%s)\n",buf,0);
296
297 if(stat(buf, &sbuf)!= 0) {
298 if(errno ==ENOENT) {
299 if(( munix = creat(buf, (mode_t) 0666) ) == -1) {
300 PRMSG(" Can't create: %s\n", buf,0);
301 return(-1);
302 }
303 close(munix);
304 if(chmod(buf,(mode_t) 0666)<0) {
305 PRMSG( "Cannot chmod %s", buf,0);
306 perror(" ");
307 return(-1);
308 }
309 }
310 else {
311 PRMSG("stat err=%d,-%s\n", errno, strerror(errno));
312 return(-1);
313 }
314 }
315
316 if(pipe(fld) != 0)
317 {
318 fprintf(stderr,"pipe failed, errno=%d:%s\n", errno,
319 strerror(errno));
320 return(-1);
321 }
322
323 if((ret=ioctl(fld[0], I_PUSH,"connld")) != 0) {
324 fprintf(stderr,"ioctl error:%s\n", strerror(errno));
325 return(-1);
326 }
327
328 if((fattach(fld[0], buf)) !=0) {
329 fprintf(stderr,"fattach failed:%s\n", strerror(errno));
330 return(-1);
331 }
332
333 _AusTypeOfStream[fld[1]] = type;
334 NetworkInfo->_nnets++;
335
336 return(fld[1]);
337 }
338
339 /* Enhanced Application Compatibility Support */
340
341 int
_AusSetupSpStream(char * display,char * stype)342 _AusSetupSpStream (char *display, char *stype)
343 {
344 return 0;
345 }
346
347 int
_AusConnectSpClient(int connmaster)348 _AusConnectSpClient (int connmaster) /* Add connection to new slave */
349 {
350 return 0;
351 }
352 /* End Enhanced Application Compatibility Support */
353
354 #endif /* SVR4 */
355
356
357
358
359 /* Routines for handling local streams (streams-pipes) */
360 int
_AusSetupLocalStream(char * display,char * stype)361 _AusSetupLocalStream(char *display, char *stype)
362 {
363 int munix, sunix;
364 char * slave;
365 char buf[MAX_AUTO_BUF_LEN];
366 int type = Au_LOCAL_STREAM;
367 int nameserver();
368
369 PRMSG("Calling SetupLocalStream()\n",0,0);
370
371 SetupNetworkInfo();
372 dispno = display;
373
374 NetworkInfo->_nnets = NetworkInfo->_npeers = 0;
375 NetworkInfo->_peer = NULL;
376 NetworkInfo->_peerlen = NULL;
377
378 #ifdef SVR4
379 NetworkInfo->_net[0] = (struct netconfig *) 0;
380 #else
381 NetworkInfo->_net[0] = (char *) 0;
382 #endif
383 NetworkInfo->_nnets++;
384
385
386 munix = atoi(display);
387 /*
388 if(munix != 0){
389 fprintf(stderr, "Only display # 0 can be used on this server\n");
390 return(-1);
391 }
392 */
393
394 sprintf(buf, "%s.%d", LOCAL_LISTENER, munix);
395 /*
396 if(open(buf, O_RDWR) >= 0){
397 fprintf(stderr, "Server is already running\n");
398 return(-1);
399 }
400 */
401 if( (munix = open(ptmx, O_RDWR)) < 0 ){
402 fprintf(stderr,"Cannot open %s", ptmx);
403 perror(" ");
404 return(-1);
405 }
406 grantpt(munix);
407 unlockpt(munix);
408
409 if(unlink(buf) < 0 && errno != ENOENT){
410 fprintf(stderr, "Cannot unlink %s", buf);
411 perror(" ");
412 return(-1);
413 }
414
415 if(! (slave = (char *) ptsname(munix))) {
416 close(munix);
417 perror("Cannot get slave pt-name");
418 return(-1);
419 }
420
421 if( link(slave, buf) <0 ){
422 fprintf(stderr, "Cannot link %s to %s", slave, buf);
423 perror(" ");
424 return(-1);
425 }
426 if( chmod(buf, 0666) < 0){
427 close(munix);
428 fprintf(stderr, "Cannot chmod %s", buf);
429 perror(" ");
430 return(-1);
431 }
432
433 sunix = open(buf, O_RDWR);
434 if(sunix < 0){
435 fprintf(stderr, "Cannot open %s", buf);
436 perror(" ");
437 close(munix);
438 return(-1);
439 }
440
441 _AusTypeOfStream[munix] = type;
442 _AusTypeOfStream[sunix] = CLOSED_STREAM;
443
444 return(munix);
445 }
446
447 int
_AusConnectLocalClient(int ufd,char * MoreConnections)448 _AusConnectLocalClient(int ufd, char *MoreConnections)
449 {
450
451 int fd;
452 int read_in;
453 unsigned char length;
454 char buf[MAX_AUTO_BUF_LEN];
455 #ifdef SVR4
456 struct strrecvfd str;
457 #endif
458
459
460 PRMSG("Calling ConnectLocalClient(%d)\n", ufd,0);
461
462 /* MoreConnections is set to zero because if any more connections are underway
463 * select() will return immediately. It is nicer if we can process all connections
464 * that exist the way we handle TLI connections by setting MoreConnections.
465 * May be I will end up doing it later.
466 */
467 *MoreConnections = 0;
468
469 #ifdef SVR4
470
471 if( _AusTypeOfStream[ufd] == Au_NAMED_STREAM) {
472 PRMSG("Calling ConnectLocalClient(%d) - thru named streams\n", ufd,0);
473 if (ioctl(ufd, I_RECVFD, &str) < 0) {
474 fprintf(stderr,"I_RECVFD failed\n");
475 return(-1);
476 }
477
478 _AusTypeOfStream[str.fd] = _AusTypeOfStream[ufd];
479 PRMSG("ConnectNamedClient(%d) return success\n", str.fd,0);
480 return(str.fd);
481 }
482
483 /* Enhanced Application Compatibility Support */
484
485 /* End Enhanced Application Compatibility Support */
486
487 #endif /* SVR4 */
488
489 PRMSG("Calling ConnectLocalClient(%d) - thru psuedo tty\n", ufd,0);
490
491 if( (read_in = read(ufd, &length, 1)) <= 0 ){
492 if( !read_in ) /* client closed fd */
493 perror("0 bytes read");
494 else perror("Error in reading the local connection msg length");
495 return(-1);
496 }
497
498
499 if( (read_in = read(ufd, buf, length)) <= 0 ){
500 if( !read_in ) /* client closed fd */
501 perror("0 bytes read");
502 else perror("Error in reading the local connection slave name");
503 return(-1);
504 }
505
506 buf[ length ] = '\0';
507
508 if( (fd = open(buf,O_RDWR)) < 0 ){
509 strcat(buf," open fail, clientfd");
510 perror(buf);
511 return(-1);
512 }
513
514 write(fd,SUCCESS,1);
515
516 _AusTypeOfStream[fd] = _AusTypeOfStream[ufd];
517 PRMSG("ConnectLocalClient(%d) return success\n", ufd,0);
518 return(fd);
519 }
520
dummy(int sig)521 static void dummy (int sig)
522 {
523 return;
524 }
525
526 int
527 _AusCallLocalServer(char *host, int idisplay,
528 #ifdef SVR4
529 struct netconfig *nettype,
530 #else
531 char *nettype,
532 #endif
533 )
534 {
535 char buf[MAX_AUTO_BUF_LEN];
536 char *listener;
537 int type = Au_LOCAL_STREAM;
538 int fd;
539
540
541 PRMSG("Calling CallLocalServer(%s)\n", host,0);
542
543 sprintf(_dispno, "%d", idisplay);
544 dispno = _dispno;
545
546 /*
547 * Open channel to server
548 */
549
550
551 #ifdef SVR4
552 if (strncmp("NAMED", (char *) getenv("XLOCAL"), 5) == 0) {
553 named = 1;
554 type = Au_NAMED_STREAM;
555 listener = NAMED_LISTENER;
556 sprintf(buf, "%s.%d", listener, idisplay);
557 if((fd = OpenNamedServer(buf)) < 0)
558 {
559 PRMSG("Cannot open %s\n", buf,0);
560 #ifdef DEBUG
561 perror("AuIO"); /* Sorry, but I don't have the dpy handy */
562 #endif
563 return(-1);
564 }
565 }
566
567 /* Enhanced Application Compatibility Support */
568
569 /* End Enhanced Application Compatibility Support */
570 #endif
571
572
573 if(!named) {
574 type = Au_LOCAL_STREAM;
575 listener = LOCAL_LISTENER;
576 sprintf(buf, "%s.%d", listener, idisplay);
577 PRMSG("buf for local listener %s\n",buf,0);
578 if((fd = OpenLocalServer(buf)) < 0)
579 {
580 PRMSG("Cannot open %s\n", buf,0);
581 #ifdef DEBUG
582 perror("AuIO"); /* Sorry, but I don't have the dpy handy */
583 #endif
584 return(-1);
585 }
586 }
587
588
589 _AusTypeOfStream[fd] = type;
590 if (_AusInputBuffer[fd].DataBuffer == NULL)
591 if ((_AusInputBuffer[fd].DataBuffer = (char *) malloc(BUFFERSIZE)) == NULL)
592 {
593 errno = ENOMEM;
594 perror("Client can't connect to local server");
595 return (-1);
596 }
597 _AusInputBuffer[fd].LastBytePtr = 0;
598 _AusInputBuffer[fd].FirstBytePtr = 0;
599
600 PRMSG("Calling CallLocalServer(%s) return success\n", host,fd);
601
602 return(fd);
603 }
604
605
606
607
608 #ifdef SVR4
609 static int
610 OpenNamedServer(char *node)
611 char *node;
612 {
613 int fld;
614
615 PRMSG("Calling 4.0 -- opening (%s)\n", node,0);
616
617 fld = open(node, O_RDWR);
618 if(fld <0) {
619 fprintf(stderr,"OpenNamedServer failed:%s\n", strerror(errno));
620 return(-1);
621 }
622
623 if(isastream(fld) != 1) {
624 fprintf(stderr,"OpenNamedServer failed: %s is not a NamedStream\n",
625 node);
626 return(-1);
627 }
628
629 return (fld);
630 }
631
632 /* Enhanced Application Compatibility Support */
633
634 static int
_AusOpenSpServer(char * node)635 _AusOpenSpServer(char *node)
636 {
637 return 0;
638 }
639 /* End Enhanced Application Compatibility Support */
640
641 #endif /* SVR4 */
642
643 static int
OpenLocalServer(char * node)644 OpenLocalServer(char *node)
645 {
646 int server, fd, c;
647 char buf[MAX_AUTO_BUF_LEN], *slave;
648 PFV savef;
649
650 if ((server = open (node, O_RDWR)) < 0)
651 {
652 #ifdef DEBUG
653 fprintf(stderr, "open(%s) failed\n", node);
654 perror(" ");
655 #endif
656 return(-1);
657 }
658
659 /*
660 * Open streams based pipe and get slave name
661 */
662
663
664 if ((fd = open (ptmx, O_RDWR)) < 0) {
665 close (server);
666 PRMSG("Cannot open %s\n", ptmx, 0);
667 return(-1);
668 }
669
670 grantpt (fd);
671
672 unlockpt (fd);
673
674 if (! (slave = (char *) ptsname(fd))) {
675 close(fd);
676 close(server);
677 PRMSG("Cannot get slave pt-name", 0, 0);
678 return(-1);
679 }
680
681
682 if (chmod(slave, 0666) < 0)
683 {
684 close(fd);
685 close(server);
686 PRMSG("Cannot chmod %s\n", buf,0);
687 return(-1);
688 }
689
690 c = strlen (slave);
691
692 buf[0] = c;
693 sprintf(&buf[1], slave);
694
695 /*
696 * write slave name to server
697 */
698
699 write(server, buf, c+1);
700 close (server);
701 /*
702 * wait for server to respond
703 */
704 savef = signal (SIGALRM, dummy);
705 alarm (CONNECT_TIMEOUT);
706
707 if (read (fd, &c, 1) != 1)
708 {
709 fprintf(stderr, "No reply from the server.\n");
710 close(fd);
711 fd = -1;
712 }
713 alarm (0);
714 signal (SIGALRM, savef);
715
716 return(fd);
717 }
718
719 #ifdef DEBUG
dumpBytes(int len,char * data)720 static void dumpBytes (int len, char *data)
721 {
722 int i;
723
724 fprintf(stderr, "%d: ", len);
725 for (i = 0; i < len; i++)
726 fprintf(stderr, "%02x ", data[i] & 0377);
727 fprintf(stderr, "\n");
728
729 return;
730 }
731 #endif
732
733 #define AuSTREAMS_COMPILE /* magic symbol to avoid lint problems */
734 #ifdef SVR4
735 #include "nameaddr.c"
736 #else
737 #include "nameserver.c"
738 #endif
739 #undef AuSTREAMS_COMPILE
740
741 int
_AusReadLocalStream(int fd,char * buf,int count,int do_buffering)742 _AusReadLocalStream(int fd, char *buf, int count, int do_buffering)
743 {
744 int amount;
745 InputBuffer *ioptr = &_AusInputBuffer[fd];
746
747 if (do_buffering == NO_BUFFERING){
748 amount = read(fd, buf, count);
749
750 return (amount);
751 }
752
753 if (ioptr->LastBytePtr <= ioptr->FirstBytePtr)
754 {
755 errno = 0;
756 if(count > BUFFERSIZE)
757 {
758 ioptr->LastBytePtr = ioptr->FirstBytePtr = 0;
759 amount = read(fd, buf, count);
760
761 return(amount);
762 }
763
764 /* JET - 5/8/99 - hmmm, this buffer may not be allocated yet,
765 if it's not there, allocate it */
766 if (ioptr->DataBuffer == NULL)
767 if ((ioptr->DataBuffer = (char *) malloc(BUFFERSIZE)) == NULL)
768 {
769 errno = ENOMEM;
770 perror("Client can't connect to remote server");
771 return (-1);
772 }
773
774 ioptr->LastBytePtr = read(fd, ioptr->DataBuffer, BUFFERSIZE);
775
776 ioptr->FirstBytePtr = 0;
777 }
778
779 if (ioptr->LastBytePtr > 0)
780 {
781 amount = ioptr->LastBytePtr - ioptr->FirstBytePtr;
782 amount = amount > count ? count : amount;
783 memcpy(buf, &ioptr->DataBuffer[ioptr->FirstBytePtr], amount);
784 ioptr->FirstBytePtr += amount;
785 return amount;
786 }
787 else {
788 return (ioptr->LastBytePtr);
789 }
790
791 }
792
793 int
_AusWriteLocalStream(int fd,char * buf,int count)794 _AusWriteLocalStream(int fd, char *buf, int count)
795 {
796 /* obsolete code */
797 return (write(fd, buf, count));
798 }
799
800 int
_AusCloseLocalStream(int fd)801 _AusCloseLocalStream(int fd)
802 {
803 /* obsolete code */
804 return (close(fd));
805 }
806
807
808
809 int
_AusConnectTliClient(int sfd,char * MoreConnections)810 _AusConnectTliClient(int sfd, char *MoreConnections)
811 {
812 register char type = _AusTypeOfStream[sfd];
813 register struct listenQue *freeq, *pendq;
814
815 freeq = &Network.FreeList[type];
816 pendq = &Network.PendingQue[type];
817
818 PRMSG("Calling ConnectTliClient(%d)\n", sfd,0);
819 LookForEvents(freeq, pendq, sfd);
820 return (CheckListenQue(freeq, pendq, sfd, MoreConnections));
821 }
822
823
824 static void
checkNewEvent(int fd)825 checkNewEvent(int fd)
826 {
827 int t;
828
829 t = t_look(fd);
830 switch(t)
831 {
832 case T_DATA :
833 fprintf(stderr, "T_DATA received\n");
834 break;
835 case T_EXDATA :
836 fprintf(stderr, "T_EXDATA received\n");
837 break;
838 case T_DISCONNECT :
839 t_rcvdis(fd, NULL);
840 fprintf(stderr, "T_DISCONNECT received\n");
841 break;
842 case T_ERROR :
843 fprintf(stderr, "T_ERROR received\n");
844 break;
845 case T_UDERR :
846 fprintf(stderr, "T_UDERR received\n");
847 break;
848 case T_ORDREL :
849 fprintf(stderr, "T_ORDREL received\n");
850 break;
851 }
852 }
853
854 int
_AusReadTliStream(int fd,char * buf,int count,int do_buffering)855 _AusReadTliStream(int fd, char *buf, int count, int do_buffering)
856 {
857 /* obsolete code */
858 return 0;
859 }
860
_AusWriteTliStream(int fd,char * buf,int count)861 _AusWriteTliStream(int fd, char *buf, int count)
862 {
863 return 0;
864 /* obsolete code */
865 }
866
867 static void
868 OnError(int sig)
869 int sig;
870 {
871 return;
872 }
873
874 int
_AusCloseTliStream(int fd)875 _AusCloseTliStream(int fd)
876 {
877 /* obsolete code */
878 return 0;
879 }
880
881 /*
882 * LookForEvents: handle an asynchronous event
883 */
884
885 static void
LookForEvents(struct listenQue * FreeHead,struct listenQue * PendHead,int fd)886 LookForEvents(struct listenQue *FreeHead, struct listenQue *PendHead, int fd)
887 {
888 int address;
889 short port, nf;
890 struct t_discon disc;
891 struct listenCall *current;
892 struct t_call *call;
893 int t;
894 char buf[MAX_AUTO_BUF_LEN];
895 int flag, i;
896
897 if((t = t_look(fd)) < 0) {
898 PRMSG("t_look failed. t_errno %d\n", t_errno,0);
899 return;
900 }
901 switch (t) {
902 case 0:
903 PRMSG("t_look 0\n",0,0);
904 break;
905 /* no return */
906 case T_LISTEN:
907 PRMSG("t_look T_LISTEN\n",0,0);
908 current = deQue(FreeHead);
909 call = current->CurrentCall;
910
911 if (t_listen(fd, call) < 0) {
912 PRMSG("t_listen failed\n",0,0);
913 return;
914 }
915
916 Que(PendHead, current, ~CLEAR);
917 PRMSG("incoming call seq # %d", call->sequence,0);
918 break;
919 case T_DISCONNECT:
920 PRMSG("t_look T_DISCONNECT\n",0,0);
921 if (t_rcvdis(fd, &disc) < 0) {
922 PRMSG("Received T_DISCONNECT but t_rcvdis failed\n",0,0);
923 exit(1);
924 }
925 PRMSG("incoming disconnect seq # %d", disc.sequence,0);
926 RemoveCall(FreeHead, PendHead, &disc);
927 t_close(fd);
928 _AusTypeOfStream[fd] = -1;
929 break;
930 case T_DATA :
931 if((i = t_rcv(fd, buf, MAX_AUTO_BUF_LEN, &flag)) > 0)
932 break;
933 default:
934 PRMSG("t_look default %o %x\n", t, t);
935 break;
936 }
937 }
938
939
940 /*
941 * CheckListenQue: try to accept a connection
942 */
943
944 static int
CheckListenQue(struct listenQue * FreeHead,struct listenQue * PendHead,int fd,char * MoreConnections)945 CheckListenQue(struct listenQue *FreeHead, struct listenQue *PendHead,
946 int fd, char *MoreConnections)
947 {
948 struct listenCall *current;
949 struct t_call *call;
950 int pid, nfd, n;
951 char *retptr, *ptr;
952
953 int address;
954 short port, nf;
955
956 PRMSG( "in CheckListenQue",0,0);
957 if (!(EMPTY(PendHead)))
958 {
959 current = deQue(PendHead);
960 call = current->CurrentCall;
961 PRMSG( "try to accept #%d", call->sequence,0);
962 if((nfd = OpenVirtualCircuit(fd)) < 0)
963 {
964 PRMSG( "OpenVirtualCircuit failed\n",0,0);
965 Que(FreeHead, current, CLEAR);
966 *MoreConnections = !EMPTY(PendHead);
967 return(-1); /* let transport provider generate disconnect */
968 }
969
970 n = t_accept(fd, nfd, call);
971 if (n < 0){
972
973 PRMSG( "t_accept failed\n",0,0);
974 if (t_errno == TLOOK) {
975 t_close(nfd);
976 PRMSG( "t_accept collision",0,0);
977 PRMSG( "save call #%d", call->sequence,0);
978 pQue(PendHead, current);
979 *MoreConnections = !EMPTY(PendHead);
980 return(-1);
981 }
982 else {
983 PRMSG( "t_accept failed but not t_look\n",0,0);
984 t_close(nfd);
985 Que(FreeHead, current, CLEAR);
986 *MoreConnections = !EMPTY(PendHead);
987 return(-1);
988 }
989 }
990 _AusTypeOfStream[nfd] = _AusTypeOfStream[fd];
991 retptr = NULL;
992
993
994
995
996 if( GetNetworkInfo (nfd, Network._net[_AusTypeOfStream[fd]],
997 ConvertTliCallToName, addtliheader(call), &retptr, NULL) <= 0)
998
999 {
1000 retptr = NULL;
1001
1002 }
1003 ptr = NULL;
1004 if(retptr != NULL)
1005 {
1006 ptr = retptr;
1007 retptr += sizeof(xHostEntry);
1008 }
1009 GetNetworkInfo (nfd, Network._net[_AusTypeOfStream[fd]], PEER_ALLOC, &retptr, NULL);
1010 if(ptr != NULL)
1011 Aufree(ptr);
1012 PRMSG( "Accepted call %d", call->sequence,0);
1013 PRMSG("Channel %d is opened\n", nfd,0);
1014
1015 Que(FreeHead, current, CLEAR);
1016
1017
1018 (void) ioctl(nfd, I_POP, "timod");
1019 if(ioctl(nfd, I_PUSH, "tirdwr") < 0)
1020 {
1021 t_close(nfd);
1022 return(-1);
1023 }
1024
1025 PRMSG( "Accepted call %d", call->sequence,0);
1026 PRMSG("Channel %d is opened\n", nfd,0);
1027
1028 *MoreConnections = !EMPTY(PendHead);
1029 return(nfd);
1030 }
1031
1032 *MoreConnections = !EMPTY(PendHead);
1033 return(-1);
1034 }
1035
1036
1037 /*
1038 * ClearCall: clear out a call structure
1039 */
1040
1041 static void
ClearCall(struct t_call * call)1042 ClearCall(struct t_call *call)
1043 {
1044 call->sequence = 0;
1045 call->addr.len = 0;
1046 call->opt.len = 0;
1047 call->udata.len = 0;
1048 memset(call->addr.buf, 0, call->addr.maxlen);
1049 memset(call->opt.buf, 0, call->opt.maxlen);
1050 memset(call->udata.buf, 0, call->udata.maxlen);
1051 }
1052
1053
1054 /*
1055 * RemoveCall: remove call from pending list
1056 */
1057
1058 static void
RemoveCall(struct listenQue * freeq,struct listenQue * pendq,struct t_discon * disc)1059 RemoveCall(struct listenQue *freeq, struct listenQue *pendq,
1060 struct t_discon *disc)
1061 {
1062 struct listenCall *p, *oldp;
1063
1064 PRMSG( "Removing call, sequence # is %d", disc->sequence,0);
1065 if (EMPTY(pendq)) {
1066 disc->sequence = -1;
1067 return;
1068 }
1069 p = pendq->QueHead;
1070 oldp = (struct listenCall *) NULL;
1071 while (p) {
1072 if (p->CurrentCall->sequence == disc->sequence) {
1073 if (oldp == (struct listenCall *) NULL) {
1074 pendq->QueHead = p->NextCall;
1075 if (pendq->QueHead == (struct listenCall *) NULL) {
1076 pendq->QueTail = (struct listenCall *) NULL;
1077 }
1078 }
1079 else if (p == pendq->QueTail) {
1080 oldp->NextCall = p->NextCall;
1081 pendq->QueTail = oldp;
1082 }
1083 else {
1084 oldp->NextCall = p->NextCall;
1085 }
1086 Que(freeq, p, CLEAR);
1087 disc->sequence = -1;
1088 return;
1089 }
1090 oldp = p;
1091 p = p->NextCall;
1092 }
1093 disc->sequence = -1;
1094 return;
1095 }
1096
1097
1098 static int
1099 nameserver(int fd,
1100 #ifdef SVR4
1101 struct netconfig *nettype;
1102 #else
1103 char *nettype;
1104 #endif
1105 int service;
1106 char **arg1, **arg2;
1107 int *arg3;
1108 }
1109 {
1110
1111 char *ptr;
1112 int n;
1113 int type;
1114
1115 if (fd >= 0)
1116 type = _AusTypeOfStream[fd];
1117 else
1118 type = Au_TLI_STREAM;
1119
1120 if(type < Au_TLI_STREAM || type >= Network._nnets)
1121 {
1122 if(type == Au_LOCAL_STREAM || type == Au_NAMED_STREAM)
1123 return(0);
1124 if(fd >= 0)
1125
1126 {
1127 PRMSG("in nameserver type %d unknown d\n", type, fd);
1128 return(-1);
1129 }
1130 }
1131
1132 if(nettype == NULL)
1133 nettype = Network._net[type];
1134
1135
1136 switch(service){
1137 case OpenDaemonConnection :
1138 #ifdef SVR4
1139 return(InitializeNetPath());
1140 #else
1141 if(NameServer < 0 )
1142 NameServer = OpenLocalServer(NAME_SERVER_NODE);
1143 return(NameServer);
1144 #endif /* SVR4 */
1145
1146 case ConvertTliCallToName :
1147 case ConvertNetAddrToName :
1148 case ConvertNameToNetAddr :
1149 case ConvertNameToTliBind :
1150 case ConvertNameToTliCall :
1151 if((n = CallTheNameServer(service, nettype, arg1, arg2, arg3)) < 0)
1152 return(-1);
1153 return(n);
1154
1155 case PEER_NAME :
1156 if( fd < Network._npeers )
1157 {
1158 *arg2 = Network._peer[fd];
1159 return(1);
1160 }
1161 return(-1);
1162 case PEER_ALLOC :
1163 if(fd >= Network._npeers)
1164 return(-1);
1165
1166 if(*arg1 == NULL){
1167 n = 0;
1168 }
1169 else n = strlen(*arg1);
1170
1171 Network._peerlen[fd] = n;
1172
1173 if(n > 0){
1174 if(Network._peerlen[fd] > UNAME_LENGTH)
1175 Network._peerlen[fd] = UNAME_LENGTH;
1176 bcopy(*arg1, Network._peer[fd], Network._peerlen[fd]);
1177 Network._peer[fd][Network._peerlen[fd]] = '\0';
1178 }
1179 else {
1180 Network._peer[fd][0] = '\0';
1181 }
1182 return(1);
1183
1184 case PEER_FREE :
1185 if(fd < Network._npeers && Network._peer[fd] != NULL)
1186 {
1187 Network._peer[fd][0] = '\0';
1188 Network._peerlen[fd] = 0;
1189 }
1190 return(1);
1191 }
1192 }
1193
1194
1195 static int _hlen = 0;
1196 static char *_hptr = NULL;
1197
1198 static char **
1199 addheader(char *string, int len)
1200 {
1201
1202 int n, m, p;
1203 char *ptr;
1204
1205 n = len;
1206 m = n + sizeof(xHostEntry);
1207 p = m + 2 * sizeof(int);
1208
1209 if(p > _hlen){
1210 if(_hptr == NULL)
1211 _hptr = malloc(p);
1212 else _hptr = realloc(_hptr, p);
1213 }
1214 if(_hptr == NULL){
1215 fprintf(stderr, "addheader(): malloc failed\n");
1216 exit(1);
1217 }
1218 else if(p > _hlen)
1219 _hlen = p;
1220
1221 ptr = _hptr;
1222
1223 *(int *) ptr = m;
1224 ptr += sizeof(int);
1225 *(int *) ptr = 1;
1226 ptr += sizeof(int);
1227
1228 ((xHostEntry *) ptr)-> length = n;
1229 ptr += sizeof(xHostEntry);
1230 memcpy(ptr, string, n);
1231
1232 return(&_hptr);
1233 }
1234
1235 static char **
1236 addtliheader(struct t_call *call)
1237 {
1238
1239
1240 char *ptr;
1241 int a, o, u;
1242 int ra, ro, ru, rentlen;
1243
1244
1245 a = call->addr.len;
1246 o = call->opt.len;
1247 u = call->udata.len;
1248
1249 ra = ((a + sizeof(xHostEntry) +3) >>2) << 2;
1250 ro = ((o + sizeof(xHostEntry) +3) >>2) << 2;
1251 ru = ((u + sizeof(xHostEntry) +3) >>2) << 2;
1252
1253 rentlen = ra + ro + ru + 2 * sizeof(int);
1254
1255 if(rentlen > _hlen){
1256 if(_hptr == NULL)
1257 _hptr = malloc(rentlen);
1258 else _hptr = realloc(_hptr, rentlen);
1259 }
1260 if(_hptr == NULL){
1261 fprintf(stderr, "addheader(): malloc failed\n");
1262 exit(1);
1263 }
1264 else if(rentlen > _hlen)
1265 _hlen = rentlen;
1266
1267 ptr = _hptr;
1268
1269 *(int *) ptr = rentlen - 2 * sizeof(int);
1270 ptr += sizeof(int);
1271 *(int *) ptr = 1;
1272 ptr += sizeof(int);
1273
1274 ((xHostEntry *) ptr)-> length = a;
1275 if(a > 0){
1276 memcpy(ptr + sizeof(xHostEntry), call->addr.buf, a);
1277 }
1278
1279
1280 ptr += ra;
1281 ((xHostEntry *) ptr)-> length = o;
1282 if(o > 0)
1283 memcpy(ptr + sizeof(xHostEntry), call->opt.buf, o);
1284
1285 ptr += ro;
1286 ((xHostEntry *) ptr)-> length = u;
1287 if(u > 0){
1288 memcpy(ptr + sizeof(xHostEntry), call->udata.buf, u);
1289 }
1290
1291 return(&_hptr);
1292 }
1293
1294
1295 int _AuBytesReadable (int fd, int *ptr)
1296 {
1297 int inbuf;
1298 int n;
1299 int flg;
1300 InputBuffer *ioptr = &_AusInputBuffer[fd];
1301
1302 inbuf = ioptr->LastBytePtr - ioptr->FirstBytePtr;
1303
1304 if (inbuf >= SIZEOF(xReply))
1305 {
1306 *ptr = inbuf;
1307 return (0);
1308 }
1309
1310 if (ioptr->FirstBytePtr > 0)
1311 {
1312 /* move tidbit to front of buffer */
1313 bcopy(&ioptr->DataBuffer[ioptr->FirstBytePtr],
1314 ioptr->DataBuffer, inbuf);
1315
1316 /* Adjust pointers in buffer to reflect move */
1317 ioptr->LastBytePtr = inbuf;
1318 ioptr->FirstBytePtr = 0;
1319 }
1320
1321 if (inbuf < 0)
1322 {
1323 inbuf = 0;
1324 ioptr->LastBytePtr = 0;
1325 }
1326 /* Read no more than number of bytes left in buffer */
1327
1328 errno = 0;
1329
1330
1331 n = read(fd, &ioptr->DataBuffer[inbuf], BUFFERSIZE-inbuf);
1332 if (n > 0)
1333 {
1334 ioptr->LastBytePtr += n;
1335 *ptr = ioptr->LastBytePtr;
1336 return (0);
1337 }
1338 else
1339 {
1340 if (ETEST(errno))
1341 {
1342 *ptr = ioptr->LastBytePtr;
1343 return (0);
1344 }
1345 else
1346 {
1347 if (n == 0 )
1348 {
1349 errno = EPIPE;
1350 return (-1);
1351 }
1352 else
1353 {
1354 if (errno != EINTR)
1355 return (-1);
1356 else
1357 {
1358 *ptr = ioptr->LastBytePtr;
1359 return (0);
1360 }
1361 }
1362 }
1363 }
1364 }
1365
1366
1367
1368
1369 #ifndef SVR4
1370
1371 #include <sys/poll.h>
1372
1373 #define POLLERROR (POLLHUP | POLLNVAL | POLLERR)
1374 #define PFD(fds, i, x) { if (fds) if (ev & (x)) BITSET (fds, i); else BITCLEAR (fds, i); }
1375 #define ERROR(x) { errno = x; return -1; }
1376 /*
1377 simulate BSD select system call with SYSV poll system call
1378 note that efds parameter is not fully supported (or understood)
1379 */
1380
1381 extern long ulimit();
1382
1383 int
1384 pollselect (int nfds, unsigned long *rfds, unsigned long *wfds,
1385 unsigned long *efds, struct timeval *timeout)
1386 {
1387 int i, rc, ev, timevalue;
1388 struct pollfd pfds[NOFILES_MAX];
1389 static long _NOFILE = 0;
1390
1391 PRMSG("in pollselect\n", 0,0);
1392
1393 if (_NOFILE == 0) {
1394 _NOFILE = ulimit(4, (long)0);
1395 if (_NOFILE > NOFILES_MAX)
1396 _NOFILE = NOFILES_MAX;
1397 }
1398
1399 if (nfds > _NOFILE)
1400 nfds = _NOFILE; /* make poll happy */
1401
1402 for (i = 0; i < nfds; i++)
1403 {
1404 ev = 0;
1405
1406 if (rfds && GETBIT (rfds, i)) ev |= POLLIN;
1407 if (wfds && GETBIT (wfds, i)) ev |= POLLOUT;
1408 if (ev || (efds && GETBIT (efds, i)))
1409 pfds[i].fd = i;
1410 else
1411 pfds[i].fd = -1;
1412 pfds[i].events = ev;
1413 }
1414 if (timeout)
1415 timevalue = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
1416 else
1417 timevalue = -1;
1418
1419 while (1) {
1420 rc = poll (pfds, (unsigned long)nfds, timevalue);
1421
1422 if(rc<0 && errno == EAGAIN)
1423 continue;
1424 else break;
1425 }
1426 if(rc>0) {
1427 if (!efds)
1428 for (i = 0; i < nfds; ++i)
1429 {
1430 ev = pfds[i].revents;
1431 if (ev & POLLERROR)
1432 ERROR (EBADF);
1433 }
1434
1435 for (i = 0; i < nfds; ++i)
1436 {
1437 ev = pfds[i].revents;
1438 PFD (rfds, i, POLLIN);
1439 PFD (wfds, i, POLLOUT);
1440 PFD (efds, i, POLLERROR);
1441 }
1442 }
1443
1444 if(rc==0) {
1445 i = (nfds+ 7)/8;
1446 if ( rfds != NULL)
1447 memset((char *) rfds, 0, i);
1448 if ( wfds != NULL)
1449 memset((char *) wfds, 0, i);
1450 if ( efds != NULL)
1451 memset((char *) efds, 0, i);
1452
1453 }
1454
1455 return rc;
1456 }
1457 #define SELECT pollselect
1458
1459
1460 #else
1461 #define SELECT select
1462 #endif /* ndef SVR4 */
1463
1464
1465 /* The following routine is used for USL Compatibility between
1466 * Operating System versions of SVR4.0 and SVR3.2. In System
1467 * V Release 3.2 the select call is not available, and the
1468 * pollselect is used to poll for connections. In SVR4.0 the
1469 * system supplies select and it is used. However, the arguments
1470 * to these routines are not identical so this routine
1471 * takes care of operating system differences by calling the
1472 * proper os dependent routine. It is called (by USL) from the
1473 * server, Xlib and Xt.
1474 */
1475
1476 int
1477 _AuSelect(int nfds, unsigned long *r_mask, unsigned long *w_mask,
1478 unsigned long *e_mask, struct timeval *timeout)
1479 {
1480 int retval = 0;
1481 int count = 0;
1482 int i;
1483 unsigned long save_mask[MSKCNT];
1484 static struct timeval notime;
1485
1486 /*PRMSG("IN AuSelect from Austreams nfds=%d r_mask=%0x\n",nfds ,r_mask);*/
1487 if (r_mask) {
1488 CLEARBITS(save_mask);
1489
1490 for (i = 0; i < nfds; ++i) {
1491 if (GETBIT(r_mask, i)
1492 && (_AusInputBuffer[i].LastBytePtr - _AusInputBuffer[i].FirstBytePtr) > 0) {
1493 BITCLEAR(r_mask, i);
1494 BITSET(save_mask, i);
1495 ++count;
1496 }
1497 }
1498 }
1499 if (count) {
1500 if (_AuANYSET((AuInt32 *)r_mask)
1501 || (w_mask && _AuANYSET((AuInt32 *)w_mask))
1502 || (e_mask && _AuANYSET((AuInt32 *)e_mask))) {
1503 retval = SELECT(nfds, r_mask, w_mask, e_mask, ¬ime);
1504 }
1505
1506 for (i = 0; i < nfds; ++i) {
1507 if (GETBIT(save_mask, i)) {
1508 BITSET(r_mask, i);
1509 }
1510 }
1511 return retval < 0 ? retval : retval + count;
1512 } else {
1513 return SELECT(nfds, r_mask, w_mask, e_mask, timeout);
1514
1515 }
1516 } /* AuSelect() */
1517
1518
1519
1520 #else /* not STREAMSCONN */
1521 #ifndef lint
1522 static int dummy; /* prevent ranlibs from complaining */
1523 #endif
1524 #endif /* STREAMSCONN */
1525