v09i017: Xmon - X protocol monitor, Part03/05
Greg McFarlane
gregm at otc.otca.oz.au
Wed Sep 5 04:46:23 AEST 1990
Submitted-by: Greg McFarlane <gregm at otc.otca.oz.au>
Posting-number: Volume 9, Issue 17
Archive-name: xmon/part03
Submitted-by: gregm at otc.otca.oz.au
Archive-name: xmon/part03
---- Cut Here and unpack ----
#!/bin/sh
# This is part 03 of xmon
if touch 2>&1 | fgrep 'amc' > /dev/null
then TOUCH=touch
else TOUCH=true
fi
# ============= server.c ==============
if test X"$1" != X"-c" -a -f 'server.c'; then
echo "File already exists: skipping 'server.c'"
else
echo "x - extracting server.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > server.c &&
X/*
X * Project: XMON - An X protocol monitor
X *
X * File: server.c
X *
X * Description: Code to decode and print X11 protocol
X
X * These are the possible values for ByteProcessing:
X * For clients:
X * StartSetUpMessage
X * FinishSetUpMessage
X * StartRequest
X * FinishRequest
X * For servers:
X * StartSetUpReply
X * FinishSetUpReply
X * ServerPacket
X * FinishReply
X *
X */
X
X#include <sys/time.h> /* for struct timeval * */
X#include <errno.h> /* for EINTR, EADDRINUSE, ... */
X
X#include "common.h"
X
X#include "x11.h"
X#include "xmond.h"
X
X/* function prototypes: */
X/* server.c: */
Xstatic void ProcessBuffer P((int fd , unsigned char *buf , long n , int
WriteFD ));
Xstatic void WriteBuffer P((Client *client , long n , char *buf , int
WriteFD ));
Xstatic long StartSetUpMessage P((Pointer private_data , unsigned char
*buf , long n ));
Xstatic long FinishSetUpMessage P((Pointer private_data , unsigned char
*buf , long n ));
Xstatic long StartRequest P((Pointer private_data , unsigned char *buf ,
long n ));
Xstatic long FinishRequest P((Pointer private_data , unsigned char *buf
, long n ));
Xstatic long StartSetUpReply P((Pointer private_data , unsigned char
*buf , long n ));
Xstatic long FinishSetUpReply P((Pointer private_data , unsigned char
*buf , long n ));
Xstatic long ErrorPacket P((Server *server , unsigned char *buf , long n ));
Xstatic long EventPacket P((Server *server , unsigned char *buf , long n ));
Xstatic long ReplyPacket P((Server *server , unsigned char *buf , long n ));
Xstatic long ServerPacket P((Pointer private_data , unsigned char *buf ,
long n ));
Xstatic long FinishReply P((Pointer private_data , unsigned char *buf ,
long n ));
X
X/* end function prototypes */
X
XGlobal Bool ignore_bytes;
X
Xextern int CurrentVerbose;
Xextern int ErrorVerbose;
Xextern Bool littleEndian;
X
Xstatic long ZeroTime1 = -1;
Xstatic long ZeroTime2 = -1;
Xstatic struct timeval tp;
X
X/*
X * print the time since we started in hundredths (1/100) of seconds
X */
X
XGlobal void
XPrintTime()
X{
X static long lastsec = 0;
X long sec /* seconds */ ;
X long hsec /* hundredths of a second */ ;
X
X gettimeofday(&tp, (struct timezone *)NULL);
X if (ZeroTime1 == -1 || (tp.tv_sec - lastsec) >= 1000)
X {
X ZeroTime1 = tp.tv_sec;
X ZeroTime2 = tp.tv_usec / 10000;
X }
X
X lastsec = tp.tv_sec;
X sec = tp.tv_sec - ZeroTime1;
X hsec = tp.tv_usec / 10000 - ZeroTime2;
X if (hsec < 0)
X {
X hsec += 100;
X sec -= 1;
X }
X fprintf(stdout, "%2d.%02ld: ", sec, hsec);
X}
X
X/*
X * pad:
X *
X * we will need to be able to interpret the values stored in the requests
X * as various built-in types. The following routines support the types
X * built into X11
X */
XGlobal int
Xpad (n)
X long n;
X{
X /* round up to next multiple of 4 */
X return((n + 3) & ~0x3);
X}
X
XGlobal unsigned long
XILong (buf)
X unsigned char buf[];
X{
X if (littleEndian)
X return((((((buf[3] << 8) | buf[2]) << 8) | buf[1]) << 8) | buf[0]);
X return((((((buf[0] << 8) | buf[1]) << 8) | buf[2]) << 8) | buf[3]);
X}
X
XGlobal unsigned short
XIShort (buf)
Xunsigned char buf[];
X{
X if (littleEndian)
X return (buf[1] << 8) | buf[0];
X return((buf[0] << 8) | buf[1]);
X}
X
XGlobal unsigned short
XIByte (buf)
Xunsigned char buf[];
X{
X return(buf[0]);
X}
X
XGlobal Bool
XIBool(buf)
X unsigned char buf[];
X{
X if (buf[0] != 0)
X return(True);
X else
X return(False);
X}
X
X/*
X * Byte Processing Routines. Each routine MUST set num_Needed
X * and ByteProcessing. It probably needs to do some computation first.
X */
X
XGlobal void
XStartClientConnection(client)
X Client *client;
X{
X /* when a new connection is started, we have no saved bytes */
X client->fdd->inBuffer.data = NULL;
X client->fdd->inBuffer.BlockSize = 0;
X client->fdd->inBuffer.num_Saved = 0;
X client->fdd->outBuffer.data = NULL;
X client->fdd->outBuffer.BlockSize = 0;
X client->fdd->outBuffer.num_Saved = 0;
X
X /* each new connection gets a request sequence number */
X client->SequenceNumber = 0;
X
X /* we need 12 bytes to start a SetUp message */
X client->fdd->ByteProcessing = StartSetUpMessage;
X client->fdd->inBuffer.num_Needed = 12;
X}
X
XGlobal void
XStartServerConnection(server)
X Server *server;
X{
X /* when a new connection is started, we have no saved bytes */
X server->fdd->inBuffer.data = NULL;
X server->fdd->inBuffer.BlockSize = 0;
X server->fdd->inBuffer.num_Saved = 0;
X server->fdd->outBuffer.data = NULL;
X server->fdd->outBuffer.BlockSize = 0;
X server->fdd->outBuffer.num_Saved = 0;
X
X /* when a new connection is started, we have no reply Queue */
X initList(&server->reply_list);
X
X /* we need 8 bytes to start a SetUp reply */
X server->fdd->ByteProcessing = StartSetUpReply;
X server->fdd->inBuffer.num_Needed = 8;
X}
X
Xstatic void
XWriteBuffer(client, n, buf, WriteFD)
X Client *client;
X long n;
X char *buf;
X int WriteFD;
X{
X int BytesToWrite = n;
X int num_written;
X
X while (BytesToWrite > 0)
X {
X num_written = write (WriteFD, buf, BytesToWrite);
X if (num_written > 0)
X {
X BytesToWrite -= num_written;
X buf += num_written;
X }
X else
X {
X if (errno == EWOULDBLOCK)
X printf("WriteBuffer: write would block (TODO)\n");
X if (errno == EINTR)
X printf("WriteBuffer: write interrupted (TODO)\n");
X perror("Error on write to Client/Server");
X CloseConnection(client);
X BytesToWrite = 0;
X }
X }
X}
X
X/*
X * StartSetUpMessage:
X *
X * we need the first 12 bytes to be able to determine if, and how many,
X * additional bytes we need for name and data authorization. However, we
X * can't process the first 12 bytes until we get all of them, so
X * return zero bytes used, and increase the number of bytes needed
X */
Xstatic long
XStartSetUpMessage (private_data, buf, n)
X Pointer private_data;
X unsigned char *buf;
X long n;
X{
X Client *client = (Client *) private_data;
X short namelength;
X short datalength;
X
X namelength = IShort(&buf[6]);
X datalength = IShort(&buf[8]);
X client->fdd->ByteProcessing = FinishSetUpMessage;
X client->fdd->inBuffer.num_Needed =
X n + pad((long)namelength) + pad((long)datalength);
X return(0);
X}
X
Xstatic long
XFinishSetUpMessage (private_data, buf, n)
X Pointer private_data;
X unsigned char *buf;
X long n;
X{
X Client *client = (Client *) private_data;
X
X littleEndian = client->fdd->littleEndian = (buf[0] == 'l');
X
X CurrentVerbose = ErrorVerbose;
X PrintSetUpMessage(buf);
X
X /* after a set-up message, we expect a string of requests */
X client->fdd->ByteProcessing = StartRequest;
X client->fdd->inBuffer.num_Needed = 4;
X return(n);
X}
X
X
Xstatic long
XStartRequest (private_data, buf, n)
X Pointer private_data;
X unsigned char *buf;
X long n;
X{
X short requestlength = IShort(&buf[2]);
X Client *client = (Client *) private_data;
X
X client->fdd->ByteProcessing = FinishRequest;
X client->fdd->inBuffer.num_Needed = 4 * requestlength;
X return(0);
X}
X
X
Xstatic long
XFinishRequest (private_data, buf, n)
X Pointer private_data;
X unsigned char *buf;
X long n;
X{
X Client *client = (Client *) private_data;
X
X DecodeRequest(client, buf, n);
X client->fdd->ByteProcessing = StartRequest;
X client->fdd->inBuffer.num_Needed = 4;
X return(n);
X}
X
Xstatic long
XStartSetUpReply (private_data, buf, n)
X Pointer private_data;
X unsigned char *buf;
X long n;
X{
X short replylength = IShort(&buf[6]);
X Server *server = (Server *) private_data;
X
X server->fdd->ByteProcessing = FinishSetUpReply;
X server->fdd->inBuffer.num_Needed = n + 4 * replylength;
X return(0);
X}
X
Xstatic long
XFinishSetUpReply (private_data, buf, n)
X Pointer private_data;
X unsigned char *buf;
X long n;
X{
X Server *server = (Server *) private_data;
X
X CurrentVerbose = ErrorVerbose;
X PrintSetUpReply(buf);
X server->fdd->ByteProcessing = ServerPacket;
X server->fdd->inBuffer.num_Needed = 32;
X return(n);
X}
X
Xstatic long
XErrorPacket (server, buf, n)
X Server *server;
X unsigned char *buf;
X long n;
X{
X DecodeError(server, buf, n);
X server->fdd->ByteProcessing = ServerPacket;
X server->fdd->inBuffer.num_Needed = 32;
X return(n);
X}
X
X
Xstatic long
XEventPacket (server, buf, n)
X Server *server;
X unsigned char *buf;
X long n;
X{
X DecodeEvent(server, buf, n);
X server->fdd->ByteProcessing = ServerPacket;
X server->fdd->inBuffer.num_Needed = 32;
X return(n);
X}
X
X/*
X Replies may need more bytes, so we compute how many more
X bytes are needed and ask for them, not using any of the bytes
X we were given (return(0) to say that no bytes were used).
X If the replylength is zero (we don't need any more bytes), the
X number of bytes needed will be the same as what we have, and
X so the top-level loop will call the next routine immediately
X with the same buffer of bytes that we were given.
X*/
Xstatic long
XReplyPacket (server, buf, n)
X Server *server;
X unsigned char *buf;
X long n;
X{
X short replylength = ILong(&buf[4]);
X
X server->fdd->ByteProcessing = FinishReply;
X server->fdd->inBuffer.num_Needed = n + 4 * replylength;
X return(0);
X}
X
Xstatic long
XServerPacket (private_data, buf, n)
X Pointer private_data;
X unsigned char *buf;
X long n;
X{
X short PacketType = IByte(&buf[0]);
X Server *server = (Server *) private_data;
X
X if (PacketType == 0)
X return(ErrorPacket(server, buf, n));
X else if (PacketType == 1)
X return(ReplyPacket(server, buf, n));
X else
X return(EventPacket(server, buf, n));
X}
X
Xstatic long
XFinishReply (private_data, buf, n)
X Pointer private_data;
X unsigned char *buf;
X long n;
X{
X Server *server = (Server *) private_data;
X
X DecodeReply(server, buf, n);
X server->fdd->ByteProcessing = ServerPacket;
X server->fdd->inBuffer.num_Needed = 32;
X return(n);
X}
SHAR_EOF
$TOUCH -am 0903162990 server.c &&
chmod 0664 server.c ||
echo "restore of server.c failed"
set `wc -c server.c`;Wc_c=$1
if test "$Wc_c" != "9529"; then
echo original size 9529, current size $Wc_c
fi
fi
# ============= fd.c ==============
if test X"$1" != X"-c" -a -f 'fd.c'; then
echo "File already exists: skipping 'fd.c'"
else
echo "x - extracting fd.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > fd.c &&
X/*
X * Project: XMON - An X protocol monitor
X *
X * File: fd.c
X *
X * Description: Support routines for file descriptors
X *
X * All of this code is to support the handling of file descriptors.
X * The idea is to keep a table of the FDs that are in use and why. For
X * each FD that is open for input, we keep the name of a procedure to call
X * if input arrives for that FD. When an FD is created (by an open, pipe,
X * socket, ...) declare that by calling UsingFD. When it is no longer in
X * use (close ...), call NotUsingFD.
X */
X
X#include <errno.h> /* for EINTR, EADDRINUSE, ... */
X
X#include "common.h"
X
X#include "xmond.h"
X#include "select_args.h"
X
X/* function prototypes: */
X/* fd.c: */
X
X/* end function prototypes */
X
Xextern FDDescriptor *FDD;
Xextern long ReadDescriptors[];
Xextern long WriteDescriptors[];
Xextern short HighestFD;
X
XGlobal void
XInitializeFD()
X{
X register short i;
X short MaxFD /* maximum number of FD's possible */ ;
X
X enterprocedure("InitializeFD");
X /* get the number of file descriptors the system will let us use */
X MaxFD = getdtablesize();
X
X /* allocate space for a File Descriptor Table */
X FDD = (FDDescriptor *)malloc((long)(MaxFD * sizeof(FDDescriptor)));
X
X for (i = 0; i < MaxFD; i++)
X FDD[i].InputHandler = (VoidCallback)NULL;
X
X CLEARBITS(ReadDescriptors);
X CLEARBITS(WriteDescriptors);
X HighestFD = 0;
X}
X
XGlobal FDDescriptor*
XUsingFD(fd, Handler, private_data)
X int fd;
X VoidCallback Handler;
X Pointer private_data;
X{
X FDD[fd].InputHandler = Handler;
X FDD[fd].private_data = private_data;
X if (Handler == NULL)
X BITCLEAR(ReadDescriptors, fd);
X else
X BITSET(ReadDescriptors, fd);
X
X if (fd > HighestFD)
X HighestFD = fd;
X return &FDD[fd];
X}
X
XGlobal void
XNotUsingFD(fd)
X int fd;
X{
X FDD[fd].InputHandler = (VoidCallback)NULL;
X BITCLEAR(ReadDescriptors, fd);
X
X while (FDD[HighestFD].InputHandler == (VoidCallback)NULL && HighestFD > 0)
X HighestFD -= 1;
X}
X
XGlobal void
XEOFonFD(fd)
X int fd;
X{
X close(fd);
X NotUsingFD(fd);
X}
SHAR_EOF
$TOUCH -am 0903162990 fd.c &&
chmod 0664 fd.c ||
echo "restore of fd.c failed"
set `wc -c fd.c`;Wc_c=$1
if test "$Wc_c" != "1997"; then
echo original size 1997, current size $Wc_c
fi
fi
# ============= main.c ==============
if test X"$1" != X"-c" -a -f 'main.c'; then
echo "File already exists: skipping 'main.c'"
else
echo "x - extracting main.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > main.c &&
X/*
X * Project: XMON - An X protocol monitor
X *
X * File: main.c
X *
X * Description: Contains main() for xmond
X *
X */
X
X#include <sys/types.h> /* needed by sys/socket.h and netinet/in.h */
X#include <sys/uio.h> /* for struct iovec, used by socket.h */
X#include <sys/socket.h> /* for AF_INET, SOCK_STREAM, ... */
X#include <sys/ioctl.h> /* for FIONCLEX, FIONBIO, ... */
X#include <netinet/in.h> /* struct sockaddr_in */
X#include <netdb.h> /* struct servent * and struct hostent * */
X#include <errno.h> /* for EINTR, EADDRINUSE, ... */
X#include <signal.h>
X
X#include "common.h"
X
X#include "linkl.h"
X#include "xmond.h"
X#include "select_args.h"
X
X#define BACKLOG 5
X#define XBasePort 6000
X#define NUM_REQUESTS /* 128 */ 256
X#define NUM_EVENTS /* 40 */ 256
X
X
X/* function prototypes: */
X/* main.c: */
Xstatic void ScanArgs P((int argc , char **argv ));
Xstatic void SetUpConnectionSocket P((int iport ));
Xstatic void SetSignalHandling P((void ));
Xstatic void MainLoop P((void ));
Xstatic Bool SendBuffer P((int fd , Buffer *buffer ));
Xstatic short GetServerport P((void ));
Xstatic short GetScopePort P((void ));
Xstatic void Usage P((void ));
Xstatic void ReadStdin P((Pointer private_data ));
Xstatic void NewConnection P((Pointer private_data ));
Xstatic void DataFromClient P((Pointer private_data ));
Xstatic void DataFromServer P((Pointer private_data ));
Xstatic Bool ReadAndProcessData P((Pointer private_data , FDDescriptor
*read_fdd , FDDescriptor *write_fdd ));
Xstatic void SaveBytes P((Buffer *buffer , char *buf , long n ));
Xstatic void RemoveSavedBytes P((Buffer *buffer , int n ));
Xstatic int ConnectToClient P((int ConnectionSocket ));
Xstatic int ConnectToServer P((char *hostName ));
Xstatic char *OfficialName P((char *name ));
Xstatic void SignalURG P((void ));
Xstatic void SignalPIPE P((void ));
Xstatic void SignalINT P((void ));
Xstatic void SignalQUIT P((void ));
Xstatic void SignalTERM P((void ));
Xstatic void SignalTSTP P((void ));
Xstatic void SignalCONT P((void ));
X
X/* end function prototypes */
X
XGlobal Bool ignore_bytes;
XGlobal int RequestVerbose = 0; /* verbose level for requests */
XGlobal int EventVerbose = 0; /* verbose level for events */
XGlobal int ReplyVerbose = 0; /* verbose level for replies */
XGlobal int ErrorVerbose = 1; /* verbose level for error */
XGlobal Bool VerboseRequest[NUM_REQUESTS];/* requests that are very
verbose */
XGlobal Bool VerboseEvent[NUM_EVENTS]; /* events that are very verbose */
XGlobal Bool BlockRequest[NUM_REQUESTS]; /* do not transmit these
requests */
XGlobal Bool BlockEvent[NUM_EVENTS]; /* do not transmit these events */
XGlobal Bool MonitoringRequests = True; /* monitor selected requests? */
XGlobal Bool MonitoringEvents = True; /* monitor selected events? */
XGlobal Bool BlockingRequests = True; /* block selected requests? */
XGlobal Bool BlockingEvents = True; /* block selected events? */
XGlobal int SelectedRequestVerbose = 3; /* selected requests verboseness */
XGlobal int SelectedEventVerbose = 3; /* selected errors verboseness */
XGlobal char ServerHostName[255];
XGlobal char *LocalHostName;
XGlobal int debuglevel = 0;
XGlobal LinkList client_list; /* list of Client */
XGlobal FDDescriptor *FDD;
XGlobal long ReadDescriptors[mskcnt];
XGlobal long WriteDescriptors[mskcnt];
XGlobal short HighestFD;
XGlobal Bool littleEndian;
X
Xstatic long ClientNumber = 0;
Xstatic int ServerPort = 0;
Xstatic int ListenForClientsPort = 1;
X
XGlobal void
Xmain(argc, argv)
X int argc;
X char **argv;
X{
X int i;
X
X ScanArgs(argc, argv);
X InitializeFD();
X InitializeX11();
X InitRequestCount();
X InitEventCount();
X InitErrorCount();
X (void)UsingFD(fileno(stdin), ReadStdin, (Pointer)fileno(stdin));
X SetUpConnectionSocket(GetScopePort());
X SetSignalHandling();
X for (i = 0; i < NUM_REQUESTS; i++)
X BlockRequest[i] = VerboseRequest[i] = False;
X for (i = 0; i < NUM_EVENTS; i++)
X BlockEvent[i] = VerboseEvent[i] = False;
X initList(&client_list);
X MainLoop();
X}
X
XGlobal void
XCloseConnection(client)
X Client *client;
X{
X Server *server;
X
X if (client->fdd->outBuffer.BlockSize > 0)
X Tfree(client->fdd->outBuffer.data);
X if (client->fdd->inBuffer.BlockSize > 0)
X Tfree(client->fdd->inBuffer.data);
X close(client->fdd->fd);
X NotUsingFD(client->fdd->fd);
X
X server = (Server *)(TopOfList(&client->server_list));
X if (server->fdd->outBuffer.BlockSize > 0)
X Tfree(server->fdd->outBuffer.data);
X if (server->fdd->inBuffer.BlockSize > 0)
X Tfree(server->fdd->inBuffer.data);
X close(server->fdd->fd);
X NotUsingFD(server->fdd->fd);
X}
X
Xstatic void
XScanArgs(argc, argv)
X int argc;
X char **argv;
X{
X int i;
X
X /* Scan argument list */
X for (i = 1; i < argc; i++)
X {
X if (Streq(argv[i], "-server"))
X {
X /* Generally of the form server_name:display_number.
X * These all mean port 0 on server blah:
X * "blah",
X * "blah:",
X * "blah:0"
X * This means port 0 on local host: ":0".
X */
X if (++i < argc || argv[i] == NULL || argv[i][0] == '\0')
X {
X char *index = strchr(argv[i], ':');
X if (index == NULL)
X ServerPort = 0;
X else
X {
X ServerPort = atoi(index + 1);
X *index = '\0';
X }
X if (ServerPort < 0)
X ServerPort = 0;
X if (index != argv[i])
X strcpy(ServerHostName, OfficialName(argv[i]));
X }
X else
X Usage();
X debug(1,(stderr, "ServerHostName=%s\n", ServerHostName));
X }
X else if (Streq(argv[i], "-port"))
X {
X if (++i < argc)
X ListenForClientsPort = atoi(argv[i]);
X else
X Usage();
X if (ListenForClientsPort <= 0)
X ListenForClientsPort = 0;
X debug(1,(stderr, "ListenForClientsPort=%d\n",ListenForClientsPort));
X }
X else if (Streq(argv[i], "-debug"))
X {
X /*
X debug levels:
X 2 - trace each procedure entry
X 4 - I/O, connections
X 8 - Scope internals
X 16 - Message protocol
X 32 - 64 - malloc
X 128 - 256 - really low level
X */
X if (++i < argc)
X debuglevel = atoi(argv[i]);
X else
X Usage();
X if (debuglevel == 0)
X debuglevel = 255;
X debuglevel |= 1;
X debug(1,(stderr, "debuglevel = %d\n", debuglevel));
X }
X else if (Streq(argv[i], "-verbose"))
X {
X if (++i < argc)
X RequestVerbose = EventVerbose =
X ReplyVerbose = ErrorVerbose = atoi(argv[i]);
X else
X Usage();
X }
X else
X Usage();
X }
X
X LocalHostName = (char *)malloc(255);
X (void) gethostname(LocalHostName, 255);
X if (ServerHostName[0] == '\0')
X (void) gethostname(ServerHostName, sizeof (ServerHostName));
X if (Streq(ServerHostName,LocalHostName) && ListenForClientsPort ==
ServerPort)
X {
X fprintf
X (
X stderr, "Can't have xmond on same port as server (%d)\n",
X ListenForClientsPort
X );
X Usage();
X }
X}
X
X/*
X * SetUpConnectionSocket:
X *
X * Create a socket for a service to listen for clients
X */
Xstatic void
XSetUpConnectionSocket(iport)
Xint iport;
X{
X int ON = 1; /* used in ioctl */
X int ConnectionSocket;
X struct sockaddr_in sin;
X
X enterprocedure("SetUpConnectionSocket");
X
X /* create the connection socket and set its parameters of use */
X ConnectionSocket = socket(AF_INET, SOCK_STREAM, 0);
X if (ConnectionSocket < 0)
X {
X perror("socket");
X exit(-1);
X }
X (void)setsockopt(ConnectionSocket, SOL_SOCKET, SO_REUSEADDR, (char
*)NULL, 0);
X (void)setsockopt(ConnectionSocket, SOL_SOCKET, SO_USELOOPBACK,
(char*)NULL,0);
X#ifdef SO_DONTLINGER
X (void)setsockopt(ConnectionSocket, SOL_SOCKET, SO_DONTLINGER,
(char*)NULL, 0);
X#endif
X
X /* define the name and port to be used with the connection socket */
X bzero((char *)&sin, sizeof(sin));
X sin.sin_family = AF_INET;
X
X /* the address of the socket is composed of two parts: the host machine and
X the port number. We need the host machine address for the current host
X */
X {
X /* define the host part of the address */
X struct hostent *hp;
X
X hp = gethostbyname(LocalHostName);
X if (hp == NULL)
X panic("No address for our host"); /* and exit */
X bcopy((char *)hp->h_addr, (char*)&sin.sin_addr, hp->h_length);
X }
X /* new code -- INADDR_ANY should be better than using the name of the
X host machine. The host machine may have several different network
X addresses. INADDR_ANY should work with all of them at once. */
X sin.sin_addr.s_addr = INADDR_ANY;
X
X sin.sin_port = htons (iport);
X
X /* bind the name and port number to the connection socket */
X if (bind(ConnectionSocket, (struct sockaddr *)&sin, sizeof(sin)) < 0)
X {
X perror("bind");
X exit(-1);
X }
X
X debug(4,(stderr, "Socket is FD %d for %s,%d\n",
X ConnectionSocket, LocalHostName, iport));
X
X /* now activate the named connection socket to get messages */
X if (listen(ConnectionSocket, BACKLOG) < 0)
X {
X perror("listen");
X exit(-1);
X };
X
X /* a few more parameter settings */
X ioctl(ConnectionSocket, FIOCLEX, 0);
X ioctl(ConnectionSocket, FIONBIO, &ON);
X
X debug(4,(stderr, "Listening on FD %d\n", ConnectionSocket));
X (void)UsingFD(ConnectionSocket, NewConnection, (Pointer)ConnectionSocket);
X}
X
X/*
X * Signal Handling support
X */
Xstatic void
XSetSignalHandling()
X{
X enterprocedure("SetSignalHandling");
X signal(SIGURG, SignalURG);
X signal(SIGPIPE, SignalPIPE);
X signal(SIGINT, SignalINT);
X signal(SIGQUIT, SignalQUIT);
X signal(SIGTERM, SignalTERM);
X signal(SIGTSTP, SignalTSTP);
X signal(SIGCONT, SignalCONT);
X}
X
X/*
X * MainLoop:
X *
X * Wait for input from any source and Process.
X */
Xstatic void
XMainLoop()
X{
X long rfds[mskcnt];
X long wfds[mskcnt];
X long xfds[mskcnt];
X short nfds;
X short fd;
X Client *client;
X Server *server;
X
X while (True)
X {
X COPYBITS(ReadDescriptors, rfds);
X COPYBITS(WriteDescriptors, wfds);
X ORBITS(xfds, ReadDescriptors, WriteDescriptors);
X nfds = select
X (
X HighestFD + 1, (fd_set *)rfds, (fd_set *)wfds, (fd_set *)xfds, NULL
X );
X if (ANYSET(xfds))
X panic("MainLoop: error in select");
X if (nfds <= 0)
X {
X if (errno != EINTR)
X if (errno == EBADF)
X EOFonFD(HighestFD);
X else
X panic("Select returns error");
X }
X else
X {
X for (fd = 0; ANYSET(rfds) && fd <= HighestFD; fd++)
X {
X if (GETBIT(rfds, fd))
X {
X BITCLEAR(rfds, fd);
X (FDD[fd].InputHandler)(FDD[fd].private_data);
X }
X }
X for (fd = 0; ANYSET(wfds) && fd <= HighestFD; fd++)
X {
X if (GETBIT(wfds, fd))
X {
X BITCLEAR(wfds, fd);
X if (!SendBuffer(fd, &FDD[fd].outBuffer))
X panic("help: which connection do we shut down (TODO?");
X }
X }
X }
X ForAllInList(&client_list)
X {
X client = (Client *)CurrentContentsOfList(&client_list);
X if (!SendBuffer(client->fdd->fd, &client->fdd->outBuffer))
X CloseConnection(client);
X server = (Server *)(TopOfList(&client->server_list));
X if (!SendBuffer(server->fdd->fd, &server->fdd->outBuffer))
X CloseConnection(client);
X }
X }
X}
X
Xstatic Bool
XSendBuffer(fd, buffer)
X int fd;
X Buffer *buffer;
X{
X char *buf = buffer->data;
X int BytesToWrite = buffer->num_Saved;
X int num_written;
X int total_num_written = 0;
X Bool ok = True;
X
X BITCLEAR(WriteDescriptors, fd);
X if (BytesToWrite > 0)
X {
X do
X {
X num_written = write (fd, buf, BytesToWrite);
X if (num_written > 0)
X {
X BytesToWrite -= num_written;
X buf += num_written;
X total_num_written += num_written;
X }
X }
X while (BytesToWrite > 0 && num_written > 0);
X
X if (BytesToWrite > 0)
X {
X if (errno == EWOULDBLOCK || errno == EINTR)
X {
X debug(4,(stderr, "write is blocked: buffering output\n"));
X RemoveSavedBytes(buffer, total_num_written);
X BITSET(WriteDescriptors, fd);
X }
X else
X {
X perror("Error on write to Client/Server");
X ok = False;
X }
X }
X else
X buffer->num_Saved = 0;
X }
X return ok;
X}
X
Xstatic short
XGetServerport ()
X{
X short port;
X
X enterprocedure("GetServerport");
X
X port = XBasePort + ServerPort;
X debug(4,(stderr, "Server service is on port %d\n", port));
X return(port);
X}
X
Xstatic short
XGetScopePort ()
X{
X short port;
X
X enterprocedure("GetScopePort");
X
X port = XBasePort + ListenForClientsPort;
X debug(4,(stderr, "xmond service is on port %d\n", port));
X return(port);
X}
X
Xstatic void
XUsage()
X{
X fprintf(stderr, "Usage: xmond\n");
X fprintf(stderr, " [-server <server_name:port>]\n");
X fprintf(stderr, " [-port <listen_port>]\n");
X fprintf(stderr, " [-debug <debug_level>]\n");
X fprintf(stderr, " [-verbose <all_monitor_level>]\n");
X exit(1);
X}
X
X#define SELECTED_REQUEST_VERBOSE_STR "selected_request_verbose"
X#define SELECTED_EVENT_VERBOSE_STR "selected_event_verbose"
X#define REQUEST_VERBOSE_STR "request_verbose"
X#define EVENT_VERBOSE_STR "event_verbose"
X#define REPLY_VERBOSE_STR "reply_verbose"
X#define ERROR_VERBOSE_STR "error_verbose"
X#define MONITOR_REQUEST_ON_STR "monitor_request_on"
X#define MONITOR_REQUEST_OFF_STR "monitor_request_off"
X#define MONITOR_EVENT_ON_STR "monitor_event_on"
X#define MONITOR_EVENT_OFF_STR "monitor_event_off"
X#define BLOCK_REQUEST_ON_STR "block_request_on"
X#define BLOCK_REQUEST_OFF_STR "block_request_off"
X#define BLOCK_EVENT_ON_STR "block_event_on"
X#define BLOCK_EVENT_OFF_STR "block_event_off"
X#define START_REQUEST_COUNT_STR "startrequestcount"
X#define STOP_REQUEST_COUNT_STR "stoprequestcount"
X#define CLEAR_REQUEST_COUNT_STR "clearrequestcount"
X#define PRINT_REQUEST_COUNT_STR "printrequestcount"
X#define PRINT_ZERO_REQUEST_COUNT_STR "printzerorequestcount"
X#define START_EVENT_COUNT_STR "starteventcount"
X#define STOP_EVENT_COUNT_STR "stopeventcount"
X#define CLEAR_EVENT_COUNT_STR "cleareventcount"
X#define PRINT_EVENT_COUNT_STR "printeventcount"
X#define PRINT_ZERO_EVENT_COUNT_STR "printzeroeventcount"
X#define START_ERROR_COUNT_STR "starterrorcount"
X#define STOP_ERROR_COUNT_STR "stoperrorcount"
X#define CLEAR_ERROR_COUNT_STR "clearerrorcount"
X#define PRINT_ERROR_COUNT_STR "printerrorcount"
X#define PRINT_ZERO_ERROR_COUNT_STR "printzeroerrorcount"
X#define REQUEST_MONITORING_ON_STR "request_monitoring_on"
X#define REQUEST_MONITORING_OFF_STR "request_monitoring_off"
X#define EVENT_MONITORING_ON_STR "event_monitoring_on"
X#define EVENT_MONITORING_OFF_STR "event_monitoring_off"
X#define REQUEST_BLOCKING_ON_STR "request_blocking_on"
X#define REQUEST_BLOCKING_OFF_STR "request_blocking_off"
X#define EVENT_BLOCKING_ON_STR "event_blocking_on"
X#define EVENT_BLOCKING_OFF_STR "event_blocking_off"
X#define QUIT_STR "quit"
X#define HELP_STR "help"
X
X#define Strleneq(a,b) Strneq(a, b, strlen(b))
X
Xstatic void
XReadStdin(private_data)
X Pointer private_data;
X{
X int fd = (int)private_data;
X char buf[2048];
X char *ptr;
X int n;
X
X enterprocedure("ReadStdin");
X n = read(fd, buf, 2048);
X if (n == 0)
X {
X fprintf(stdout, "EOF on stdin\n");
X exit(0);
X }
X if (n < 0)
X {
X fprintf(stdout, "Error reading stdin\n");
X exit(0);
X }
X
X buf[n] = '\0';
X ptr = buf;
X while (*ptr == ' ' || *ptr == '\t')
X ptr++;
X if (*ptr != '\0')
X {
X if (Strleneq(ptr, REQUEST_VERBOSE_STR))
X RequestVerbose = atoi(ptr + strlen(REQUEST_VERBOSE_STR));
X else if (Strleneq(ptr, EVENT_VERBOSE_STR))
X EventVerbose = atoi(ptr + strlen(EVENT_VERBOSE_STR));
X else if (Strleneq(ptr, REPLY_VERBOSE_STR))
X ReplyVerbose = atoi(ptr + strlen(REPLY_VERBOSE_STR));
X else if (Strleneq(ptr, ERROR_VERBOSE_STR))
X ErrorVerbose = atoi(ptr + strlen(ERROR_VERBOSE_STR));
X else if (Strleneq(ptr, MONITOR_REQUEST_ON_STR))
X VerboseRequest[atoi(ptr + strlen(MONITOR_REQUEST_ON_STR))] = True;
X else if (Strleneq(ptr, MONITOR_REQUEST_OFF_STR))
X VerboseRequest[atoi(ptr + strlen(MONITOR_REQUEST_OFF_STR))] = False;
X else if (Strleneq(ptr, MONITOR_EVENT_ON_STR))
X VerboseEvent[atoi(ptr + strlen(MONITOR_EVENT_ON_STR))] = True;
X else if (Strleneq(ptr, MONITOR_EVENT_OFF_STR))
X VerboseEvent[atoi(ptr + strlen(MONITOR_EVENT_OFF_STR))] = False;
X else if (Strleneq(ptr, REQUEST_MONITORING_ON_STR))
X MonitoringRequests = True;
X else if (Strleneq(ptr, REQUEST_MONITORING_OFF_STR))
X MonitoringRequests = False;
X else if (Strleneq(ptr, EVENT_MONITORING_ON_STR))
X MonitoringEvents = True;
X else if (Strleneq(ptr, EVENT_MONITORING_OFF_STR))
X MonitoringEvents = False;
X else if (Strleneq(ptr, REQUEST_BLOCKING_ON_STR))
X BlockingRequests = True;
X else if (Strleneq(ptr, REQUEST_BLOCKING_OFF_STR))
X BlockingRequests = False;
X else if (Strleneq(ptr, EVENT_BLOCKING_ON_STR))
X BlockingEvents = True;
X else if (Strleneq(ptr, EVENT_BLOCKING_OFF_STR))
X BlockingEvents = False;
X else if (Strleneq(ptr, SELECTED_REQUEST_VERBOSE_STR))
X SelectedRequestVerbose =
X atoi(ptr +strlen(SELECTED_REQUEST_VERBOSE_STR));
X else if (Strleneq(ptr, SELECTED_EVENT_VERBOSE_STR))
X SelectedEventVerbose =
X atoi(ptr + strlen(SELECTED_EVENT_VERBOSE_STR));
X else if (Strleneq(ptr, BLOCK_REQUEST_ON_STR))
X BlockRequest[atoi(ptr + strlen(BLOCK_REQUEST_ON_STR))] = True;
X else if (Strleneq(ptr, BLOCK_REQUEST_OFF_STR))
X BlockRequest[atoi(ptr + strlen(BLOCK_REQUEST_OFF_STR))] = False;
X else if (Strleneq(ptr, BLOCK_EVENT_ON_STR))
X BlockEvent[atoi(ptr + strlen(BLOCK_EVENT_ON_STR))] = True;
X else if (Strleneq(ptr, BLOCK_EVENT_OFF_STR))
X BlockEvent[atoi(ptr + strlen(BLOCK_EVENT_OFF_STR))] = False;
X else if (Strleneq(ptr, START_REQUEST_COUNT_STR))
X StartRequestCount();
X else if (Strleneq(ptr, STOP_REQUEST_COUNT_STR))
X EndRequestCount();
X else if (Strleneq(ptr, CLEAR_REQUEST_COUNT_STR))
X ClearRequestCount();
X else if (Strleneq(ptr, PRINT_REQUEST_COUNT_STR))
X PrintRequestCounts();
X else if (Strleneq(ptr, PRINT_ZERO_REQUEST_COUNT_STR))
X PrintZeroRequestCounts();
X else if (Strleneq(ptr, START_EVENT_COUNT_STR))
X StartEventCount();
X else if (Strleneq(ptr, STOP_EVENT_COUNT_STR))
X EndEventCount();
X else if (Strleneq(ptr, CLEAR_EVENT_COUNT_STR))
X ClearEventCount();
X else if (Strleneq(ptr, PRINT_EVENT_COUNT_STR))
X PrintEventCounts();
X else if (Strleneq(ptr, PRINT_ZERO_EVENT_COUNT_STR))
X PrintZeroEventCounts();
X else if (Strleneq(ptr, START_ERROR_COUNT_STR))
X StartErrorCount();
X else if (Strleneq(ptr, STOP_ERROR_COUNT_STR))
X EndErrorCount();
X else if (Strleneq(ptr, CLEAR_ERROR_COUNT_STR))
X ClearErrorCount();
X else if (Strleneq(ptr, PRINT_ERROR_COUNT_STR))
X PrintErrorCounts();
X else if (Strleneq(ptr, PRINT_ZERO_ERROR_COUNT_STR))
X PrintZeroErrorCounts();
X else if (Strleneq(ptr, QUIT_STR))
X exit(0);
X else if (Strleneq(ptr, HELP_STR))
X {
X fprintf(stdout, "%s <verbose_level>\n", REQUEST_VERBOSE_STR);
X fprintf(stdout, "%s <verbose_level>\n", EVENT_VERBOSE_STR);
X fprintf(stdout, "%s <verbose_level>\n", REPLY_VERBOSE_STR);
X fprintf(stdout, "%s <verbose_level>\n", ERROR_VERBOSE_STR);
X fprintf(stdout, "%s <verbose_request_number>\n",
X MONITOR_REQUEST_ON_STR);
X fprintf(stdout, "%s <verbose_request_number>\n",
X MONITOR_REQUEST_OFF_STR);
X fprintf(stdout, "%s <verbose_event_number>\n",
X MONITOR_EVENT_ON_STR);
X fprintf(stdout, "%s <verbose_event_number>\n",
X MONITOR_EVENT_OFF_STR);
X fprintf(stdout, "%s <selected_request_verboseness>\n",
X SELECTED_REQUEST_VERBOSE_STR);
X fprintf(stdout, "%s <selected_event_verboseness>\n",
X SELECTED_EVENT_VERBOSE_STR);
X fprintf(stdout, "%s <block_request_number>\n",BLOCK_REQUEST_ON_STR);
X fprintf(stdout,"%s <block_request_number>\n",BLOCK_REQUEST_OFF_STR);
X fprintf(stdout, "%s <block_event_number>\n", BLOCK_EVENT_ON_STR);
X fprintf(stdout, "%s <block_event_number>\n", BLOCK_EVENT_OFF_STR);
X
X fprintf(stdout, "%s\n", START_REQUEST_COUNT_STR);
X fprintf(stdout, "%s\n", STOP_REQUEST_COUNT_STR);
X fprintf(stdout, "%s\n", CLEAR_REQUEST_COUNT_STR);
X fprintf(stdout, "%s\n", PRINT_REQUEST_COUNT_STR);
X fprintf(stdout, "%s\n", PRINT_ZERO_REQUEST_COUNT_STR);
X fprintf(stdout, "%s\n", START_EVENT_COUNT_STR);
X fprintf(stdout, "%s\n", STOP_EVENT_COUNT_STR);
X fprintf(stdout, "%s\n", CLEAR_EVENT_COUNT_STR);
X fprintf(stdout, "%s\n", PRINT_EVENT_COUNT_STR);
X fprintf(stdout, "%s\n", PRINT_ZERO_EVENT_COUNT_STR);
X fprintf(stdout, "%s\n", START_ERROR_COUNT_STR);
X fprintf(stdout, "%s\n", STOP_ERROR_COUNT_STR);
X fprintf(stdout, "%s\n", CLEAR_ERROR_COUNT_STR);
X fprintf(stdout, "%s\n", PRINT_ERROR_COUNT_STR);
X fprintf(stdout, "%s\n", PRINT_ZERO_ERROR_COUNT_STR);
X fprintf(stdout, "%s\n", QUIT_STR);
X fprintf(stdout, "%s\n", HELP_STR);
X }
X else
X fprintf
X (
X stdout, "illegal command: %s\n\"help\" to get help\n", ptr
X );
X }
X}
X
X/*
X * NewConnection:
X *
X * Create New Connection to a client program and to Server.
X */
Xstatic void
XNewConnection(private_data)
X Pointer private_data;
X{
X int XPort = (int)private_data;
X Client *client;
X Server *server;
X int fd;
X
X client = Tmalloc(Client);
X appendToList(&client_list, (Pointer)client);
X fd = ConnectToClient(XPort);
X client->fdd = UsingFD(fd, DataFromClient, (Pointer)client);
X client->fdd->fd = fd;
X StartClientConnection(client);
X
X initList(&client->server_list);
X server = Tmalloc(Server);
X appendToList(&client->server_list, (Pointer)server);
X fd = ConnectToServer(ServerHostName);
X server->fdd = UsingFD(fd, DataFromServer, (Pointer)server);
X server->fdd->fd = fd;
X server->client = client;
X StartServerConnection(server);
X
X ClientNumber += 1;
X client->ClientNumber = ClientNumber;
X}
X
Xstatic void
XDataFromClient(private_data)
X Pointer private_data;
X{
X Client *client = (Client *)private_data;
X Server *server;
X
X server = (Server *)(TopOfList(&client->server_list));
X if (!ReadAndProcessData(private_data, client->fdd, server->fdd))
X CloseConnection(client);
X}
X
Xstatic void
XDataFromServer(private_data)
X Pointer private_data;
X{
X Server *server = (Server *)private_data;
X Client *client = server->client;
X
X if (!ReadAndProcessData(private_data, server->fdd, client->fdd))
X CloseConnection(client);
X}
X
X/*
X * ReadAndProcessData:
X *
X * Read as much as we can and then loop as long as we have enough
X * bytes to do anything.
X *
X * In each cycle check if we have enough bytes (saved or in the newly read
X * buffer) to do something. If so, we want the bytes to be grouped
X * together into one contiguous block of bytes. We have three cases:
X *
X * (1) num_Saved == 0; so all needed bytes are in the read buffer.
X *
X * (2) num_Saved >= num_Needed; in this case all needed
X * bytes are in the save buffer and we will not need to copy any extra
X * bytes from the read buffer into the save buffer.
X *
X * (3) 0 < num_Saved < num_Needed; so some bytes are in
X * the save buffer and others are in the read buffer. In this case we
X * need to copy some of the bytes from the read buffer to the save buffer
X * to get as many bytes as we need, then use these bytes. First determine
X * the number of bytes we need to transfer; then transfer them and remove
X * them from the read buffer. (There may be additional requests in the
X * read buffer - we'll deal with them next cycle.)
X *
X * At this stage, we have a pointer to a contiguous block of
X * num_Needed bytes that we should process. The type of
X * processing depends upon the state we are in, given in the
X * ByteProcessing field of the FDDescriptor structure pointed to by
X * read_fdd. The processing routine returns the number of bytes that it
X * actually used.
X *
X * The number of bytes that were actually used is normally (but not
X * always) the number of bytes needed. Discard the bytes that were
X * actually used, not the bytes that were needed. The number of used
X * bytes must be less than or equal to the number of needed bytes. If
X * there were no saved bytes, then the bytes that were used must have been
X * in the read buffer so just modify the buffer pointer. Otherwise call
X * RemoveSavedBytes.
X *
X * After leaving the loop, if there are still some bytes left in the read
X * buffer append the newly read bytes to the save buffer.
X *
X * Return False if we reached end-of-file on read.
X */
X
Xstatic Bool
XReadAndProcessData(private_data, read_fdd, write_fdd)
X Pointer private_data;
X FDDescriptor *read_fdd;
X FDDescriptor *write_fdd;
X{
X Buffer *inbuffer = &read_fdd->inBuffer;
X Buffer *outbuffer = &write_fdd->outBuffer;
X int fd = read_fdd->fd;
X char read_buf_block[2048];
X char *read_buf = read_buf_block;
X int num_read;
X char *process_buf;
X int NumberofUsedBytes;
X int BytesToSave;
X
X num_read = read(fd, read_buf, 2048);
X if (num_read < 0)
X {
X perror("read error");
X if (errno == EWOULDBLOCK)
X panic("ReadAndProcessData: read would block (not implemented)");
X if (errno == EINTR)
X panic("ReadAndProcessData: read interrupted (not implemented)");
X }
X if (num_read == 0)
X {
X if (ErrorVerbose > 1)
X fprintf(stdout, "EOF\n");
X return False;
X }
X
X littleEndian = read_fdd->littleEndian;
X while (inbuffer->num_Saved + num_read >= inbuffer->num_Needed)
X {
X if (inbuffer->num_Saved == 0)
X process_buf = read_buf;
X else
X {
X if (inbuffer->num_Saved < inbuffer->num_Needed)
X {
X BytesToSave = inbuffer->num_Needed - inbuffer->num_Saved;
X SaveBytes(inbuffer, read_buf, BytesToSave);
X read_buf += BytesToSave;
X num_read -= BytesToSave;
X }
X process_buf = inbuffer->data;
X }
X ignore_bytes = False;
X NumberofUsedBytes = (*read_fdd->ByteProcessing)
X (
X private_data, process_buf, inbuffer->num_Needed
X );
X if (NumberofUsedBytes > 0)
X {
X if (!ignore_bytes)
X SaveBytes(outbuffer, process_buf, NumberofUsedBytes);
X if (inbuffer->num_Saved > 0)
X RemoveSavedBytes(inbuffer, NumberofUsedBytes);
X else
X {
X read_buf += NumberofUsedBytes;
X num_read -= NumberofUsedBytes;
X }
X }
X }
X if (num_read > 0)
X SaveBytes(inbuffer, read_buf, num_read);
X return True;
X}
X
X/*
X * We will need to save bytes until we get a complete request to
X * interpret. The following procedures provide this ability.
X */
X
Xstatic void
XSaveBytes(buffer, buf, n)
X Buffer *buffer;
X char *buf;
X long n;
X{
X long new_size;
X char *new_buf;
X
X /* check if there is enough space to hold the bytes we want */
X if (buffer->num_Saved + n > buffer->BlockSize)
X {
X /* not enough room so far; malloc more space and copy */
X new_size = (buffer->num_Saved + n + 1);
X new_buf = (char *)malloc(new_size);
X bcopy(buffer->data, new_buf, buffer->BlockSize);
X if (buffer->BlockSize > 0)
X Tfree(buffer->data);
X buffer->data = new_buf;
X buffer->BlockSize = new_size;
X }
X
X /* now copy the new bytes onto the end of the old bytes */
X bcopy(buf, (buffer->data + buffer->num_Saved), n);
X buffer->num_Saved += n;
X}
X
Xstatic void
XRemoveSavedBytes(buffer, n)
X Buffer *buffer;
X int n;
X{
X /* check if all bytes are being removed -- easiest case */
X if (buffer->num_Saved <= n)
X buffer->num_Saved = 0;
X else if (n != 0)
X {
X /* not all bytes are being removed -- shift the remaining ones down */
X register char *p = buffer->data;
X register char *q = buffer->data + n;
X register int i = buffer->num_Saved - n;
X while (i-- > 0)
X *p++ = *q++;
X buffer->num_Saved -= n;
X }
X}
X
Xstatic int
XConnectToClient(ConnectionSocket)
X int ConnectionSocket;
X{
X int ON = 1; /* used in ioctl */
X int ClientFD;
X struct sockaddr_in from;
X int len = sizeof (from);
X
X ClientFD = accept(ConnectionSocket, (struct sockaddr *)&from, &len);
X debug(4,(stderr, "Connect To Client: FD %d\n", ClientFD));
X if (ClientFD < 0 && errno == EWOULDBLOCK)
X {
X debug(4,(stderr, "Almost blocked accepting FD %d\n", ClientFD));
X panic("Can't connect to Client");
X }
X if (ClientFD < 0)
X {
X debug(4,(stderr, "ConnectToClient: error %d\n", errno));
X panic("Can't connect to Client");
X }
X
X ioctl(ClientFD, FIOCLEX, 0);
X ioctl(ClientFD, FIONBIO, &ON);
X return(ClientFD);
X}
X
Xstatic int
XConnectToServer(hostName)
X char *hostName;
X{
X int ServerFD;
X struct sockaddr_in sin;
X struct hostent *hp;
X
X enterprocedure("ConnectToServer");
X
X /* establish a socket to the name server for this host */
X bzero((char *)&sin, sizeof(sin));
X ServerFD = socket(AF_INET, SOCK_STREAM, 0);
X if (ServerFD < 0)
X {
X perror("socket() to Server failed");
X debug(1,(stderr, "socket failed\n"));
X panic("Can't open connection to Server");
X }
X (void) setsockopt(ServerFD, SOL_SOCKET, SO_REUSEADDR, (char *) NULL, 0);
X (void) setsockopt(ServerFD, SOL_SOCKET, SO_USELOOPBACK,(char *) NULL, 0);
X#ifdef SO_DONTLINGER
X (void) setsockopt(ServerFD, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0);
X#endif
X
X debug(4,(stderr, "try to connect on %s\n", hostName));
X
X hp = gethostbyname(hostName);
X if (hp == 0)
X {
X perror("gethostbyname failed");
X debug(1,(stderr, "gethostbyname failed for %s\n", hostName));
X panic("Can't open connection to Server");
X }
X
X sin.sin_family = AF_INET;
X bcopy((char *)hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
X sin.sin_port = htons (GetServerport());
X
X /* ******************************************************** */
X /* try to connect to Server */
X
X if (connect(ServerFD, (struct sockaddr *)&sin, sizeof(sin)) < 0)
X {
X debug(4,(stderr, "connect returns errno of %d\n", errno));
X if (errno != 0)
X perror("connect");
X switch (errno)
X {
X case ECONNREFUSED:
X /* experience says this is because there is no Server
X to connect to */
X close(ServerFD);
X debug(1,(stderr, "No Server\n"));
X panic("Can't open connection to Server");
X default:
X close(ServerFD);
X panic("Can't open connection to Server");
X }
X }
X
X debug(4,(stderr, "Connect To Server: FD %d\n", ServerFD));
X return(ServerFD);
X}
X
Xstatic char*
XOfficialName(name)
Xchar *name;
X{
X struct hostent *HostEntry;
X
X HostEntry = gethostbyname(name);
X if (HostEntry == NULL)
X {
X perror("gethostbyname");
X exit(-1);
X }
X debug(4,(stderr, "Official name of %s is %s\n", name, HostEntry->h_name));
X return(HostEntry->h_name);
X}
X
Xstatic void
XSignalURG()
X{
X debug(1,(stderr, "==> SIGURG received\n"));
X}
X
Xstatic void
XSignalPIPE()
X{
X debug(1,(stderr, "==> SIGPIPE received\n"));
X}
X
Xstatic void
XSignalINT()
X{
X debug(1,(stderr, "==> SIGINT received\n"));
X exit(1);
X}
X
Xstatic void
XSignalQUIT()
X{
X debug(1,(stderr, "==> SIGQUIT received\n"));
X exit(1);
X}
X
Xstatic void
XSignalTERM()
X{
X debug(1,(stderr, "==> SIGTERM received\n"));
X exit(1);
X}
X
Xstatic void
XSignalTSTP()
X{
X debug(1,(stderr, "==> SIGTSTP received\n"));
X}
X
Xstatic void
XSignalCONT()
X{
X debug(1,(stderr, "==> SIGCONT received\n"));
X}
X
XGlobal void
Xenterprocedure(s)
X char *s;
X{
X debug(2,(stderr, "-> %s\n", s));
X}
X
XGlobal void
Xpanic(s)
X char *s;
X{
X fprintf(stderr, "%s\n", s);
X exit(1);
X}
SHAR_EOF
$TOUCH -am 0903162990 main.c &&
chmod 0664 main.c ||
echo "restore of main.c failed"
set `wc -c main.c`;Wc_c=$1
if test "$Wc_c" != "30426"; then
echo original size 30426, current size $Wc_c
fi
fi
# ============= prtype.c ==============
if test X"$1" != X"-c" -a -f 'prtype.c'; then
echo "File already exists: skipping 'prtype.c'"
else
echo "x - extracting prtype.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > prtype.c &&
X/*
X * Project: XMON - An X protocol monitor
X *
X * File: prtype.c
X *
X * Description: Type Printing for X11 protocol
X *
X * For each of the types we need a way to print that type. Types are of
X * varieties:
X *
X * (1) BUILTIN -- we have a separate routine to interpret and print each
X * built-in type.
X *
X * (2) ENUMERATED, SET -- we have one routine which prints, given the data
X * and the list of values.
X *
X * (3) RECORDS -- a separate routine for each to print each field.
X */
X
X#include "common.h"
X
X#include "xmond.h"
X#include "x11.h"
X
X/*
X * we use indentation for two purposes:
X *
X * (1) To show substructure of records inside records ...
X *
X * (2) To separate the bytes from the client (on the left) from those from
X * the server (on the right).
X *
X * Each indention level is one tab (8 spaces).
X */
X#define MaxIndent 10
X
X#define NumberofAtoms 68
X#define MAXline 78
X
X/* function prototypes: */
X/* prtype.c: */
Xstatic char *printrep P((unsigned short c ));
Xstatic short SizeofLeader P((void ));
X
X/* end function prototypes */
X
Xextern int CurrentVerbose;
Xextern int debuglevel;
X
Xstatic char Leader[MaxIndent + 1];
Xstatic short CurrentLevel = 0;
X
Xstatic char *AtomTable[NumberofAtoms + 1] =
X{
X "NONE", "PRIMARY", "SECONDARY", "ARC", "ATOM", "BITMAP", "CARDINAL",
X "COLORMAP", "CURSOR", "CUT_BUFFER0", "CUT_BUFFER1", "CUT_BUFFER2",
X "CUT_BUFFER3", "CUT_BUFFER4", "CUT_BUFFER5", "CUT_BUFFER6",
X "CUT_BUFFER7", "DRAWABLE", "FONT", "INTEGER", "PIXMAP", "POINT",
X "RECTANGLE", "RESOURCE_MANAGER", "RGB_COLOR_MAP", "RGB_BEST_MAP",
X "RGB_BLUE_MAP", "RGB_DEFAULT_MAP", "RGB_GRAY_MAP", "RGB_GREEN_MAP",
X "RGB_RED_MAP", "STRING", "VISUALID", "WINDOW", "WM_COMMAND",
X "WM_HINTS", "WM_CLIENT_MACHINE", "WM_ICON_NAME", "WM_ICON_SIZE",
X "WM_NAME", "WM_NORMAL_HINTS", "WM_SIZE_HINTS", "WM_ZOOM_HINTS",
X "MIN_SPACE", "NORM_SPACE", "MAX_SPACE", "END_SPACE", "SUPERSCRIPT_X",
X "SUPERSCRIPT_Y", "SUBSCRIPT_X", "SUBSCRIPT_Y", "UNDERLINE_POSITION",
X "UNDERLINE_THICKNESS", "STRIKEOUT_ASCENT", "STRIKEOUT_DESCENT",
X "ITALIC_ANGLE", "X_HEIGHT", "QUAD_WIDTH", "WEIGHT", "POINT_SIZE",
X "RESOLUTION", "COPYRIGHT", "NOTICE", "FONT_NAME", "FAMILY_NAME",
X "FULL_NAME", "CAP_HEIGHT", "WM_CLASS", "WM_TRANSIENT_FOR"
X };
X
X/*
X * printrep:
X *
X * print representation of a character for debugging
X */
Xstatic char*
Xprintrep (c)
X unsigned short c;
X{
X static char pr[8];
X
X if (c < 32)
X {
X /* control characters */
X pr[0] = '^';
X pr[1] = c + 64;
X pr[2] = '\0';
X }
X else if (c < 127)
X {
X /* printing characters */
X pr[0] = c;
X pr[1] = '\0';
X }
X else if (c == 127)
X return("<del>");
X else if (c <= 0377)
X {
X /* upper 128 codes from 128 to 255; print as \ooo - octal */
X pr[0] = '\\';
X pr[3] = '0' + (c & 7);
X c = c >> 3;
X pr[2] = '0' + (c & 7);
X c = c >> 3;
X pr[1] = '0' + (c & 3);
X pr[4] = '\0';
X }
X else
X {
X /* very large number -- print as 0xffff - 4 digit hex */
X sprintf(pr, "0x%04x", c);
X }
X return(pr);
X}
X
XGlobal void
XSetIndentLevel(which)
X short which;
X{
X short i;
X
X if (which > MaxIndent)
X which = MaxIndent;
X if (which < 0)
X which = 0;
X if (which == CurrentLevel)
X return;
X
X /* set the indent level to <which> */
X /* -> set the Print Leader to <which> tabs */
X for (i = 0; i < which; i++)
X Leader[i] = '\t';
X Leader[which] = '\0';
X CurrentLevel = which;
X}
X
XGlobal void
XModifyIndentLevel(amount)
X short amount;
X{
X SetIndentLevel(CurrentLevel + amount);
X}
X
Xstatic short
XSizeofLeader ()
X{
X return (CurrentLevel * 8);
X}
X
X/*
X * DumpItem:
X *
X * if we want verbose enough output, we will dump the buffer in hex
X */
XGlobal void
XDumpItem(name, fd, buf, n)
X char *name;
X int fd;
X unsigned char *buf;
X long n;
X{
X if (n == 0)
X return;
X
X fprintf(stdout, "%s%20s (fd %d): ", Leader, name, fd);
X
X DumpHexBuffer(buf, n);
X fprintf(stdout, "\n");
X}
X
XGlobal void
XPrintINT8(buf)
X unsigned char *buf;
X{
X /* print a INT8 -- 8-bit signed integer */
X short n = IByte (buf);
X if (n > 127)
X n = 256 - n;
X fprintf(stdout, "%d", n);
X}
X
XGlobal void
XPrintINT16(buf)
X unsigned char *buf;
X{
X /* print a INT16 -- 16-bit signed integer */
X long n = IShort (buf);
X if (n > 32767)
X n = 65536 - n;
X fprintf(stdout, "%d", n);
X}
X
XGlobal void
XPrintINT32(buf)
X unsigned char *buf;
X{
X /* print a INT32 -- 32-bit signed integer */
X long n = ILong (buf);
X fprintf(stdout, "%d", n);
X}
X
XGlobal void
XPrintCARD8(buf)
X unsigned char *buf;
X{
X /* print a CARD8 -- 8-bit unsigned integer */
X short n = IByte (buf);
X fprintf(stdout, "%02x", (unsigned)(n & 0xff));
X}
X
XGlobal void
XPrintCARD16(buf)
X unsigned char *buf;
X{
X /* print a CARD16 -- 16-bit unsigned integer */
X unsigned long n = IShort (buf);
X fprintf(stdout, "%04x", (unsigned)(n & 0xffff));
X}
X
XGlobal int
XPrintCARD32(buf)
X unsigned char *buf;
X{
X /* print a CARD32 -- 32-bit unsigned integer */
X unsigned long n = ILong (buf);
X fprintf(stdout, "%08x", n);
X return(4);
X}
X
XGlobal int
XPrintBYTE(buf)
X unsigned char *buf;
X{
X /* print a BYTE -- 8-bit value */
X short n = IByte (buf);
X fprintf(stdout, "%02x", n);
X return(1);
X}
X
XGlobal int
XPrintCHAR8(buf)
X unsigned char *buf;
X{
X /* print a CHAR8 -- 8-bit character */
X unsigned short n = IByte (buf);
X fprintf(stdout, "%s", printrep(n));
X return(1);
X}
X
XGlobal int
XPrintSTRING16(buf)
X unsigned char *buf;
X{
X /* print a CHAR16 -- 16-bit character */
X unsigned short n = IShort (buf);
X fprintf(stdout, "%s", printrep(n));
X return(1);
X}
X
XGlobal int
XPrintSTR(buf)
X unsigned char *buf;
X{
X /* STR have the length (1 byte) then a string of CHAR8 */
X short n;
X short i;
X
X n = IByte(buf++);
X for (i = 0; i < n; i++)
X fprintf(stdout, "%s", printrep(buf[i]));
X return(n+1);
X}
X
XGlobal int
XPrintWINDOW(buf)
X unsigned char *buf;
X{
X /* print a WINDOW -- CARD32 plus 0 = None */
X long n = ILong (buf);
X if (n == 0)
X fprintf(stdout, "None");
X else
X fprintf(stdout, "WIN %08x", n);
X return(4);
X}
X
XGlobal void
XPrintWINDOWD(buf)
X unsigned char *buf;
X{
X /* print a WINDOWD -- CARD32 plus 0 = PointerWindow, 1 = InputFocus */
X long n = ILong (buf);
X if (n == 0)
X fprintf(stdout, "PointerWindow");
X else if (n == 1)
X fprintf(stdout, "InputFocus");
X else
X PrintWINDOW(buf);
X}
X
XGlobal void
XPrintWINDOWNR(buf)
X unsigned char *buf;
X{
X /* print a WINDOWNR -- CARD32 plus 0 = None, 1 = PointerRoot */
X long n = ILong (buf);
X if (n == 0)
X fprintf(stdout, "None");
X else if (n == 1)
X fprintf(stdout, "PointerRoot");
X else
X PrintWINDOW(buf);
X}
X
X
XGlobal void
XPrintPIXMAP(buf)
X unsigned char *buf;
X{
X /* print a PIXMAP -- CARD32 plus 0 = None */
X long n = ILong (buf);
X if (n == 0)
X fprintf(stdout, "None");
X else
X fprintf(stdout, "PXM %08x", n);
X}
X
XGlobal void
XPrintPIXMAPNPR(buf)
X unsigned char *buf;
X{
X /* print a PIXMAPNPR -- CARD32 plus 0 = None, 1 = ParentRelative */
X long n = ILong (buf);
X if (n == 0)
X fprintf(stdout, "None");
X else if (n == 1)
X fprintf(stdout, "ParentRelative");
X else
X PrintPIXMAP(buf);
X}
X
XGlobal void
XPrintPIXMAPC(buf)
X unsigned char *buf;
X{
X /* print a PIXMAPC -- CARD32 plus 0 = CopyFromParent */
X long n = ILong (buf);
X if (n == 0)
X fprintf(stdout, "CopyFromParent");
X else
X PrintPIXMAP(buf);
X}
X
X
XGlobal void
XPrintCURSOR(buf)
X unsigned char *buf;
X{
X /* print a CURSOR -- CARD32 plus 0 = None */
X long n = ILong (buf);
X if (n == 0)
X fprintf(stdout, "None");
X else
X fprintf(stdout, "CUR %08x", n);
X}
X
X
XGlobal void
XPrintFONT(buf)
X unsigned char *buf;
X{
X /* print a FONT -- CARD32 plus 0 = None */
X long n = ILong (buf);
X if (n == 0)
X fprintf(stdout, "None");
X else
X fprintf(stdout, "FNT %08x", n);
X}
X
X
XGlobal void
XPrintGCONTEXT(buf)
X unsigned char *buf;
X{
X /* print a GCONTEXT -- CARD32 */
X long n = ILong (buf);
X fprintf(stdout, "GXC %08x", n);
X}
X
X
XGlobal int
XPrintCOLORMAP(buf)
X unsigned char *buf;
X{
X /* print a COLORMAP -- CARD32 plus 0 = None */
X long n = ILong (buf);
X if (n == 0)
X fprintf(stdout, "None");
X else
X fprintf(stdout, "CMP %08x", n);
X return(4);
X}
X
XGlobal void
XPrintCOLORMAPC(buf)
X unsigned char *buf;
X{
X /* print a COLORMAPC -- CARD32 plus 0 = CopyFromParent */
X long n = ILong (buf);
X if (n == 0)
X fprintf(stdout, "CopyFromParent");
X else
X PrintCOLORMAP(buf);
X}
X
X
XGlobal void
XPrintDRAWABLE(buf)
X unsigned char *buf;
X{
X /* print a DRAWABLE -- CARD32 */
X long n = ILong (buf);
X fprintf(stdout, "DWB %08x", n);
X}
X
XGlobal void
XPrintFONTABLE(buf)
X unsigned char *buf;
X{
X /* print a FONTABLE -- CARD32 */
X long n = ILong (buf);
X fprintf(stdout, "FTB %08x", n);
X}
X
X/*
X * For atoms, we print the built-in atoms. We could expand to printing
X * the user defined ones, too.
X */
X
XGlobal int
XPrintATOM(buf)
X unsigned char *buf;
X{
X /* print a ATOM -- CARD32 plus 0 = None */
X long n = ILong (buf);
X if (0 <= n && n <= NumberofAtoms)
X fprintf(stdout, "<%s>", AtomTable[n]);
X else
X fprintf(stdout, "ATM %08x", n);
X return(4);
X}
X
XGlobal void
XPrintATOMT(buf)
X unsigned char *buf;
X{
X /* print a ATOMT -- CARD32 plus 0 = AnyPropertyType */
X long n = ILong (buf);
X if (n == 0)
X fprintf(stdout, "AnyPropertyType");
X else
X PrintATOM(buf);
X}
X
X
XGlobal void
XPrintVISUALID(buf)
X unsigned char *buf;
X{
X /* print a VISUALID -- CARD32 plus 0 = None */
X long n = ILong (buf);
X if (n == 0)
X fprintf(stdout, "None");
X else
X fprintf(stdout, "VIS %08x", n);
X}
X
XGlobal void
XPrintVISUALIDC(buf)
X unsigned char *buf;
X{
X /* print a VISUALIDC -- CARD32 plus 0 = CopyFromParent */
X long n = ILong (buf);
X if (n == 0)
X fprintf(stdout, "CopyFromParent");
X else
X PrintVISUALID(buf);
X}
X
X
XGlobal void
XPrintTIMESTAMP(buf)
X unsigned char *buf;
X{
X /* print a TIMESTAMP -- CARD32 plus 0 as the current time */
X long n = ILong (buf);
X if (n == 0)
X fprintf(stdout, "CurrentTime");
X else
X fprintf(stdout, "TIM %08x", n);
X}
X
X
XGlobal void
XPrintRESOURCEID(buf)
X unsigned char *buf;
X{
X /* print a RESOURCEID -- CARD32 plus 0 = AllTemporary */
X long n = ILong (buf);
X if (n == 0)
X fprintf(stdout, "AllTemporary");
X else
X fprintf(stdout, "RID %08x", n);
X}
X
X
XGlobal int
XPrintKEYSYM(buf)
X unsigned char *buf;
X{
X /* print a KEYSYM -- CARD32 */
X long n = ILong (buf);
X fprintf(stdout, "KYS %08x", n);
X return(4);
X}
X
XGlobal int
XPrintKEYCODE(buf)
X unsigned char *buf;
X{
X /* print a KEYCODE -- CARD8 */
X unsigned short n = IByte (buf);
X fprintf(stdout, "%d (%s)", n, printrep(n));
X return(1);
X}
X
XGlobal void
XPrintKEYCODEA(buf)
X unsigned char *buf;
X{
X /* print a KEYCODEA -- CARD8 plus 0 = AnyKey */
X long n = IByte (buf);
X if (n == 0)
X fprintf(stdout, "AnyKey");
X else
X PrintKEYCODE(buf);
X}
X
X
XGlobal void
XPrintBUTTON(buf)
X unsigned char *buf;
X{
X /* print a BUTTON -- CARD8 */
X unsigned short n = IByte (buf);
X fprintf(stdout, "%d (%s)", n, printrep(n));
X}
X
XGlobal void
XPrintBUTTONA(buf)
X unsigned char *buf;
X{
X /* print a BUTTONA -- CARD8 plus 0 = AnyButton */
X long n = IByte (buf);
X if (n == 0)
X fprintf(stdout, "AnyButton");
X else
X PrintBUTTON(buf);
X}
X
X
X/*
X * PrintEVENTFORM:
X *
X * This is an interesting cheat -- we call DecodeEvent to print an event
X * should work, but its never been tried.
X */
XGlobal void
XPrintEVENTFORM(buf)
X unsigned char *buf;
X{
X /* print an EVENT_FORM -- event format */
X fprintf(stdout, "PrintEVENTFORM: calling DecodeEvent with NULL server!\n");
X DecodeEvent((Server *)NULL, buf, (long)-1);
X}
X
XGlobal void
XPrintENUMERATED(buf, length, ValueList)
X unsigned char *buf;
X short length;
X struct ValueListEntry *ValueList;
X{
X long n;
X struct ValueListEntry *p;
X
X if (length == 1)
X n = IByte(buf);
X else if (length == 2)
X n = IShort(buf);
X else
X n = ILong(buf);
X
X p = ValueList;
X while (p != NULL && p->Value != n)
X p = p->Next;
X
X if (p != NULL)
X fprintf(stdout, "%s", p->Name);
X else
X fprintf(stdout, "**INVALID** (%d)", n);
X}
X
XGlobal void
XPrintSET(buf, length, ValueList)
X unsigned char *buf;
X short length;
X struct ValueListEntry *ValueList;
X{
X unsigned long n;
X struct ValueListEntry *p;
X Bool MatchesAll = False;
X Bool FoundOne = False;
X
X if (length == 1)
X n = IByte(buf);
X else if (length == 2)
X n = IShort(buf);
X else
X n = ILong(buf);
X
X if (n != 0)
X {
X /* first check if the value matches ALL of the bits. */
X MatchesAll = True;
X for (p = ValueList; MatchesAll && (p != NULL); p = p->Next)
X {
X if ((p->Value & n) == 0)
X MatchesAll = False;
X }
X
X if (!MatchesAll)
X /* if it matches some but not all print only those it matches */
X for (p = ValueList; p != NULL; p = p->Next)
X {
X if ((p->Value & n) != 0)
X {
X if (FoundOne)
X fprintf(stdout, " | ");
X fprintf(stdout, "%s", p->Name);
X FoundOne = True;
X }
X }
X }
X
X if (MatchesAll)
X fprintf(stdout, "<ALL>");
X else if (!FoundOne)
X fprintf(stdout, "0");
X}
X
XGlobal void
XPrintField(buf, start, length, FieldType, name)
X unsigned char *buf;
X short start;
X short length;
X short FieldType;
X char *name;
X{
X if (length == 0)
X return;
X if (CurrentVerbose <= 0)
X return;
X
X fprintf(stdout, "%s%20s: ", Leader, name);
X
X if (debuglevel & 8)
X DumpHexBuffer(&(buf[start]), (long)length);
X
X switch (TD[FieldType].Type)
X {
X case BUILTIN:
X (*TD[FieldType].PrintProc)(&buf[start]);
X break;
X
X case ENUMERATED:
X PrintENUMERATED(&buf[start], length, TD[FieldType].ValueList);
X break;
X
X case SET:
X PrintSET(&buf[start], length, TD[FieldType].ValueList);
X break;
X
X case RECORD:
X ModifyIndentLevel(1);
X fprintf(stdout, "\n");
X if (CurrentVerbose < 3)
X return;
X (*TD[FieldType].PrintProc)(&buf[start]);
X ModifyIndentLevel(-1);
X break;
X }
X fprintf(stdout, "\n");
X fflush(stdout);
X}
X
X/*
X * PrintList:
X *
X * Print a list of things. The things are of type <ListType>.
X * They start at <buf>. There are <number> things in the list
X */
XGlobal int
XPrintList(buf, number, ListType, name)
X unsigned char *buf;
X long number;
X short ListType;
X char *name;
X{
X long n;
X long i;
X long sum;
X
X if (number == 0)
X return(0);
X
X fprintf(stdout, "%s%20s: (%d)\n", Leader, name, number);
X if (CurrentVerbose < 3)
X return(0);
X
X ModifyIndentLevel(1);
X sum = 0;
X for (i = 0; i < number; i++)
X {
X switch (TD[ListType].Type)
X {
X case BUILTIN:
X n = (*TD[ListType].PrintProc)(buf);
X break;
X case RECORD:
X n = (*TD[ListType].PrintProc)(buf);
X break;
X default:
X fprintf(stdout, "**INVALID**");
X n = 0;
X break;
X }
X buf = buf + n;
X sum = sum + n;
X fprintf(stdout, "%s---\n", Leader);
X }
X
X ModifyIndentLevel(-1);
X return(sum);
X}
X
X/*
X * PrintListSTR:
X *
X * Print a list of STRs. Similar to PrintList
X * They start at <buf>. There are <number> things in the list
X */
XGlobal void
XPrintListSTR(buf, number, name)
X unsigned char *buf;
X long number;
X char *name;
X{
X long n;
X long i;
X long sum;
X
X if (number == 0)
X return;
X
X fprintf(stdout, "%s%20s: (%d)\n", Leader, name, number);
X if (CurrentVerbose < 3)
X return;
X
X ModifyIndentLevel(1);
X sum = 0;
X for (i = 0; i < number; i++)
X {
X fprintf(stdout, "%s", Leader);
X n = PrintSTR(buf);
X buf = buf + n;
X sum = sum + n;
X fprintf(stdout, "\n");
X }
X
X ModifyIndentLevel(-1);
X return;
X}
X
XGlobal int
XPrintBytes(buf, number, name)
X unsigned char buf[];
X long number;
X char *name;
X{
X /* print a list of BYTE -- 8-bit character */
X long i;
X short column;
X
X if (number == 0)
X return(0);
X
X fprintf(stdout, "%s%20s: ", Leader, name);
X column = SizeofLeader() + 25;
X for (i = 0; i < number; i++)
X {
X if (column > 80)
X {
X if (CurrentVerbose < 3)
X break;
X fprintf(stdout, "\n%s%20s: ", Leader, "");
X column = SizeofLeader() + 25;
X }
X fprintf(stdout, "%02x ",((unsigned int) buf[i]));
X column += 3;
X }
X fprintf(stdout, "\n");
X
X return((int)number);
X}
X
X/*
X * print a String of CHAR8 -- 8-bit characters
X */
XGlobal int
XPrintString8(buf, number, name)
X unsigned char buf[];
X short number;
X char *name;
X{
X short i;
X
X if (number == 0)
X return(0);
X
X fprintf(stdout, "%s%20s: \"", Leader, name);
X for (i = 0; i < number; i++)
X fprintf(stdout, "%s", printrep(buf[i]));
X fprintf(stdout, "\"\n");
X
X return(number);
X}
X
X/*
X * print a String of CHAR16 -- 16-bit characters
X */
XGlobal int
XPrintString16(buf, number, name)
X unsigned char buf[];
X short number;
X char *name;
X{
X short i;
X unsigned short c;
X
X if (number == 0)
X return(0);
X
X fprintf(stdout, "%s%20s: \"", Leader, name);
X for (i = 0; i < number; i += 2)
X {
X c = IShort(&buf[i]);
X fprintf(stdout, "%s", printrep(c));
X }
X fprintf(stdout, "\"\n");
X
X return(number);
X}
X
X/*
X A Value List is two things:
X
X (1) A controlling bitmask. For each one bit in the control,
X a value is in the list.
X (2) A list of values.
X*/
X
XGlobal void
XPrintValues(control, clength, ctype, values, name)
X unsigned char *control;
X short clength;
X short ctype;
X unsigned char *values;
X char *name;
X{
X long cmask;
X struct ValueListEntry *p;
X
X /* first get the control mask */
X if (clength == 1)
X cmask = IByte(control);
X else if (clength == 2)
X cmask = IShort(control);
X else
X cmask = ILong(control);
X
X /* now if it is zero, ignore and return */
X if (cmask == 0)
X return;
X
X /* there are bits in the controlling bitmask, figure out which */
X /* the ctype is a set type, so this code is similar to PrintSET */
X fprintf(stdout, "%s%20s:\n", Leader, name);
X ModifyIndentLevel(1);
X for (p = TD[ctype].ValueList; p != NULL; p = p->Next)
X {
X if ((p->Value & cmask) != 0)
X {
X short m = 4 - p->Length;
X PrintField(values, m, p->Length, p->Type, p->Name);
X values += 4;
X }
X }
X ModifyIndentLevel(-1);
X}
X
X/* PolyText8 and PolyText16 take lists of characters with possible
X font changes in them. */
X
XGlobal void
XPrintTextList8(buf, length, name)
X unsigned char *buf;
X short length;
X char *name;
X{
X short n;
X
X fprintf(stdout, "%s%20s:\n", Leader, name);
X while (length > 1)
X {
X n = IByte(&buf[0]);
X if (n != 255)
X {
X PrintField(buf, 1, 1, INT8, "delta");
X PrintString8(&buf[2], n, "text item 8 string");
X buf += n + 2;
X length -= n + 2;
X }
X else
X {
X PrintField(buf, 1, 4, FONT, "font-shift-id");
X buf += 4;
X length -= 4;
X }
X }
X}
X
XGlobal void
XPrintTextList16(buf, length, name)
X unsigned char *buf;
X short length;
X char *name;
X{
X short n;
X
X fprintf(stdout, "%s%20s:\n", Leader, name);
X while (length > 1)
X {
X n = IByte(&buf[0]);
X if (n != 255)
X {
X PrintField(buf, 1, 1, INT8, "delta");
X PrintString16(&buf[2], n, "text item 16 string");
X buf += n + 2;
X length -= n + 2;
X }
X else
X {
X PrintField(buf, 1, 4, FONT, "font-shift-id");
X buf += 4;
X length -= 4;
X }
X }
X}
X
XGlobal void
XDumpHexBuffer(buf, n)
X unsigned char *buf;
X long n;
X{
X short i;
X short column;
X char h[6] /* one hex or octal character */ ;
X
X column = 27 + SizeofLeader();
X for (i = 0; i < n; i++)
X {
X /* get the hex representations */
X sprintf(h, "%02x",(0xff & buf[i]));
X
X /* check if these characters will fit on this line */
X if ((column + strlen(h) + 1) > MAXline)
X {
X /* line will be too long -- print it */
X fprintf(stdout, "\n");
X column = 0;
X }
X fprintf(stdout, "%s ", h);
X column += 3;
X }
X}
SHAR_EOF
$TOUCH -am 0903162990 prtype.c &&
chmod 0664 prtype.c ||
echo "restore of prtype.c failed"
set `wc -c prtype.c`;Wc_c=$1
if test "$Wc_c" != "19125"; then
echo original size 19125, current size $Wc_c
fi
fi
echo "End of part 3, continue with part 4"
exit 0
dan
----------------------------------------------------
O'Reilly && Associates argv at sun.com / argv at ora.com
Opinions expressed reflect those of the author only.
More information about the Comp.sources.x
mailing list