summaryrefslogtreecommitdiff
path: root/scope.c
diff options
context:
space:
mode:
Diffstat (limited to 'scope.c')
-rw-r--r--scope.c421
1 files changed, 383 insertions, 38 deletions
diff --git a/scope.c b/scope.c
index 52eadee..96164b7 100644
--- a/scope.c
+++ b/scope.c
@@ -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