diff options
Diffstat (limited to 'scope.c')
-rw-r--r-- | scope.c | 421 |
1 files changed, 383 insertions, 38 deletions
@@ -23,10 +23,46 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * + * * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, and/or sell copies of the Software, and to permit persons + * to whom the Software is furnished to do so, provided that the above + * copyright notice(s) and this permission notice appear in all copies of + * the Software and that both the above copyright notice(s) and this + * permission notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * of the copyright holder. + * ***************************************************** */ #include "scope.h" +#include <unistd.h> +#include <sys/param.h> + +#ifdef SYSV +#define bzero(s,l) memset(s, 0, l) +#define bcopy(s,d,l) memmove(d,s,l) +#endif + #include <sys/uio.h> /* for struct iovec, used by socket.h */ #include <sys/socket.h> /* for AF_INET, SOCK_STREAM, ... */ #include <sys/ioctl.h> /* for FIONCLEX, FIONBIO, ... */ @@ -40,6 +76,7 @@ #include <errno.h> /* for EINTR, EADDRINUSE, ... */ extern int errno; + extern InitializePEX(); /* ********************************************** */ /* */ @@ -47,12 +84,38 @@ extern InitializePEX(); #define DefaultPort 6000 -char ServerHostName[255]; -char AudioServerHostName[255]; -long ServerBasePort = DefaultPort; -long ServerInPort = 1; -long ServerOutPort = 0; -long ServerDisplay = 0; + char ServerHostName[MAXHOSTNAMELEN]; + char AudioServerHostName[MAXHOSTNAMELEN]; + long ServerBasePort = DefaultPort; +static long ServerInPort = 1; +static long ServerOutPort = 0; +static long ServerDisplay = 0; + +#ifdef USE_XTRANS +#undef DNETCONN +#undef DNETSVR4 +#endif + +#ifdef DNETCONN +#include <X11/dni.h> +#include <sys/fcntl.h> +int decnet_in = 0; +int decnet_out = 0; +int decnet_server = 0; +#endif +#ifdef DNETSVR4 +#include <X11/dni8.h> +extern struct hostent *(*dnet_gethostbyname)(); +extern int (*dnet_gethostname)(); +short initialize_libdni(); +int decnet_in = 0; +int decnet_out = 0; +int decnet_server = 0; +#endif + +static FD ConnectToClient(FD ConnectionSocket); +static void SetUpStdin(void); + long TranslateText = 0; char ScopeEnabled = 1; char HandleSIGUSR1 = 0; @@ -381,7 +444,7 @@ setBreakPoint () BreakPoint = b; for (fd = 0; fd < HighestFD; fd++) { - extern DataFromClient(); + static void DataFromClient(FD fd); if (FDD[fd].Busy && FDD[fd].InputHandler == DataFromClient) { @@ -606,23 +669,35 @@ CMDAudio (argc, argv) /* */ /* ********************************************** */ -short GetServerport () +short GetServerport () { short port; enterprocedure("GetServerport"); +#if defined(DNETCONN) || defined(DNETSVR4) + if (decnet_server) { + port = ServerDisplay + ServerOutPort; + return(port); + } +#endif port = ServerBasePort + ServerOutPort + ServerDisplay; debug(4,(stderr, "Server service is on port %d\n", port)); return(port); } -short GetScopePort () +static short GetScopePort () { short port; enterprocedure("GetScopePort"); +#if defined(DNETCONN) || defined(DNETSVR4) + if (decnet_in) { + port = ServerInPort + ServerDisplay; + return(port); + } +#endif port = ServerBasePort + ServerInPort + ServerDisplay; debug(4,(stderr, "scope service is on port %d\n", port)); return(port); @@ -632,6 +707,7 @@ short GetScopePort () /* */ /* ********************************************** */ +static void Usage() { fprintf(stderr, "Usage: xscope\n"); @@ -640,6 +716,9 @@ Usage() fprintf(stderr, " [-o<out-port>]\n"); fprintf(stderr, " [-d<display-number>]\n"); fprintf(stderr, " [-v<n>] -- verbose output\n"); +#ifdef RAW_MODE + fprintf(stderr, " [-r] -- raw output\n"); +#endif fprintf(stderr, " [-a<n>] -- audio verbose output\n"); fprintf(stderr, " [-q] -- quiet output\n"); fprintf(stderr, " [-D<debug-level>]\n"); @@ -649,14 +728,19 @@ Usage() } -char *OfficialName(); /* forward type declaration */ - +static void ScanArgs(argc, argv) int argc; char **argv; { +#if defined(DNETCONN) || defined(DNETSVR4) + char *ss; +#endif XVerbose = 1 /* default verbose-ness level */; NasVerbose = 1; +#ifdef RAW_MODE + Raw = 0 ; +#endif /* Scan argument list */ while (--argc > 0) @@ -692,6 +776,13 @@ ScanArgs(argc, argv) debug(1,(stderr, "Verbose = %d\n", XVerbose)); break; +#ifdef RAW_MODE + case 'r': /* raw mode */ + Raw = 1 ; + debug(1,(stderr, "Raw = %d\n", Raw)); + break; +#endif + case 'v': /* verbose mode */ XVerbose = atoi(++*argv); debug(1,(stderr, "Verbose = %d\n", XVerbose)); @@ -712,6 +803,12 @@ ScanArgs(argc, argv) break; case 'i': +#if defined(DNETCONN) || defined(DNETSVR4) + if (ss = (char *)strchr(*argv,':')) { + decnet_in = 1; + *ss = NULL; + } +#endif ServerInPort = atoi(++*argv); if (ServerInPort <= 0) ServerInPort = 0; @@ -719,8 +816,17 @@ ScanArgs(argc, argv) break; case 'h': - if (++*argv != NULL && **argv != '\0') - (void)strcpy(ServerHostName, OfficialName(*argv)); +#if defined(DNETCONN) || defined(DNETSVR4) + if (ss = (char *)strchr(*argv,':')) { + decnet_server = 1; + *ss = NULL; + strcpy(ServerHostName,++*argv); + break; + } +#endif + if (++*argv != NULL && **argv != '\0' + && (strlen(*argv) < sizeof(ServerHostName))) + strcpy(ServerHostName, *argv); debug(1,(stderr, "ServerHostName=%s\n", ServerHostName)); break; @@ -739,7 +845,7 @@ ScanArgs(argc, argv) case 'n': /* NAS server host */ if (++*argv != NULL && **argv != '\0') - (void)strcpy(AudioServerHostName, OfficialName(*argv)); + (void)strcpy(AudioServerHostName, *argv); debug(1,(stderr, "AudioServerHostName=%s\n", AudioServerHostName)); break; case 't': @@ -775,7 +881,6 @@ ScanArgs(argc, argv) /* */ /* ********************************************** */ -int NewConnection (); int NewAudio (); main(argc, argv) @@ -791,14 +896,22 @@ main(argc, argv) InitializePEX(); #endif SetUpStdin(); +#if defined(DNETCONN) || defined(DNETSVR4) + if (decnet_in) + SetUpDECnetConnection(GetScopePort(), NewConnection); + else + SetUpConnectionSocket(GetScopePort(), NewConnection); +#else SetUpConnectionSocket(GetScopePort(), NewConnection); if (DoAudio) SetUpConnectionSocket (GetScopePort() + 2000, NewAudio); SetSignalHandling(); +#endif - MainLoop(); + return MainLoop(); } +void TimerExpired() { debug(16,(stderr, "Timer tick\n")); @@ -820,6 +933,7 @@ TimerExpired() (e) allow fake events, errors to be generated. */ +static void ReadStdin(fd) FD fd; { @@ -831,10 +945,11 @@ ReadStdin(fd) debug(4,(stderr, "read %d bytes from stdin\n", n)); } +static void SetUpStdin() { enterprocedure("SetUpStdin"); - UsingFD(fileno(stdin), ReadStdin, (int (*)()) NULL); + UsingFD(fileno(stdin), ReadStdin, (int (*)()) NULL, NULL); } /* ************************************************************ */ @@ -854,6 +969,7 @@ SetUpStdin() static long clientNumber = 0; struct fdinfo FDinfo[StaticMaxFD]; +void SetUpPair(client, server) FD client; FD server; @@ -879,7 +995,7 @@ SetUpPair(client, server) } else if (server >= 0) { - (void)close(server); + close(server); NotUsingFD(server); } } @@ -903,6 +1019,7 @@ ResetPair (client, server) } } +static void CloseConnection(fd) FD fd; { @@ -911,9 +1028,14 @@ CloseConnection(fd) StopClientConnection(ServerHalf(fd)); StopServerConnection(ClientHalf(fd)); - (void)close(fd); +#ifdef USE_XTRANS + _X11TransClose(GetXTransConnInfo(fd)); + _X11TransClose(GetXTransConnInfo(FDPair(fd))); +#else + close(fd); + close(FDPair(fd)); +#endif NotUsingFD(fd); - (void)close(FDPair(fd)); NotUsingFD(FDPair(fd)); if (TerminateClose) exit (0); @@ -948,6 +1070,8 @@ char *ClientName (fd) { static char name[12]; + if (clientNumber <= 1) + return(""); (void)sprintf(name, " %d", FDinfo[fd].ClientNumber); return(name); } @@ -967,6 +1091,7 @@ int ClientNumber (fd) * Block reads from the sender until the receiver gets all of the * data */ +void FlushFD (fd) FD fd; { @@ -1023,6 +1148,7 @@ FlushFD (fd) server for this client, then dump it to the client. Note, we don't have to have a server, if there isn't one. */ +static void DataFromClient(fd) FD fd; { @@ -1076,6 +1202,7 @@ DataFromClient(fd) /* similar situation for the server, but note that if there is no client, we close the connection down -- don't need a server with no client. */ +static void DataFromServer(fd) FD fd; { @@ -1125,34 +1252,104 @@ DataFromServer(fd) /* */ /* ************************************************************ */ +#include <sys/types.h> /* needed by sys/socket.h and netinet/in.h */ +#include <sys/uio.h> /* for struct iovec, used by socket.h */ +#include <sys/socket.h> /* for AF_INET, SOCK_STREAM, ... */ +#include <sys/ioctl.h> /* for FIONCLEX, FIONBIO, ... */ +#include <netinet/in.h> /* struct sockaddr_in */ +#include <netdb.h> /* struct servent * and struct hostent * */ +#include <errno.h> /* for EINTR, EADDRINUSE, ... */ +extern int errno; + static int ON = 1 /* used in ioctl */ ; +void NewConnection(fd) FD fd; { FD ServerFD = -1; FD ClientFD = -1; +#ifdef DNETCONN + if (decnet_in) + ClientFD = ConnectToDECnetClient(fd); + else + ClientFD = ConnectToClient(fd); + if (decnet_server) + ServerFD = ConnectToDECnetServer(true); + else + ServerFD = ConnectToServer(true); +#endif +#ifdef DNETSVR4 + ClientFD = ConnectToClient(fd); + if (decnet_server) { + if (!initialize_libdni()) { + fprintf(stderr,"Unable to open libdni.so\n"); + exit(0); + } + ServerFD = ConnectToDECnetSVR4Server(true); + } + else + ServerFD = ConnectToServer(true); +#endif +#if !(defined(DNETCONN)) && !(defined(DNETSVR4)) ClientFD = ConnectToClient(fd); ServerFD = ConnectToServer(true); + +#endif SetUpPair(ClientFD, ServerFD); } /* ************************************************************ */ -FD ConnectToClient(ConnectionSocket) +static FD ConnectToClient(ConnectionSocket) FD ConnectionSocket; { FD ClientFD; + XtransConnInfo trans_conn = NULL; +#ifdef USE_XTRANS + XtransConnInfo listen_conn; + int status; +#else + struct sockaddr_in from; + int len = sizeof (from); +#endif + + enterprocedure("ConnectToClient"); + +#ifdef USE_XTRANS + listen_conn = GetXTransConnInfo(ConnectionSocket); + if ((trans_conn = _X11TransAccept (listen_conn, &status)) == NULL) { + debug(4,(stderr, "Failed to accept connection\n")); + return -1; + } + _X11TransSetOption(trans_conn, TRANS_NONBLOCKING, 1); + ClientFD = _X11TransGetConnectionNumber(trans_conn); +#else ClientFD = AcceptConnection(ConnectionSocket); - UsingFD(ClientFD, DataFromClient, FlushFD); +#endif + debug(4,(stderr, "Connect To Client: FD %d\n", ClientFD)); + if (ClientFD < 0 && errno == EWOULDBLOCK) + { + debug(4,(stderr, "Almost blocked accepting FD %d\n", ClientFD)); + panic("Can't connect to Client"); + } + if (ClientFD < 0) + { + debug(4,(stderr, "NewConnection: error %d\n", errno)); + panic("Can't connect to Client"); + } + + UsingFD(ClientFD, DataFromClient, FlushFD, trans_conn); +#ifndef USE_XTRANS + ioctl(ClientFD, FIOCLEX, 0); + ioctl(ClientFD, FIONBIO, &ON); +#endif StartClientConnection(ClientFD); return(ClientFD); } - - /* ************************************************************ */ /* */ /* */ @@ -1164,32 +1361,180 @@ FD ConnectToServer(report) Boolean report; { FD ServerFD; - ServerFD = MakeConnection (ServerHostName, GetServerport (), report); + XtransConnInfo trans_conn = NULL; /* transport connection object */ + short port; + + enterprocedure("ConnectToServer"); + + port = GetServerport (); + + if (port == ScopePort && + ((ServerHostName[0] == '\0') || strcmp(ServerHostName, ScopeHost) == 0)) + { + char error_message[100]; + sprintf(error_message, "Trying to attach to myself: %s,%d\n", + ServerHostName, port); + panic(error_message); + } + + ServerFD = MakeConnection (ServerHostName, port, report, &trans_conn); + + debug(4,(stderr, "Connect To Server: FD %d\n", ServerFD)); if (ServerFD >= 0) { - UsingFD(ServerFD, DataFromServer, FlushFD); + UsingFD(ServerFD, DataFromServer, FlushFD, trans_conn); StartServerConnection(ServerFD); } return(ServerFD); } +#ifdef DNETSVR4 +FD ConnectToDECnetSVR4Server(report) + Boolean report; +{ + FD ServerFD; + struct sockaddr_dn sdn; + struct hostent *hp; + + enterprocedure("ConnectToServer"); + + /* establish a socket to the name server for this host */ + ServerFD = socket(AF_DECnet, SOCK_STREAM, 0); + if (ServerFD < 0) + { + perror("socket() to Server failed"); + debug(1,(stderr, "socket failed\n")); + panic("Can't open connection to Server"); + } + (void) setsockopt(ServerFD, SOL_SOCKET, SO_REUSEADDR, (char *) NULL, 0); + (void) setsockopt(ServerFD, SOL_SOCKET, SO_USELOOPBACK,(char *) NULL, 0); + /* determine the host machine for this process */ + initialize_libdni(); + if (ServerHostName[0] == '\0') + (dnet_gethostname)(ServerHostName); + debug(4,(stderr, "try to connect on %s\n", ServerHostName)); + + hp = (struct hostent *)(dnet_gethostbyname)(ServerHostName); + if (hp == 0) + { + perror("gethostbyname failed"); + debug(1,(stderr, "gethostbyname failed for %s\n", ServerHostName)); + panic("Can't open connection to Server"); + } + + sdn.sdn_family = AF_DECnet; + sdn.sdn_format = DNADDR_FMT1; + sdn.sdn_port = 0; + sprintf (sdn.sdn_name, "X$X%d", GetServerport() ); + sdn.sdn_namelen = strlen(sdn.sdn_name); + sdn.sdn_addr = *(u_short *)hp->h_addr_list[0]; + + /* ******************************************************** */ + /* try to connect to Server */ + + if (connect(ServerFD, (struct sockaddr *)&sdn, sizeof(sdn)) < 0) + { + debug(4,(stderr, "connect returns errno of %d\n", errno)); + if (errno != 0) + if (report) + perror("connect"); + switch (errno) + { + case ECONNREFUSED: + /* experience says this is because there is no Server + to connect to */ + close(ServerFD); + debug(1,(stderr, "No Server\n")); + if (report) + warn("Can't open connection to Server"); + return(-1); + + default: + close(ServerFD); + panic("Can't open connection to Server"); + } + } + + debug(4,(stderr, "Connect To Server: FD %d\n", ServerFD)); + if (ServerFD >= 0) + { + UsingFD(ServerFD, DataFromServer, FlushFD, NULL); + StartServerConnection(ServerFD); + } + return(ServerFD); +} +#endif /* ********************************************** */ /* */ /* ********************************************** */ -char *OfficialName(name) -char *name; +#ifdef DNETCONN +FD ConnectToDECnetClient(fd) + FD fd; { - struct hostent *HostEntry; - - HostEntry = gethostbyname(name); - if (HostEntry == NULL) - { - perror("gethostbyname"); - exit(-1); - } - debug(4,(stderr, "Official name of %s is %s\n", name, HostEntry->h_name)); - return(HostEntry->h_name); + struct ses_io_type sesopts; + static SessionData sd= {0, {0, ""}}; + + if (ioctl(fd, SES_ACCEPT, &sd) < 0) { + fprintf(stderr,"xscope: dni: SES_ACCEPT failed\n"); + exit(-1); + } + UsingFD(fd, DataFromClient, NULL, NULL); + StartClientConnection(fd); + /* unlike sockets, dni consumes the fd on which it was listening */ + /* in order to accept new logical link requests using the same name */ + /* we must re-open the logical link device and re-supply the */ + /* appropriate access control information */ + + SetUpDECnetConnection(GetScopePort()); + + return(fd); } + +FD ConnectToDECnetServer(report) + Boolean report; +{ + FD fd; + OpenBlock opblk; + struct ses_io_type sesopts; + struct nodeent *np; + + if ((fd = open("/dev/dni", O_RDWR)) < 0) { + fprintf(stderr,"xscope: dni: open failed\n"); + exit(-1); + } + if (ioctl(fd, SES_GET_LINK, 0)) { + fprintf(stderr,"xscope: dni: can't get link\n"); + exit(-1); + } + + /* set nonblocking here since dni can't handle fcntls */ + sesopts.io_flags = SES_IO_NBIO; + sesopts.io_io_signal = sesopts.io_int_signal = 0; + + if (ioctl(fd, SES_IO_TYPE, &sesopts) < 0) { + fprintf(stderr,"xscope: dni: ioctl failed\n"); + exit(-1); + } + + strncpy(opblk.op_node_name,ServerHostName , 6); /* dni server name */ + opblk.op_node_name[6] = '\0'; + sprintf(opblk.op_task_name, "X$X%d", GetServerport()); + opblk.op_userid[0] = '\0'; /* No one checks our id */ + opblk.op_object_nbr = 0; /* Any fields not used */ + opblk.op_account[0] = '\0'; /* should be set to zero */ + opblk.op_password[0] = '\0'; + opblk.op_opt_data.im_length = 0; + + if (ioctl(fd, SES_LINK_ACCESS, &opblk) == -1) { + fprintf(stderr,"xscope: dni: cannot connect to server\n"); + exit(-1); + } + UsingFD(fd, DataFromServer, NULL, NULL); + StartServerConnection(fd); + return(fd); + +} +#endif |