"SfR Fresh" - the SfR Freeware/Shareware Archive 
Member "xlab-0.8.3/scope.c" of archive xlab-0.8.3.tar.gz:
As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers.
Alternatively you can here view or download the uninterpreted source code file.
That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
1 /*
2 * $Id: scope.c,v 1.4 1998/07/24 11:59:17 marc Exp $
3 *
4 * A script program to store and replay X input events
5 *
6 * Adapted from "xscope"
7 * James Peterson, 1988
8 * (c) Copyright MCC, 1988
9 * (c) Copyright Oliver Jones, 1993
10 * (c) Copyright Marc Vertes 1996, 1997, 1998
11 *
12 */
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <sys/uio.h> /* for struct iovec, used by socket.h */
16 #include <sys/socket.h> /* for AF_INET, SOCK_STREAM, ... */
17 #include <sys/ioctl.h> /* for FIONCLEX, FIONBIO, ... */
18 #ifdef SVR4
19 #include <sys/filio.h>
20 #endif
21 #include <fcntl.h>
22 #include <netinet/in.h> /* struct sockaddr_in */
23 #include <netdb.h> /* struct servent * and struct hostent * */
24 #include <errno.h> /* for EINTR, EADDRINUSE, ... */
25 extern int errno;
26
27 typedef struct TypeDef *TYPE;
28
29 #include "scope.h"
30 #include "table11.h"
31 #include "common.h"
32 #include "server.h"
33 #include "record.h"
34 #include "y.tab.h"
35
36 /*
37 * we need a local X display connection to the server-under-test
38 * to allow various queries to go through.
39 * Hence, include the X definitions.
40 */
41 #include <X11/Xlib.h>
42 #include <X11/Xutil.h>
43
44 short debuglevel;
45 short Verbose; /* quiet (0) or increasingly verbose ( > 0) */
46 int ScopePort;
47 char *ScopeHost;
48
49 /* path name of file to record, if any */
50 char RecordFileName[MAXPATHLEN];
51
52 /* FILE id of file name to record, if any */
53 FILE *RecordFile = 0;
54
55 /* path name of file to play back, if any */
56 char PlaybackFileName[MAXPATHLEN];
57
58 /* FILE id of file name to play back, if any */
59 FILE *PlaybackFile = 0;
60
61 /* user requested playback */
62 #define PLAYBACK_INACTIVE 0
63 #define PLAYBACK_PENDING 1
64 #define PLAYBACK_ACTIVE 2
65 #define PLAYBACK_COMPLETE 3
66 long Playback = PLAYBACK_INACTIVE;
67
68 /* non-zero if user requested recording */
69 /* Record and Playback cannot both be nonzero */
70 long Record = 0;
71
72 /* number of seconds to wait after starting program to start playback */
73 long Wait = 15;
74
75 /* time dilation in percentage ... 200 means speed up x2 */
76 long TimeDilation = 100;
77
78 /* double click time in milliseconds */
79 long DoubleClickTime = 250;
80
81 /* grab timeout in seconds */
82 unsigned long int GrabTimeout = 30;
83
84 /* display connection */
85 Display *Dpy = 0;
86
87 /* playback error count */
88 unsigned long int Errorcount = 0;
89
90 #define DefaultPort 6000
91
92 char ServerHostName[255];
93 long ServerBasePort = DefaultPort;
94 long ServerInPort = 1;
95 long ServerOutPort = 0;
96 long ServerDisplay = 0;
97 char ScopeEnabled = 0;
98 char HandleSIGUSR1 = 0;
99
100 /*----------------------------------------------------------------------*/
101 short GetServerport()
102 {
103 short port;
104
105 enterprocedure("GetServerport");
106
107 port = ServerBasePort + ServerOutPort + ServerDisplay;
108 debug(4, (stderr, "Server service is on port %d\n", port));
109 return (port);
110 }
111
112 /*----------------------------------------------------------------------*/
113 short GetScopePort()
114 {
115 short port;
116
117 enterprocedure("GetScopePort");
118
119 port = ServerBasePort + ServerInPort + ServerDisplay;
120 debug(4, (stderr, "scope service is on port %d\n", port));
121 return (port);
122 }
123
124 /*----------------------------------------------------------------------*/
125 void Usage(xscript)
126 char *xscript;
127 {
128 fprintf(stderr, "Usage: %s [-r<script-file-to-record>]\n", xscript);
129 fprintf(stderr, " [-p<script-file-to-play-back>]\n");
130 fprintf(stderr, " [-w<seconds-to-wait-before-playback>]\n");
131 fprintf(stderr, " [-c<double-click-time>]\n");
132 fprintf(stderr, " [-t<time-contraction-percentage>]\n");
133 fprintf(stderr, " [-h<server-host>]\n");
134 fprintf(stderr, " [-i<in-port>]\n");
135 fprintf(stderr, " [-o<out-port>]\n");
136 fprintf(stderr, " [-d<display-number>]\n");
137 fprintf(stderr, " [-v<n>] -- verbose output\n");
138 fprintf(stderr, " [-q] -- quiet output\n");
139 fprintf(stderr, " [-D<debug-level>]\n");
140 fprintf(stderr, " [-S<n>] -- start/stop on SIGUSR1\n");
141 fprintf(stderr, " [-G<timeout>] -- grab timeout in seconds\n");
142
143 fprintf(stderr, "To record a session, do this:\n");
144 fprintf(stderr, " (1) setenv DISPLAY `hostname`:0\n");
145 fprintf(stderr, " (2) %s -rscript-file&\n", xscript);
146 fprintf(stderr, " (3) setenv DISPLAY `hostname`:1\n");
147 fprintf(stderr, " (4) run the program under test, and operate it.\n");
148 fprintf(stderr, "To play back a session at 50%% speed, do this:\n");
149 fprintf(stderr, " (1) setenv DISPLAY `hostname`:0\n");
150 fprintf(stderr, " (2) %s -t50 -pscript-file&\n", xscript);
151 fprintf(stderr, " (3) setenv DISPLAY `hostname`:1\n");
152 fprintf(stderr, " (4) run the program under test, sit back, and watch.\n");
153 exit(1);
154 }
155
156
157 /*----------------------------------------------------------------------*/
158 static char *xscript = NULL;
159
160 void ScanArgs(argc, argv)
161 int argc;
162 char **argv;
163 {
164 xscript = argv[0];
165
166 Verbose = 0 /* default verbose-ness level */ ;
167
168 /* Scan argument list */
169 while (--argc > 0) {
170 ++argv;
171 if (**argv == '-')
172 switch (*++*argv) {
173 /*
174 * debug levels:
175 * 2 - trace each procedure entry
176 * 4 - I/O, connections
177 * 8 - Scope internals
178 * 16 - Message protocol
179 * 32 - 64 - malloc
180 * 128 - 256 - really low level
181 */
182 case 'D':
183 debuglevel = atoi(++*argv);
184 if (debuglevel == 0)
185 debuglevel = 255;
186 debuglevel |= 1;
187 Verbose = 7;
188 debug(1, (stderr, "debuglevel = %d\n", debuglevel));
189 break;
190
191 case 'S':
192 HandleSIGUSR1 = 1;
193 ScopeEnabled = atoi(++*argv);
194 break;
195
196 case 'G':
197 GrabTimeout = atoi(++*argv);
198 if (GrabTimeout == 0)
199 GrabTimeout = 30;
200 break;
201
202 case 'q': /* quiet mode */
203 Verbose = 0;
204 debug(1, (stderr, "Verbose = %d\n", Verbose));
205 break;
206
207 case 'v': /* verbose mode */
208 Verbose = atoi(++*argv);
209 debug(1, (stderr, "Verbose = %d\n", Verbose));
210 break;
211
212 case 'o':
213 ServerOutPort = atoi(++*argv);
214 if (ServerOutPort <= 0)
215 ServerOutPort = 0;
216 debug(1, (stderr, "ServerOutPort = %ld\n", ServerOutPort));
217 break;
218
219 case 'd':
220 ServerDisplay = atoi(++*argv);
221 if (ServerDisplay <= 0)
222 ServerDisplay = 0;
223 debug(1, (stderr, "ServerDisplay=%ld\n", ServerDisplay));
224 break;
225
226 case 'i':
227 ServerInPort = atoi(++*argv);
228 if (ServerInPort <= 0)
229 ServerInPort = 0;
230 debug(1, (stderr, "ServerInPort = %ld\n", ServerInPort));
231 break;
232
233 case 'h':
234 if (++*argv != NULL && **argv != '\0') {
235 (void) strcpy(ServerHostName, OfficialName(*argv));
236 debug(1, (stderr, "ServerHostName=%s\n", ServerHostName));
237 } else {
238 /* -h by itself means print usage message */
239 Usage(xscript);
240 }
241 break;
242
243 case 'r':
244 if (Playback != PLAYBACK_INACTIVE) {
245 fprintf(stderr, "Cannot record and play back in same session.\n");
246 Usage(xscript);
247 }
248 if (++*argv != NULL && **argv != '\0')
249 (void) strcpy(RecordFileName, *argv);
250 debug(1, (stderr, "RecordFileName=%s\n", RecordFileName));
251
252 /* ensure we can open record file correctly */
253 RecordFile = fopen(RecordFileName, "w");
254 if (RecordFile == 0) {
255 perror(RecordFileName);
256 exit(1);
257 }
258 fclose(RecordFile);
259 RecordFile = 0;
260 Record = 1;
261 break;
262
263 case 'p':
264 if (Record) {
265 fprintf(stderr, "Cannot record and play back in same session.\n");
266 Usage(xscript);
267 }
268 if (++*argv != NULL && **argv != '\0')
269 (void) strcpy(PlaybackFileName, *argv);
270 debug(1, (stderr, "PlaybackFile<Name=%s\n", PlaybackFileName));
271
272 /* ensure we can open playback file correctly */
273 PlaybackFile = fopen(PlaybackFileName, "r");
274 if (PlaybackFile == 0) {
275 perror(PlaybackFileName);
276 exit(1);
277 }
278 fclose(PlaybackFile);
279 PlaybackFile = 0;
280 Playback = PLAYBACK_PENDING;
281 /* read playbackfile to to extract Windows info */
282 LoadWtab("PlaybackFileName");
283 break;
284
285 case 'w':
286 Wait = atoi(++*argv);
287 if (Wait <= 0)
288 Wait = 10;
289 debug(1, (stderr, "Wait = %ld\n", Wait));
290 break;
291
292 case 't':
293 TimeDilation = atoi(++*argv);
294 if (TimeDilation <= 0)
295 TimeDilation = 100;
296 debug(1, (stderr, "TimeDilation = %ld\n", TimeDilation));
297 break;
298
299 case 'c':
300 DoubleClickTime = atoi(++*argv);
301 if (DoubleClickTime <= 0)
302 DoubleClickTime = 250;
303 debug(1, (stderr, "DoubleClickTime = %ld\n", DoubleClickTime));
304 break;
305
306 default:
307 fprintf(stderr, "Unknown option %c\n", **argv);
308 Usage(xscript);
309 break;
310
311 } else {
312 /* file argument to scope -- error */
313 Usage(xscript);
314 }
315 }
316
317 /* check for different port numbers or different machines */
318 if (ServerInPort == ServerOutPort)
319 if (ServerHostName[0] == '\0') {
320 fprintf(stderr, "Can't have xlab on same port as server (%ld)\n",
321 ServerInPort);
322 Usage(xscript);
323 }
324 }
325
326
327 /*----------------------------------------------------------------------*/
328 int main(argc, argv)
329 int argc;
330 char **argv;
331 {
332 /* grab input args */
333 ScanArgs(argc, argv);
334
335 /* initialize cross table of FDinfo */
336 initFDbynum();
337
338 /* initialize the file-descriptor-handling system */
339 InitializeFD();
340
341 /* initialize the symbol tables, etc, for X */
342 InitializeX11();
343
344 /* set up input stuff */
345 SetUpStdin();
346 SetUpXDisplay();
347 SetUpConnectionSocket(GetScopePort());
348 SetSignalHandling();
349
350 MainLoop();
351 return (0);
352 }
353
354
355 /*----------------------------------------------------------------------*/
356 char *mystring;
357
358 void ReadStdin(fd)
359 FD fd;
360 {
361 long n;
362 char in_buf[2048];
363 extern FILE *yyin;
364 extern int yyparse();
365 extern int yyrestart();
366
367 enterprocedure("ReadStdin");
368 n = read(fd, in_buf, 2048);
369 in_buf[n] = 0;
370 debug(4, (stderr, "read %ld bytes from stdin\n", n));
371 if (n == 0) {
372 NotUsingFD(fileno(stdin));
373 CreateTimer(2000, (void (*)()) SetUpStdin, (void *) fd);
374 return;
375 }
376 mystring = in_buf;
377 yyparse();
378 yyrestart(yyin);
379 }
380
381 /*----------------------------------------------------------------------*/
382 void SetUpStdin()
383 {
384 enterprocedure("SetUpStdin");
385 UsingFD(fileno(stdin), (int (*)()) ReadStdin);
386 }
387
388 /*----------------------------------------------------------------------*/
389 void ReportAndExit()
390 {
391
392 if (Errorcount > 0 && Playback != PLAYBACK_INACTIVE) {
393 fprintf(stderr, "xlab: Playback summary\n");
394 fprintf(stderr, " %ld errors encountered during playback\n", Errorcount);
395 exit(2);
396 }
397 exit(0);
398 }
399
400 /*----------------------------------------------------------------------*/
401 /*
402 here is where we would add code to allow control from
403 the keyboard. We would want to read a command and
404 interpret it. Possibilties:
405
406 (a) verbose level setting
407 (b) reset time
408 (c) save X requests to a file.
409 (d) replay X requests from a file.
410 (e) allow fake events, errors to be generated.
411 */
412
413 /*
414 xscope is really meant to look at one client at a time. However,
415 it can easily handle multiple clients and servers. To do so,
416 we need to have a pair of FDs: one for the client and one for the
417 server for that client. If either goes away, so does the other.
418 We need to be able to identify the other FD of a pair, so that if
419 we get input from one, we can write it to the other.
420 */
421
422 struct fdinfo {
423 Boolean Server;
424 long ClientNumber;
425 FD pair;
426 };
427
428 static long ClientNumber = 0;
429 static long ClientsConnected = 0;
430 struct fdinfo FDinfo[StaticMaxFD];
431
432 /* table to retrieve the client from the ClientNumber field of FDinfo */
433 FD FDbynum[StaticMaxFD];
434
435 /*----------------------------------------------------------------------*/
436 void SetUpPair(client, server)
437 FD client;
438 FD server;
439 {
440 if (client >= 0) {
441 ClientNumber += 1;
442 ClientsConnected += 1;
443 FDinfo[client].Server = false;
444 FDinfo[client].pair = server;
445 FDinfo[client].ClientNumber = ClientNumber;
446 if (server >= 0) {
447 FDinfo[server].Server = true;
448 FDinfo[server].pair = client;
449 FDinfo[server].ClientNumber = FDinfo[client].ClientNumber;
450 FDbynum[ClientNumber] = server;
451 }
452 } else if (server >= 0) {
453 (void) close(server);
454 NotUsingFD(server);
455 }
456 }
457
458 /*----------------------------------------------------------------------*/
459 void CloseConnection(fd)
460 FD fd;
461 {
462 debug(4, (stderr, "close %d and %d\n", fd, FDPair(fd)));
463 StopClientConnection(ServerHalf(fd));
464 StopServerConnection(ClientHalf(fd));
465
466 (void) close(fd);
467 NotUsingFD(fd);
468 (void) close(FDPair(fd));
469 NotUsingFD(FDPair(fd));
470 ClientsConnected -= 1;
471 }
472
473 /*----------------------------------------------------------------------*/
474 FD FDPair(fd)
475 FD fd;
476 {
477 return (FDinfo[fd].pair);
478 }
479
480 /*----------------------------------------------------------------------*/
481 FD ClientHalf(fd)
482 FD fd;
483 {
484 if (FDinfo[fd].Server)
485 return (FDinfo[fd].pair);
486 return (fd);
487 }
488
489 /*----------------------------------------------------------------------*/
490 FD ServerHalf(fd)
491 FD fd;
492 {
493 if (FDinfo[fd].Server)
494 return (fd);
495 return (FDinfo[fd].pair);
496 }
497
498 /*----------------------------------------------------------------------*/
499 char *ClientName(fd)
500 FD fd;
501 {
502 static char name[12];
503
504 (void) sprintf(name, " %ld", FDinfo[fd].ClientNumber);
505 return (name);
506 }
507
508 /*----------------------------------------------------------------------*/
509 void initFDbynum()
510 {
511 long i;
512 for (i = 0; i < StaticMaxFD; i++)
513 FDbynum[i] = -1;
514 }
515
516 /*----------------------------------------------------------------------*/
517 extern struct WinTab wintab[MAXWTAB];
518 extern struct WinAlias winalias[MAXWTAB];
519
520 void initwintab()
521 {
522 int i;
523
524 for (i = 0; i < MAXWTAB; i++) {
525 wintab[i].wid = 0;
526 wintab[i].parent = 0;
527 wintab[i].newid = 0;
528 wintab[i].newpar = 0;
529 wintab[i].x = -1;
530 wintab[i].y = -1;
531 wintab[i].width = -1;
532 wintab[i].height = -1;
533 wintab[i].delflag = 0;
534 winalias[i].wid = 0;
535 winalias[i].alias = 0;
536 }
537 }
538
539 /*----------------------------------------------------------------------*/
540 FD FDClientFromNumber(clientNb)
541 long clientNb;
542 {
543 return FDbynum[clientNb];
544 /*
545 long i;
546
547 for (i = 0; i < StaticMaxFD; i++) {
548 if ((FDinfo[i].ClientNumber == clientNb) && (FDinfo[i].Server == false))
549 return i;
550 }
551 return -1;
552 */
553 }
554
555 /*----------------------------------------------------------------------*/
556 long NumberFD(fd)
557 FD fd;
558 {
559 return FDinfo[fd].ClientNumber;
560 }
561
562
563 /*----------------------------------------------------------------------*/
564 /* It's possible for a write syscall to fail with
565 EWOULDBLOCK. In this case, we want to do a select
566 until the file descriptor is writeable once again */
567
568 static void WaitUntilWriteable(fd)
569 FD fd;
570 {
571 long int rfds, wfds, xfds;
572 short int nfds;
573 /* assert (fd < 32); */
574 rfds = 0;
575 wfds = 1 << fd;
576 xfds = 0;
577 debug(128, (stderr, "select %d, wfds = 0%lo\n", fd + 1, wfds));
578 nfds = select(fd + 1, (fd_set *) & rfds, (fd_set *) & wfds, (fd_set *) & xfds,
579 (struct timeval *) NULL);
580 debug(128, (stderr, "select nfds = 0%o, wfds 0%lo\n", nfds, wfds));
581 }
582
583
584 /*----------------------------------------------------------------------*/
585 /* when we get data from a client, we read it in, copy it to the
586 * server for this client, then dump it to the client. Note, we don't
587 * have to have a server, if there isn't one.
588 */
589 void DataFromClient(fd)
590 FD fd;
591 {
592 unsigned char buf[2048];
593 long n;
594 FD ServerFD;
595
596 /*MV enterprocedure("DataFromClient"); */
597 n = read(fd, (char *) buf, 2048);
598 debug(4, (stderr, "read %ld bytes from Client%s\n", n, ClientName(fd)));
599 if (n < 0 && errno == ECONNRESET)
600 n = 0;
601 if (n < 0) {
602 PrintTime();
603 perror("Client --> read error:");
604 CloseConnection(fd);
605 return;
606 }
607 if (n == 0) {
608 if (ScopeEnabled) {
609 PrintTime();
610 fprintf(stdout, "Client%s --> EOF\n", ClientName(fd));
611 }
612 if (RecordFile) {
613 fflush(RecordFile);
614 if (ClientsConnected == 0) {
615 fclose(RecordFile);
616 RecordFile = 0;
617 }
618 }
619 CloseConnection(fd);
620
621 /*
622 if ((Record || (Playback != PLAYBACK_INACTIVE)) && (ClientsConnected == 0))
623 ReportAndExit ();
624 */
625 return;
626 }
627 ServerFD = FDPair(fd);
628 if (ServerFD < 0) {
629 ServerFD = ConnectToServer(false);
630 SetUpPair(fd, ServerFD);
631 }
632 /* write bytes from client to server, allow for server to fail */
633 if (ServerFD >= 0) {
634 long BytesToWrite = n;
635 unsigned char *p = buf;
636
637 while (BytesToWrite > 0) {
638 int n1 = write(ServerFD, (char *) p, (int) BytesToWrite);
639 debug(4, (stderr, "write %d bytes to Server%s\n", n1, ClientName(fd)));
640 if (n1 < 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) {
641 if (errno == EAGAIN)
642 sleep(1);
643 WaitUntilWriteable(ServerFD);
644 n1 = 0;
645 }
646 if (n1 >= 0) {
647 BytesToWrite -= n1;
648 p += n1;
649 } else {
650 perror("Error on write to Server");
651 CloseConnection(fd);
652 BytesToWrite = 0;
653 }
654 }
655 }
656 /* also report the bytes to standard out */
657 ReportFromClient(fd, buf, n);
658 }
659
660 /*----------------------------------------------------------------------*/
661 /* push bytes from server out to client */
662 void WriteToClient(fd, buf, n)
663 FD fd;
664 unsigned char *buf;
665 int n;
666 {
667 FD ClientFD = FDPair(fd);
668 long BytesToWrite = n;
669 unsigned char *p = buf;
670
671 while (BytesToWrite > 0) {
672 int n1 = write(ClientFD, (char *) p, (int) BytesToWrite);
673 debug(4, (stderr, "write %d bytes to Client%s\n", n1, ClientName(fd)));
674
675 if (n1 < 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) {
676 if (errno == EAGAIN)
677 sleep(1);
678 WaitUntilWriteable(ClientFD);
679 n1 = 0;
680 }
681 if (n1 >= 0) {
682 BytesToWrite -= n1;
683 p += n1;
684 } else {
685 perror("Error on write to Client");
686 CloseConnection(fd);
687 BytesToWrite = 0;
688 }
689 }
690 }
691
692 /*----------------------------------------------------------------------*/
693 /* similar situation for the server, but note that if there is no client,
694 * we close the connection down -- don't need a server with no client.
695 */
696 void DataFromServer(fd)
697 FD fd;
698 {
699 unsigned char buf[2048];
700 long n;
701 FD ClientFD;
702
703 /*MV enterprocedure("DataFromServer"); */
704 n = read(fd, (char *) buf, 2048);
705 debug(4, (stderr, "read %ld bytes from Server%s\n", n, ClientName(fd)));
706 if (n < 0) {
707 PrintTime();
708 perror("read error <- Server");
709 CloseConnection(fd);
710 return;
711 }
712 if (n == 0) {
713 if (ScopeEnabled) {
714 PrintTime();
715 fprintf(stdout, "EOF <-- Server%s\n", ClientName(fd));
716 }
717 if (RecordFile) {
718 fflush(RecordFile);
719 if (ClientsConnected == 0) {
720 fclose(RecordFile);
721 RecordFile = 0;
722 }
723 }
724 CloseConnection(fd);
725
726 /*
727 if ((Record || (Playback != PLAYBACK_INACTIVE)) && (ClientsConnected == 0))
728 ReportAndExit ();
729 */
730 return;
731 }
732 ClientFD = FDPair(fd);
733 if (ClientFD < 0) {
734 CloseConnection(fd);
735 return;
736 }
737 if (Playback == PLAYBACK_INACTIVE) {
738 /*
739 * if we're not playing stuff back from a file,
740 * write bytes from server to client, allow for client to fail.
741 * Note...if we ARE playing server stuff back, we need to
742 * crack the protocol first, because we don't pass throug
743 * all events from the server; only those which don't
744 * come from the playback file.
745 */
746 WriteToClient(fd, buf, n);
747 }
748 /* also report the bytes to standard out */
749 ReportFromServer(fd, buf, n);
750 }
751
752
753
754 /*----------------------------------------------------------------------*/
755 /* Create New Connection to a client program and to Server */
756
757 #ifndef linux
758 static int ON = 1 /* used in ioctl */ ;
759 #endif
760
761 void NewConnection(fd)
762 FD fd;
763 {
764 FD ServerFD = -1;
765 FD ClientFD = -1;
766
767 ClientFD = ConnectToClient(fd);
768 ServerFD = ConnectToServer(true);
769 SetUpPair(ClientFD, ServerFD);
770 }
771
772 /*----------------------------------------------------------------------*/
773 FD ConnectToClient(ConnectionSocket)
774 FD ConnectionSocket;
775 {
776 FD ClientFD;
777 struct sockaddr_in from;
778 int len = sizeof(from);
779
780 enterprocedure("ConnectToClient");
781
782 ClientFD = accept(ConnectionSocket, (struct sockaddr *) &from, &len);
783 debug(4, (stderr, "Connect To Client: FD %d\n", ClientFD));
784 if (ClientFD < 0 && errno == EWOULDBLOCK) {
785 debug(4, (stderr, "Almost blocked accepting FD %d\n", ClientFD));
786 panic("Can't connect to Client");
787 }
788 if (ClientFD < 0) {
789 debug(4, (stderr, "NewConnection: error %d\n", errno));
790 panic("Can't connect to Client");
791 }
792 UsingFD(ClientFD, (int (*)()) DataFromClient);
793 #ifdef FD_CLOEXEC
794 (void) fcntl(ClientFD, F_SETFD, FD_CLOEXEC);
795 #else
796 (void) ioctl(ClientFD, FIOCLEX, 0);
797 #endif
798 /* ultrix reads hang on Unix sockets, hpux reads fail */
799 #if defined(O_NONBLOCK) && (!defined(ultrix) && !defined(hpux))
800 (void) fcntl(ClientFD, F_SETFL, O_NONBLOCK);
801 #else
802 #ifdef FIOSNBIO
803 ioctl(ClientFD, FIOSNBIO, &ON);
804 #else
805 (void) fcntl(ClientFD, F_SETFL, FNDELAY);
806 #endif
807 #endif
808 StartClientConnection(ClientFD);
809 return (ClientFD);
810 }
811
812 /*----------------------------------------------------------------------*/
813 FD ConnectToServer(report)
814 Boolean report;
815 {
816 FD ServerFD;
817 struct sockaddr_in sin;
818 struct hostent *hp;
819 short port;
820 int reuse_addr = 1;
821 #ifndef SO_DONTLINGER
822 struct linger linger;
823 #endif /* SO_DONTLINGER */
824
825 enterprocedure("ConnectToServer");
826
827 /* establish a socket to the name server for this host */
828 bzero((char *) &sin, sizeof(sin));
829 ServerFD = socket(AF_INET, SOCK_STREAM, 0);
830 if (ServerFD < 0) {
831 perror("socket() to Server failed");
832 debug(1, (stderr, "socket failed\n"));
833 panic("Can't open connection to Server");
834 }
835 (void) setsockopt(ServerFD, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, 0);
836 #ifndef linux
837 (void) setsockopt(ServerFD, SOL_SOCKET, SO_USELOOPBACK, (char *) NULL, 0);
838 #endif
839 #ifdef SO_DONTLINGER
840 (void) setsockopt(ServerFD, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0);
841 #else /* SO_DONTLINGER */
842 linger.l_onoff = 0;
843 linger.l_linger = 0;
844 (void) setsockopt(ServerFD, SOL_SOCKET, SO_LINGER, (char *) &linger, sizeof linger);
845 #endif /* SO_DONTLINGER */
846
847 /* determine the host machine for this process */
848 if (ServerHostName[0] == '\0')
849 (void) gethostname(ServerHostName, sizeof(ServerHostName));
850 debug(4, (stderr, "try to connect on %s\n", ServerHostName));
851
852 hp = gethostbyname(ServerHostName);
853 if (hp == 0) {
854 perror("gethostbyname failed");
855 debug(1, (stderr, "gethostbyname failed for %s\n", ServerHostName));
856 panic("Can't open connection to Server");
857 }
858 sin.sin_family = AF_INET;
859 bcopy((char *) hp->h_addr, (char *) &sin.sin_addr, hp->h_length);
860 port = GetServerport();
861
862 if (port == ScopePort
863 && strcmp(ServerHostName, ScopeHost) == 0) {
864 char error_message[100];
865 (void) sprintf(error_message, "Trying to attach to myself: %s,%d\n",
866 ServerHostName, sin.sin_port);
867 panic(error_message);
868 }
869 sin.sin_port = htons(port);
870
871 /* ******************************************************** */
872 /* try to connect to Server */
873
874 if (connect(ServerFD, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
875 debug(4, (stderr, "connect returns errno of %d\n", errno));
876 if (errno != 0)
877 if (report)
878 perror("connect");
879 switch (errno) {
880 case ECONNREFUSED:
881 /* experience says this is because there is no Server
882 to connect to */
883 (void) close(ServerFD);
884 debug(1, (stderr, "No Server\n"));
885 if (report)
886 warn("Can't open connection to Server");
887 return (-1);
888
889 default:
890 (void) close(ServerFD);
891 panic("Can't open connection to Server");
892 }
893 }
894 debug(4, (stderr, "Connect To Server: FD %d\n", ServerFD));
895 if (ServerFD >= 0) {
896 UsingFD(ServerFD, (int (*)()) DataFromServer);
897 StartServerConnection(ServerFD);
898 }
899 return (ServerFD);
900 }