home *** CD-ROM | disk | FTP | other *** search
-
- /* SOURCE FILE *****************************************************
- * WTCOMM.C - Writing Tools Communication interface
- *******************************************************************
- * Copyright (C) 1992, 1993 WordPerfect Corp., All Rights Reserved
- *******************************************************************/
-
- #include "wtapi.h"
- #include "wtcomm.h"
-
- #include <string.h>
- #include <fcntl.h>
- #include <limits.h> /* for PIPE_BUF */
- #ifdef LINUX
- #include <linux/limits.h> /* for PIPE_BUF */
- #endif
- #include <signal.h>
- #include <sys/errno.h>
- #include <Xm/Xm.h>
-
- /***** DEFINE THE APPROPRIATE ITEM TO USE THE CODE FOR WRITING *****/
- /***** TOOL SERVERS OR WRITING TOOL CLIENTS (OR BOTH). *****/
- /* define WTAPI_SERVER */
- /* define WTAPI_CLIENT */
-
-
- /*----------------------------------------------------------
- External Variables
- ------------------------------------------------------------*/
- extern int errno;
-
- /*----------------------------------------------------------
- External Functions
- ------------------------------------------------------------*/
- void quitTool(char *);
-
- /*----------------------------------------------------------
- Internal Variables
- ------------------------------------------------------------*/
- #ifdef WTAPI_CLIENT
- WTCOMM commHandle; /* conversation/comm. handle */
- #else
- extern WTCOMM comm_id;
- #endif /* WTAPI_CLIENT */
- static char *SndMessage; /* message to send */
- static char *RcvMessage; /* received message */
- static short MsgLen; /* number of bytes in message */
- static short NeedModalReply = 0; /* waiting for modal reply? */
- static short NeedRequestReply = 0; /* waiting for reply to request? */
- static void (*oldsigfunc)();
-
- /*----------------------------------------------------------
- Internal Functions
- ------------------------------------------------------------*/
- MSG_ERRS ReceiveMsg(WTPIPE, char *);
- MSG_ERRS SendMsg(WTPIPE, char *, char *, MSG_TYPE, char *, int);
- MSG_ERRS SendMsgModal(WTPIPE, char *, char *, MSG_TYPE, char *, int);
- MSG_ERRS SendRequestAct(WTPIPE,char *,char *,MSG_TYPE,char *,int,FUNCP);
- static PIPE_ERRS readpipe(int, char **, short *);
- static PIPE_ERRS writepipe(int, char *, short);
- static MSG_ERRS DoSend(WTPIPE,char *,char *,MSG_TYPE,char *,int,SEND_TYPE);
-
- #ifdef WTAPI_CLIENT
- WTCOMM WtConnect(Widget, char *);
- void WtDisconnect(WTCOMM);
- static void WtClMsgReceived(XtPointer, int *, XtInputId *);
- static WTSTATUS wtClReceiveMsg(char *, char *);
- #endif /* WTAPI_CLIENT */
-
- #ifdef WTAPI_SERVER
- WTCOMM WTInitComm(Widget, char *, int, int);
- void WTCloseComm(WTCOMM);
- static void WtTlMsgReceived(XtPointer, int *, XtInputId *);
- static WTSTATUS wtTlReceiveMsg(char *, char *);
- #endif /* WTAPI_SERVER */
-
- /*COMMENT***************************************************
- ;readpipe
- Title: Read a message from a pipe.
- In: fd - file descriptor to read from
- Out: mess - pointer to message (USER MUST FREE THIS MEMORY!!!)
- cnt - number of bytes in message
- Xin: none
- Xout: none
- Return: status of read
- Notes: THE VARIABLE TYPE OF msgsiz MUST NOT CHANGE!!!
- ***********************************************************/
- static PIPE_ERRS readpipe(int fd, char **mess, short *cnt)
- {
- short msgsiz = 0; /* number of bytes in message on pipe */
- char *msgbuf; /* pointer to buffer to read message into */
- int rdcnt = 0; /* number of bytes read from pipe */
-
- *mess = 0;
- *cnt = 0;
- /*
- * Read the size of the next message from the pipe.
- */
- while ((rdcnt = read(fd, (char *)&msgsiz, sizeof(msgsiz))) == -1) {
- if (errno != EINTR) { /* were we interrupted? */
- return(PIPE_ERROR); /* no, return error */
- } /* yes, do read again */
- }
- if (rdcnt != sizeof(msgsiz)) {
- return(PIPE_ERROR); /* return error */
- }
- /*
- * Allocate space and read the next message from the pipe.
- */
- if (!(msgbuf = (char *)malloc(msgsiz))) {
- return(PIPE_NOMEM); /* return error */
- }
- while ((rdcnt = read(fd, msgbuf, msgsiz)) == -1) {
- if (errno != EINTR) { /* were we interrupted? */
- free(msgbuf); /* no, return error */
- return(PIPE_ERROR);
- } /* yes, do read again */
- }
- if (!rdcnt) { /* partner die or close pipe? */
- free(msgbuf); /* yes */
- return(PIPE_DOWN);
- }
- if (rdcnt != msgsiz) { /* read correct number of bytes? */
- free(msgbuf); /* no, return error */
- return(PIPE_ERROR);
- }
- *mess = msgbuf; /* user must free this memory */
- *cnt = msgsiz;
- return(PIPE_OK);
- } /* readpipe */
-
- /*COMMENT***************************************************
- ;writepipe
- Title: Write a message to a pipe.
- In: fd - file descriptor to write to
- mess - pointer to message
- cnt - number of bytes in message
- Out: none
- Xin: none
- Xout: none
- Return: status of write
- Notes: THE VARIABLE TYPE OF msgsiz MUST NOT CHANGE!!!
- ***********************************************************/
- static PIPE_ERRS writepipe(int fd, char *mess, short cnt)
- {
- short msgsiz = cnt; /* number of bytes of message on pipe */
- int wrtcnt = 0; /* number of bytes written to pipe */
- char *data = NULL; /* pointer to mess data */
- int remainingsize = 0;
- int sendamount = 0;
-
-
- /*
- * Write the size of the message to the pipe.
- */
- while ((wrtcnt = write(fd, (char *)&msgsiz, sizeof(msgsiz))) == -1) {
- if (errno != EINTR) { /* were we interrupted? */
- return(PIPE_ERROR); /* no, return error */
- } /* yes, do write again */
- }
- if (wrtcnt != sizeof(msgsiz)) {
- return(PIPE_ERROR); /* return error */
- }
- /*
- * Write the message to the pipe.
- */
- data = mess;
- remainingsize = (int) msgsiz;
- /* If on a HP700 or SCO UNIX, then you may need to uncomment this line: */
- /* #define PIPE_BUF 4096 */
- while (data && (remainingsize > 0)) {
- if( remainingsize > PIPE_BUF) { /* don't send more than the pipe can handle */
- sendamount = PIPE_BUF;
- } else {
- sendamount = (int) remainingsize;
- }
- while ((wrtcnt = write(fd, data, msgsiz)) == -1) {
- if (errno != EINTR) { /* were we interrupted? */
- return(PIPE_ERROR); /* no, return error */
- } /* yes, do write again */
- }
- data += wrtcnt; /* move the pointer past bytes that were sent */
- remainingsize -= wrtcnt;
- }
- return(PIPE_OK);
- } /* writepipe */
-
- /*COMMENT***************************************************
- ;ReceiveMsg
- Title: Get the next message on the pipe.
- In: pipe - read/write file descriptors
- caller - name of application which called ReceiveMsg()
- Out: none
- Xin: none
- Xout: none
- Return: MSG_OK or error
- Notes:
- ***********************************************************/
- MSG_ERRS ReceiveMsg(WTPIPE pipe, char *caller)
- {
- PIPE_ERRS stat; /* status of pipe read/writes */
- MSG_TYPE msgtype; /* message type */
- SEND_TYPE sendtype; /* type of message send */
- char *sender; /* sender of the message */
- char *body; /* beginning of body of message */
- short result = MSG_OK; /* result of a modal send */
- char rbuf[4];
-
- /*
- * Read the next message off the pipe.
- */
- stat = readpipe(pipe.read, &RcvMessage, &MsgLen);
- if ((stat != PIPE_OK) || !RcvMessage) {
- if (RcvMessage) {
- free(RcvMessage);
- RcvMessage = 0;
- }
- return(MSG_CANT_RECEIVE);
- }
- /*
- * Get the message type, send type, and sender and find the beginning
- * of the message body.
- */
- msgtype = RcvMessage[0];
- sendtype = RcvMessage[1];
- sender = &RcvMessage[2];
- body = sender + strlen(sender) + 1;
- /*
- * If this is a REPLY, check to see if it is the REPLY sent in response
- * to a modal send. If so clear the NeedModalReply flag and return
- * the status. If not, this REPLY must be a response to SendRequestAct()
- * so clear the NeedRequestReply flag. This will result in the exit of
- * the loop in SendRequestAct() and it will proceed to handle the reply
- * message.
- */
- if (msgtype == REPLY) {
- if (NeedModalReply) {
- /*
- * If the body of the message is exactly the size of the result
- * variable then assume it is a modal reply and return the
- * result. Currently all other reply messages are larger than
- * two bytes.
- */
- if ((MsgLen - (body - RcvMessage)) == sizeof(result)) {
- memcpy((char *)&result, body, sizeof(result));
- NeedModalReply = 0; /* clear flag */
- free(RcvMessage); RcvMessage = 0;
- return(result);
- }
- } else if (NeedRequestReply) {
- NeedRequestReply = 0;
- /* don't free RcvMessage yet, used in SendRequestAct() */
- return(MSG_OK);
- }
- free(RcvMessage); RcvMessage = 0;
- return(MSG_OK);
- }
- switch (msgtype) {
- #ifdef WTAPI_CLIENT
- case WTAPI_TOOL_COMMAND:
- wtClReceiveMsg(sender, body);
- break;
- case WTAPI_TOOL_QUERY:
- wtClReceiveMsg(sender, body);
- break;
- #endif /* WTAPI_CLIENT */
- #ifdef WTAPI_SERVER
- case WTAPI_CLIENT_COMMAND:
- wtTlReceiveMsg(sender, body);
- break;
- case WTAPI_CLIENT_QUERY:
- wtTlReceiveMsg(sender, body);
- break;
- #endif /* WTAPI_SERVER */
- default:
- break; /* ignore other types of messages */
- }
- /*
- * If send type was modal, return the result of this message.
- */
- if (sendtype == MSG_SEND_MODAL) {
- memcpy(rbuf, (char *)&result, sizeof(result));
- DoSend(pipe, caller, sender, REPLY, rbuf, sizeof(result), MSG_SEND);
- }
- free(RcvMessage); RcvMessage = 0;
- return(MSG_OK);
- } /* ReceiveMsg */
-
- /*COMMENT***************************************************
- ;SendMsg
- Title: Send a message across the pipe.
- In: pipe - read/write file descriptors
- caller - name of application which called SendMsg()
- product - name of product to send message to
- msgtype - message type
- data - body of message
- len - number of bytes in message
- Out: none
- Xin: none
- Xout: none
- Return: MSG_OK or error
- Notes:
- ***********************************************************/
- MSG_ERRS SendMsg(WTPIPE pipe, char *caller, char *product,
- MSG_TYPE msgtype, char *data, int len)
- {
- return(DoSend(pipe, caller, product, msgtype, data, len, MSG_SEND));
- } /* SendMsg */
-
- /*COMMENT***************************************************
- ;SendModalMsg
- Title: Send a message across the pipe and wait for a return status.
- In: pipe - read/write file descriptors
- caller - name of application which called SendModalMsg()
- product - name of product to send message to
- msgtype - message type
- data - body of message
- len - number of bytes in message
- Out: none
- Xin: none
- Xout: none
- Return: MSG_OK or error
- Notes:
- ***********************************************************/
- MSG_ERRS SendModalMsg(WTPIPE pipe, char *caller, char *product,
- MSG_TYPE msgtype, char *data, int len)
- {
- MSG_ERRS ret;
-
- NeedModalReply = 1;
- ret = DoSend(pipe, caller, product, msgtype, data, len, MSG_SEND_MODAL);
- if (ret != MSG_OK) {
- return(ret);
- }
- /*
- * Loop receiving messages until the REPLY to the modal send is returned.
- */
- while (NeedModalReply) {
- ret = ReceiveMsg(pipe, caller); /* wait for reply */
- if (ret) { /* error receiving reply */
- return(ret);
- }
- }
- return(ret);
- } /* SendModalMsg */
-
- /*COMMENT***************************************************
- ;SendRequestAct
- Title: Send a message across the pipe, wait for a reply, call reply handler
- In: pipe - read/write file descriptors
- caller - name of application which called SendRequestAct()
- product - name of product to send message to
- msgtype - message type
- data - body of message
- len - number of bytes in message
- handler - pointer to routine to process returned message data
- Out: none
- Xin: none
- Xout: none
- Return: MSG_OK or error
- Notes:
- ***********************************************************/
- MSG_ERRS SendRequestAct(WTPIPE pipe, char *caller, char *product,
- MSG_TYPE msgtype, char *data, int len, FUNCP handler)
- {
- MSG_ERRS ret;
- char *sender, *mess;
-
- NeedRequestReply = 1;
- ret = SendMsg(pipe, caller, product, msgtype, data, len);
- if (ret) { /* error sending message */
- return(ret);
- }
- /*
- * Loop receiving messages until the REPLY to the request is returned.
- */
- while (NeedRequestReply) {
- ret = ReceiveMsg(pipe, caller); /* wait for reply */
- if (ret) { /* error receiving reply */
- return(ret);
- }
- }
- /*
- * If caller passed in a handler routine, call that routine passing
- * in the sender name and the body of the message.
- */
- if (handler) {
- sender = &RcvMessage[2];
- mess = sender + strlen(sender) + 1;
- (*handler)(sender, mess);
- }
- return(MSG_OK);
- } /* SendRequestAct */
-
- /*COMMENT***************************************************
- ;DoSend
- Title: Common code for SendMsg() and SendMsgModal().
- In: pipe - read/write file descriptors
- caller - name of application which called DoSend()
- product - name of product to send message to
- msgtype - message type
- data - body of message
- len - number of bytes in message
- sendtype - type of send (MSG_SEND, MSG_SEND_MODAL, MSG_SEND_REQUEST)
- Out: none
- Xin: none
- Xout: none
- Return: MSG_OK or error
- Notes:
- ***********************************************************/
- static MSG_ERRS DoSend(WTPIPE pipe, char *caller, char *product,
- MSG_TYPE msgtype, char *data, int len, SEND_TYPE sendtype)
- {
- PIPE_ERRS stat;
- int hdrlen; /* length of header */
-
- /*
- * Prefix the message type, send type, and name of this sending product
- * (caller) to the message.
- */
- hdrlen = 1 + 1 + strlen(caller) + 1;
- MsgLen = hdrlen + len;
- SndMessage = (char *)malloc(MsgLen);
- if (!SndMessage) {
- return(MSG_NOMEM);
- }
- SndMessage[0] = (char) msgtype; /* type of message */
- SndMessage[1] = (char) sendtype; /* type of send */
- strcpy(&SndMessage[2], caller); /* sending product */
- /*
- * Copy in the message data.
- */
- memcpy(&SndMessage[hdrlen], data, len);
- /*
- * Send the message.
- */
- stat = writepipe(pipe.write, SndMessage, MsgLen);
- free(SndMessage); SndMessage = 0;
- if (stat != PIPE_OK) {
- return(MSG_CANT_DELIVER);
- }
- return(MSG_OK);
- } /* DoSend */
-
- #ifdef WTAPI_CLIENT
- /*COMMENT***************************************************
- ;WtConnect
- Title: Initialize WT Client communication
- In: toplevel - toplevel widget of client
- exepath - full path to executable
- Out: none
- Xin: none
- Xout: none
- Return: pointer to initialized communication information
- Notes:
- ***********************************************************/
- WTCOMM WtConnect(Widget toplevel, char *exepath)
- {
- WTCOMM comm; /* for return value */
- XtInputId inputid; /* input id for input callback */
- int fd[4]; /* array of pipe file descriptors */
- int i;
-
- if (!toplevel || !exepath || !*exepath) {
- return((WTCOMM) 0); /* bad values passed in */
- }
- /*
- * Create the pipes. They will be used as follows:
- * fd[0] - client read from tool
- * fd[1] - tool write to client
- * fd[2] - tool read from client
- * fd[3] - client write to tool
- */
- if (pipe(&fd[0])) {
- return((WTCOMM) 0); /* error */
- }
- if (pipe(&fd[2])) {
- for (i = 0; i < 2; i++) {
- close(i);
- }
- return((WTCOMM) 0); /* error */
- }
- /* close client's file descriptors on exec of tool */
- if ((fcntl(fd[0], F_SETFD, 1) == -1) || (fcntl(fd[3], F_SETFD, 1) == -1)) {
- for (i = 0; i < 4; i++) {
- close(i);
- }
- return((WTCOMM) 0); /* error */
- }
- oldsigfunc = signal(SIGPIPE, SIG_IGN); /* don't die on SIGPIPE signals */
- /*
- * Allocate and initialize the WT Client communication info struct.
- */
- comm = (WTCOMM) calloc(1, sizeof(WTCOMMDATA));
- if (comm) {
- comm->client = (char *) calloc(1, strlen("WTClient") + 1);
- comm->tool = (char *) calloc(1, strlen(exepath) + 10);
- }
- if (!comm || !comm->client || !comm->tool) {
- if (comm->client) free(comm->client);
- if (comm->tool) free(comm->tool);
- if (comm) free(comm);
- for (i = 0; i < 4; i++) {
- close(i);
- }
- return((WTCOMM) 0);
- }
- strcpy(comm->client, "WTClient");
- /*
- * Build a unique tool id for this invocation of the tool consisting
- * of the read and write file descriptors and the invocation path.
- * FORMAT: readfd_writefd_path
- * EXAMPLE: 7_8_/tools/wtserver
- */
- sprintf(comm->tool, "%d_%d_", fd[2], fd[1]);
- strcat(comm->tool, exepath);
- comm->cl_pipe.read = fd[0];
- comm->tl_pipe.write = fd[1];
- comm->tl_pipe.read = fd[2];
- comm->cl_pipe.write = fd[3];
- /*
- * Add an input callback to receive messages from the new pipe.
- */
- comm->inputid = XtAppAddInput(XtWidgetToApplicationContext(toplevel),
- comm->cl_pipe.read, (XtPointer) XtInputReadMask,
- (XtInputCallbackProc) WtClMsgReceived, (XtPointer) comm);
- comm->toplevel = toplevel; /* remember toplevel shell */
- comm->window = 0; /* window id of tool set later */
- return(comm);
- } /* WtConnect */
-
- /*COMMENT***************************************************
- ;WtDisconnect
- Title: Shut down WT Client communication
- In: comm - pointer to communication information
- Out: none
- Xin: none
- Xout: none
- Return: none
- Notes: Remove input callback, close file descriptors, free memory
- ***********************************************************/
- void WtDisconnect(WTCOMM comm)
- {
- if (comm) {
- if (comm->client) {
- free(comm->client);
- comm->client = 0;
- }
- if (comm->tool) {
- free(comm->tool);
- comm->tool = 0;
- }
- /*
- * Remove the input callback (before closing file descriptors).
- */
- if (comm->inputid) {
- XtRemoveInput(comm->inputid);
- comm->inputid = 0;
- }
- /*
- * Close client's read/write file descriptors.
- */
- if (comm->cl_pipe.read != -1) {
- close(comm->cl_pipe.read);
- comm->cl_pipe.read = -1;
- }
- if (comm->cl_pipe.write != -1) {
- close(comm->cl_pipe.write);
- comm->cl_pipe.write = -1;
- }
- free(comm);
- comm = 0;
- }
- if (oldsigfunc) {
- signal(SIGPIPE, oldsigfunc); /* restore prev func */
- oldsigfunc = 0;
- }
- } /* WtDisconnect */
-
- /*COMMENT***************************************************
- ;WtClMsgReceived
- Title: Process a message received from the Writing Tool.
- In: cldata = WTAPI communication info
- source = pointer to file descriptor that generated the event
- id = ID that was returned from call to XtAppAddInput()
- Out: none
- Xin: none
- Xout: none
- Return: none
- Notes: This function should be attached as an XtInputCallbackProc
- on the client's read file descriptor.
- ***********************************************************/
- static void WtClMsgReceived(XtPointer cldata, int *source, XtInputId *id)
- {
- WTCOMM comm = (WTCOMM) cldata;
- MSG_ERRS stat; /* status of message receive */
-
- if (!comm || (comm->cl_pipe.read < 0)) {
- return;
- }
- stat = ReceiveMsg(comm->cl_pipe, comm->client);
- /*
- * If this input callback was triggered and then ReceiveMsg() failed
- * it means the pipe went down unexpectedly or there is some other
- * problem with the pipe. We need to disconnect from the pipe and
- * quit the WT session.
- */
- if (stat != MSG_OK) {
- XtRemoveInput(comm->inputid);
- comm->inputid = 0;
- quitTool("Pipe is down or faulty. Dropping the Writing Tool session.");
- }
- } /* WtClMsgReceived */
-
- /*COMMENT*******************************************************
- ;wtClReceiveMsg
- Title: Receive a raw WTAPI message on the Client side and extract parameters
- necessary to invoke wtClReceive().
- In: sender = name of sending process
- msg = pointer to raw WTAPI message
- Out: none
- Return: status of message
- Notes: This function is intended to be used in the msgHandlers table
- used by wreceiveMsg() in libunix/wmsg.c for WTAPI_TOOL_COMMAND,
- WTAPI_TOOL_QUERY, and REPLY messages.
- ***************************************************************/
- static WTSTATUS wtClReceiveMsg(char *sender, char *msg)
- {
- WTMSGHEADER headerbuf;
- WTMSGHEADERP header = &headerbuf;
- WTSTATUS status = 0;
- WTBUFP inmsg = 0, inbuf = 0, rtmsg = 0, rtbuf = 0, retdata = 0;
- int inlen, rtlen;
- WTCOMM comm;
- WTCOMM wtGetCommID(char *);
-
- /*
- * Copy data from message into header buffer. We can't just use a
- * pointer because the message data may not be word aligned and this
- * causes a Bus Error when referencing members of the structure,
- * e.g. header->inbufsize.
- */
- memcpy((char *)header, (char *)msg, sizeof(WTMSGHEADER));
- /*
- * We now use the sizes from the header to allocate space for the
- * incoming message. Again, we must do this to make sure we are
- * word aligned to avoid Bus Errors when structure overlays are used
- * to pull out the data.
- */
- inlen = header->inmsgsize + header->inbufsize;
- inmsg = 0;
- inmsg = (WTBUFP)calloc(1, inlen);
- if (!inmsg) {
- return WTS_NOMEMORY;
- }
- memcpy((char *)inmsg, (char *)msg + sizeof(WTMSGHEADER), inlen);
-
- if (header->inbufsize) {
- inbuf = inmsg + header->inmsgsize;
- } else {
- inbuf = (WTBUFP) 0;
- }
- if (header->rtmsgid != WTC_NOMESSAGE) {
- rtlen = sizeof(WTMSGHEADER) + header->rtmsgsize + header->rtbufsize;
- retdata = 0;
- retdata = (WTBUFP)calloc(1, rtlen);
- if (!retdata) {
- rtmsg = (WTBUFP) 0;
- rtbuf = (WTBUFP) 0;
- } else {
- rtmsg = (WTBUFP) retdata + sizeof(WTMSGHEADER);
- if (header->rtbufsize) {
- rtbuf = rtmsg + header->rtmsgsize;
- } else {
- rtbuf = (WTBUFP) 0;
- }
- }
- } else {
- rtmsg = (WTBUFP) 0;
- rtbuf = (WTBUFP) 0;
- }
- comm = commHandle;
- if (comm) {
- status = wtClReceive(comm, header->inmsgid, inmsg, inbuf,
- rtmsg, rtbuf, &header->rtbufsize);
- }
- if (comm && (header->rtmsgid != WTC_NOMESSAGE)) {
- header->inmsgid = header->rtmsgid;
- header->inmsgsize = header->rtmsgsize;
- header->inbufsize = header->rtbufsize;
- header->rtmsgid = WTC_NOMESSAGE;
- header->rtmsgsize = 0;
- header->rtbufsize = 0;
- memcpy((char *)retdata, (char *)header, sizeof(WTMSGHEADER));
- SendMsg(comm->cl_pipe, comm->client, comm->tool, REPLY, retdata, rtlen);
- }
- if (inmsg) {
- free((char *)inmsg);
- }
- if (retdata) {
- free((char *)retdata);
- }
- return status;
- } /* wtClReceiveMsg */
- #endif /* WTAPI_CLIENT */
-
- #ifdef WTAPI_SERVER
- /*COMMENT***************************************************
- ;WTInitComm
- Title: Initialize WT Server communication
- In: toplevel - toplevel widget of client
- exepath - full path to executable
- read_fd - read file descriptor
- write_fd - write file descriptor
- Out: none
- Xin: none
- Xout: none
- Return: pointer to initialized communication information
- Notes:
- ***********************************************************/
- WTCOMM WTInitComm(Widget toplevel, char *exepath, int read_fd, int write_fd)
- {
- WTCOMM comm; /* for return value */
- XtInputId inputid; /* input id for input callback */
- int i;
-
- if (!toplevel || !exepath || !*exepath) {
- return((WTCOMM) 0); /* bad values passed in */
- }
- oldsigfunc = signal(SIGPIPE, SIG_IGN); /* don't die on SIGPIPE signals */
- /*
- * Allocate and initialize the WT Client communication info struct.
- */
- comm = (WTCOMM) calloc(1, sizeof(WTCOMMDATA));
- if (comm) {
- comm->client = (char *) calloc(1, strlen("WTClient") + 1);
- comm->tool = (char *) calloc(1, strlen(exepath) + 10);
- }
- if (!comm || !comm->client || !comm->tool) {
- if (comm->client) free(comm->client);
- if (comm->tool) free(comm->tool);
- if (comm) free(comm);
- return((WTCOMM) 0);
- }
- strcpy(comm->client, "WTClient");
- /*
- * Build a unique tool id for this invocation of the tool consisting
- * of the read and write file descriptors and the invocation path.
- * FORMAT: readfd_writefd_path
- * EXAMPLE: 7_8_/tools/wtserver
- */
- sprintf(comm->tool, "%d_%d_", read_fd, write_fd);
- strcat(comm->tool, exepath);
- comm->tl_pipe.read = read_fd;
- comm->tl_pipe.write = write_fd;
- comm->cl_pipe.read = -1;
- comm->cl_pipe.write = -1;
- /*
- * Add an input callback to receive messages from the new pipe.
- */
- comm->inputid = XtAppAddInput(XtWidgetToApplicationContext(toplevel),
- comm->tl_pipe.read, (XtPointer) XtInputReadMask,
- (XtInputCallbackProc) WtTlMsgReceived, (XtPointer) comm);
- comm->toplevel = toplevel; /* remember toplevel shell */
- comm->window = 0; /* window id of client set later */
- return(comm);
- } /* WTInitComm */
-
- /*COMMENT***************************************************
- ;WTCloseComm
- Title: Shut down WT Server communication
- In: comm - pointer to communication information
- Out: none
- Xin: none
- Xout: none
- Return: none
- Notes: Remove input callback, close file descriptors, free memory
- ***********************************************************/
- void WTCloseComm(WTCOMM comm)
- {
- if (comm) {
- if (comm->client) {
- free(comm->client);
- comm->client = 0;
- }
- if (comm->tool) {
- free(comm->tool);
- comm->tool = 0;
- }
- /*
- * Remove the input callback (before closing file descriptors).
- */
- if (comm->inputid) {
- XtRemoveInput(comm->inputid);
- comm->inputid = 0;
- }
- /*
- * Close server's read/write file descriptors.
- */
- if (comm->tl_pipe.read != -1) {
- close(comm->tl_pipe.read);
- comm->tl_pipe.read = -1;
- }
- if (comm->tl_pipe.write != -1) {
- close(comm->tl_pipe.write);
- comm->tl_pipe.write = -1;
- }
- free(comm);
- comm = 0;
- }
- if (oldsigfunc) {
- signal(SIGPIPE, oldsigfunc); /* restore prev func */
- oldsigfunc = 0;
- }
- } /* WTCloseComm */
-
- /*COMMENT***************************************************
- ;WtTlMsgReceived
- Title: Process a message received from the WT Client.
- In: cldata = WTAPI communication info
- source = pointer to file descriptor that generated the event
- id = ID that was returned from call to XtAppAddInput()
- Out: none
- Xin: none
- Xout: none
- Return: none
- Notes: This function should be attached as an XtInputCallbackProc
- on the server's read file descriptor.
- ***********************************************************/
- static void WtTlMsgReceived(XtPointer cldata, int *source, XtInputId *id)
- {
- WTCOMM comm = (WTCOMM) cldata;
- MSG_ERRS stat; /* status of message receive */
-
- if (!comm || (comm->tl_pipe.read < 0)) {
- return;
- }
- stat = ReceiveMsg(comm->tl_pipe, comm->tool);
- /*
- * If this input callback was triggered and then ReceiveMsg() failed
- * it means the pipe went down unexpectedly or there is some other
- * problem with the pipe. We need to disconnect from the pipe and
- * quit the WT session.
- */
- if (stat != MSG_OK) {
- XtRemoveInput(comm->inputid);
- comm->inputid = 0;
- quitTool("Pipe is down or faulty. Aborting the Writing Tool session.");
- }
- } /* WtTlMsgReceived */
-
- /*COMMENT*******************************************************
- ;wtTlReceiveMsg
- Title: Receive a raw WTAPI message on the Server side and extract parameters
- necessary to invoke wtTlReceive().
- In: sender = name of sending process
- msg = pointer to raw WTAPI message
- Out: none
- Return: status of message
- Notes: This function is intended to be used in the msgHandlers table
- used by wreceiveMsg() in libunix/wmsg.c for WTAPI_TOOL_COMMAND,
- WTAPI_TOOL_QUERY, and REPLY messages.
- ***************************************************************/
- static WTSTATUS wtTlReceiveMsg(char *sender, char *msg)
- {
- WTMSGHEADER headerbuf;
- WTMSGHEADERP header = &headerbuf;
- WTSTATUS status = 0;
- WTBUFP inmsg = 0, inbuf = 0, rtmsg = 0, rtbuf = 0, retdata = 0;
- int inlen, rtlen;
- WTCOMM comm;
- WTCOMM wtGetCommID(char *);
-
- /*
- * Copy data from message into header buffer. We can't just use a
- * pointer because the message data may not be word aligned and this
- * causes a Bus Error when referencing members of the structure,
- * e.g. header->inbufsize.
- */
- memcpy((char *)header, (char *)msg, sizeof(WTMSGHEADER));
- /*
- * We now use the sizes from the header to allocate space for the
- * incoming message. Again, we must do this to make sure we are
- * word aligned to avoid Bus Errors when structure overlays are used
- * to pull out the data.
- */
- inlen = header->inmsgsize + header->inbufsize;
- inmsg = 0;
- inmsg = (WTBUFP)calloc(1, inlen);
- if (!inmsg) {
- return WTS_NOMEMORY;
- }
- memcpy((char *)inmsg, (char *)msg + sizeof(WTMSGHEADER), inlen);
-
- if (header->inbufsize) {
- inbuf = inmsg + header->inmsgsize;
- } else {
- inbuf = (WTBUFP) 0;
- }
- if (header->rtmsgid != WTC_NOMESSAGE) {
- rtlen = sizeof(WTMSGHEADER) + header->rtmsgsize + header->rtbufsize;
- retdata = 0;
- retdata = (WTBUFP)calloc(1, rtlen);
- if (!retdata) {
- rtmsg = (WTBUFP) 0;
- rtbuf = (WTBUFP) 0;
- } else {
- rtmsg = (WTBUFP) retdata + sizeof(WTMSGHEADER);
- if (header->rtbufsize) {
- rtbuf = rtmsg + header->rtmsgsize;
- } else {
- rtbuf = (WTBUFP) 0;
- }
- }
- } else {
- rtmsg = (WTBUFP) 0;
- rtbuf = (WTBUFP) 0;
- }
- comm = comm_id;
- if (comm) {
- status = wtTlReceive(comm, header->inmsgid, inmsg, inbuf,
- rtmsg, rtbuf, &header->rtbufsize);
- }
- if (comm && (header->rtmsgid != WTC_NOMESSAGE)) {
- header->inmsgid = header->rtmsgid;
- header->inmsgsize = header->rtmsgsize;
- header->inbufsize = header->rtbufsize;
- header->rtmsgid = WTC_NOMESSAGE;
- header->rtmsgsize = 0;
- header->rtbufsize = 0;
- memcpy((char *)retdata, (char *)header, sizeof(WTMSGHEADER));
- SendMsg(comm->tl_pipe, comm->tool, comm->tool, REPLY, retdata, rtlen);
- }
- if (inmsg) {
- free((char *)inmsg);
- }
- if (retdata) {
- free((char *)retdata);
- }
- return status;
- } /* wtTlReceiveMsg */
- #endif /* WTAPI_SERVER */
-