# This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by Dave Thompson on Mon Apr 24 14:07:22 1995 # # This archive contains: # cciClient.c connect.c # list.c support.c # cci.h connect.h # list.h listP.h # memStuffForPipSqueeks.h port.h # Makefile # LANG=""; export LANG PATH=/bin:/usr/bin:$PATH; export PATH echo x - cciClient.c cat >cciClient.c <<'@EOF' #include #include "memStuffForPipSqueeks.h" #include "cci.h" #include "connect.h" #include "list.h" static int initialized = 0; static List anchorCBList = 0; static List outputCBList = 0; static List browserViewCBList = 0; extern char *GetLine(); typedef struct { MCCIPort serverPort; void (*callBack)(); void *callBackData; } AnchorCallBack; typedef struct { MCCIPort serverPort; char *type; void (*callBack)(); void *callBackData; } OutputCallBack; typedef struct { MCCIPort serverPort; void (*callBack)(); void *callBackData; } BrowserViewCallBack; int MCCIGetSocketDescriptor(serverPort) /* this routine is platform dependent and is not assumed to be supported * on all platforms. It is only here for those routines that wish to have * a select() external to the MCCI library. * this routine extracts the socket descriptor from the MCCIPort and * returns it */ MCCIPort serverPort; { return(NetGetSocketDescriptor(serverPort)); } int MCCIIsConnected(serverPort) /* return 1 if connected, 0 if not */ MCCIPort serverPort; { return(NetIsConnected(serverPort)); } void MCCIReadBrowserViewOutput(serverPort,response) MCCIPort serverPort; char *response; /* Read output from BrowserView */ { char *line; char *url = (char *) 0; BrowserViewCallBack *bvCB; char *start,*end,*s,*contentType; int contentLength; char *data = (char *) 0; int numRead; /* expect response line to be 'MCCIR_SEND_BROWSERVIEW ' */ /* skip over MCCIR_SEND_BROWSERVIEW */ s = response; s+=4; /* skip over repsonse code */ GetWordFromString(s,&url,&end); if (url && (url != end)) { url = strdup(url); } else { url = (char *) 0; } #ifdef DEBUG printf("MCCIReadBrowserViewOutput(): I've been called\n"); printf("MCCIReadBrowserViewOutput(): url = \"%s\"\n",url); #endif line = GetLine(serverPort); if (!line) { return; } #ifdef DEBUG printf("MCCIReadBrowserViewOutput(): got line:%s\n",line); #endif contentType = (char *) 0; if (!strncasecmp("Content-Type:",line,13)) { start = line; start += 13; GetWordFromString(start,&s,&end); *end = '\0'; contentType = strdup(s); line = GetLine(serverPort); #ifdef DEBUG printf("MCCIReadBrowserViewOutput(): 2 got line:%s\n",line); #endif if (!line) { return; } } #ifdef DEBUG printf("MCCIReadBrowserViewOutput(): contentType:%s\n",contentType); #endif if (!strncasecmp("Content-Length:",line,15)) { start = line; start += 15; GetWordFromString(start,&s,&end); contentLength = atoi(s); if (contentLength < 1){ return; /* error */ } if (!(data = (char *) MALLOC(contentLength))) { return; /* error */ } #ifdef DEBUG printf("MCCIReadBrowserViewOutput(): type=%s,length=%d\n", contentType,contentLength); #endif numRead = ReadBuffer(serverPort,data,contentLength); #ifdef DEBUG printf("MCCIReadBrowserViewOutput(): number of bytes read = %d\n",numRead); #endif /******************************************************* * done parsing getting message from network, * now notify my callbacks */ bvCB = (BrowserViewCallBack *) ListHead(browserViewCBList); while (bvCB) { if (bvCB->callBack) { (void)(bvCB->callBack)(url,contentType, data, contentLength, bvCB->callBackData); } bvCB = (BrowserViewCallBack *) ListNext(browserViewCBList); } } #ifdef DEBUG printf("MCCIReadBrowserViewOutput(): returning\n"); #endif } /* MCCIReadBrowserViewOutput() */ static void MCCIReadSendDataOutput(serverPort) /* read output sent from the Mosaic */ /* error recovery could be better in this routine */ MCCIPort serverPort; { char *line; char *start,*end,*s,*contentType; int contentLength; char *data = (char *) 0; OutputCallBack *outCB; int numRead; #ifdef DEBUG printf("MCCIReadSendDataOutput(): I've been called\n"); #endif line = GetLine(serverPort); if (!line) { return; } #ifdef DEBUG printf("MCCIReadSendDataOutput(): got line:%s\n",line); #endif contentType = (char *) 0; if (!strncasecmp("Content-Type:",line,13)) { start = line; start += 13; GetWordFromString(start,&s,&end); *end = '\0'; contentType = strdup(s); line = GetLine(serverPort); #ifdef DEBUG printf("MCCIReadSendDataOutput(): 2 got line:%s\n",line); #endif if (!line) { return; } } #ifdef DEBUG printf("MCCIReadSendDataOutput(): contentType:%s\n",contentType); #endif if (!strncasecmp("Content-Length:",line,15)) { start = line; start += 15; GetWordFromString(start,&s,&end); contentLength = atoi(s); if (contentLength < 1){ return; /* error */ } if (!(data = (char *) MALLOC(contentLength))) { return; /* error */ } #ifdef DEBUG printf("MCCIReadSendDataOutput(): type=%s,length=%d\n", contentType,contentLength); #endif numRead = ReadBuffer(serverPort,data,contentLength); #ifdef DEBUG printf("MCCIReadSendDataOutput(): number of bytes read = %d\n",numRead); #endif /* find callback */ outCB = (OutputCallBack *) ListHead(outputCBList); while(outCB) { #ifdef DEBUG printf("MCCIReadSendDataOutput(): Checking a call back\n"); printf("MCCIReadSendDataOutput(): comparing \"%s\" with \"%s\"\n",outCB->type,contentType); #endif if ((outCB->serverPort == serverPort) && (!strcasecmp(outCB->type,contentType))) { if (outCB->callBack) { (void)(outCB->callBack)(contentType, data,numRead,outCB->callBackData); #ifdef DEBUG printf("MCCIReadSendDataOutput(): calling a cb\n"); #endif } } outCB = (OutputCallBack *) ListNext(outputCBList); } } #ifdef DEBUG printf("MCCIReadSendDataOutput(): returning\n"); #endif if (!line) { return; } } static void MCCIHandleAddOutput(serverPort,response) MCCIPort serverPort; char *response; { char respCode[10]; char *start,*end; static char url[1024]; #ifdef DEBUG printf("MCCIHandleAddOutput I've been called with"); #endif if ((!response) || (!MCCIIsConnected(serverPort))) { return; } #ifdef DEBUG printf("\n\"%s\"\n",response); #endif sprintf(respCode,"%d",MCCIR_ANCHOR_INFO); if (!strncmp(respCode,response,3)) { /* It's an ANCHOR INFO */ AnchorCallBack *acb; start = strchr(response,'<'); end = strchr(response,'>'); start++; *end='\0'; strcpy(url,start); /* call all the anchor callbacks */ acb = (AnchorCallBack *) ListHead(anchorCBList); while (acb) { if (acb->serverPort == serverPort) { if (acb->callBack) { (acb->callBack)(url,acb->callBackData); } } acb = (AnchorCallBack *) ListNext(anchorCBList); } return; } sprintf(respCode,"%d",MCCIR_SEND_DATA_OUTPUT); if (!strncmp(respCode,response,3)) { /* It's send output data */ MCCIReadSendDataOutput(serverPort); } sprintf(respCode,"%d",MCCIR_SEND_BROWSERVIEW); if (!strncmp(respCode,response,3)) { /* It's send output data */ MCCIReadBrowserViewOutput(serverPort,response); } sprintf(respCode, "%d", MCCIR_GET_OK); if (!strncmp(respCode,response,3)) { /* It's a GET OK */ #ifdef DEBUG printf("GET reply: %s\n",response); #endif } sprintf(respCode, "%d", MCCIR_GET_FAILED); if (!strncmp(respCode,response,3)) { /* It's a GET FAILED */ #ifdef DEBUG printf("GET reply: %s\n",response); #endif } /* I don't know what this is Additional Output is... */ return; } int MCCIPoll(serverPort) /* this routine is intended to be called periodically to check for input * from the server. If so, it's handled. * return -1 on Not connected. * return 1 if something was read. * return 0 on nothing here. */ MCCIPort serverPort; { char *line; int ret=0; if (!MCCIIsConnected(serverPort)) { return(-1); } while (MCCIIsThereInput(serverPort)) { line = GetLine(serverPort); if (!line) { /* server has disconnected */ MCCIDisconnect(serverPort); } MCCIHandleAddOutput(serverPort,line); ret = 1; } if (!MCCIIsConnected(serverPort)) { return(-1); } else { return(ret); } } static char *MCCIGetResponse(serverPort) MCCIPort serverPort; /* get a response from a server. The string returned is good only until the next call to GetLine() */ { char *response; if (!MCCIIsConnected(serverPort)) { return("901 Error not connected"); } response = GetLine(serverPort); if (response) { while (response[0] == '3') { MCCIHandleAddOutput(serverPort,response); response = GetLine(serverPort); } } else { MCCIDisconnect(serverPort); return("900 Error No response"); } return(response); } static int MCCIWrite(serverPort,message,length) /* This is a wrapper to NetWrite, It's here to insure that data from the * server is read in before a write is sent out so as to prevent a * write write deadlock */ MCCIPort serverPort; char *message; int length; { int writeLength; if (!MCCIIsConnected(serverPort)) { return(0); } while(NetIsThereInput(serverPort)) { MCCIGetResponse(serverPort); if (!MCCIIsConnected(serverPort)) { return(0); } } writeLength = NetWrite(serverPort,message,length); return(writeLength); } MCCIInitialize() { anchorCBList = ListCreate(); outputCBList = ListCreate(); browserViewCBList = ListCreate(); initialized = 1; } MCCIPort MCCIConnect(serverAddress,port,callBack,callBackData) /* connect to given address */ /* return 0 on can't connect */ /* upon termination of connection, the callback is called. It's of the form: * void CCICloseCallBack(MCCIPort serverPort, void callBackData); */ char *serverAddress; int port; void (*callBack)(); /* disconnect callback */ void *callBackData; /* disconnect callback data */ { MCCIPort serverPort; char *line; if (!initialized) { MCCIInitialize(); } if (!(serverPort = NetClientConnect(serverAddress,port))) { return((MCCIPort) 0); } line = MCCIGetResponse(serverPort); #ifdef DEBUG printf("MCCIConnect(): received from server:\n%s",line); #endif if (serverPort) { serverPort->callBack = callBack; serverPort->callBackData = callBackData; } return(serverPort); } int MCCIIsThereInput(serverPort) /* return 1 on true, 0 on false */ MCCIPort serverPort; { if (!serverPort) return(0); if (!MCCIIsConnected(serverPort)) { return(0); } return(NetIsThereInput(serverPort)); } int MCCISendAnchor(serverPort,status,callBack,callBackData) /*************************************************************************** * MCCISendAnchor - tell browser to send anchor history * status - 0, MCCI_SEND_BEFORE, or MCCI_SEND_AFTER * 0 disables SendAnchor * MCCI_SEND_BEFORE, instructs the server to * send the anchor before the browser finishes * pulling down the URL. * MCCI_SEND_AFTER, instruts the server to * send the anchor after the browser finishes * pulling down the URL. * callBack - Routine that should be called back upon * anchor hits from browser. This function is * defined as: * * void callBack(char *anchor, void *callBackData) * * callBackData - data to be passed back to callBack routine * ***************************************************************************/ MCCIPort serverPort; int status; void (*callBack)(); void *callBackData; { char buff[80]; int length; int lengthToSend; AnchorCallBack *a; int notFound; char *line; if (!serverPort) { return(MCCI_FAIL); } if (!MCCIIsConnected(serverPort)) { return(MCCI_NETWORK_ERROR); } if (status) { /* create memory before sending request in case of failure */ if (!(a = (AnchorCallBack *) MALLOC(sizeof(AnchorCallBack)))) { return(MCCI_OUTOFMEMORY); } if (status == MCCI_SEND_BEFORE) { /* ejb 9 March 1995 */ sprintf(buff, "%s %s %s\r\n", MCCI_S_SEND, MCCI_S_ANCHOR, MCCI_S_BEFORE); } else { /* defaults to send after, backwards compatible. */ sprintf(buff, "%s %s %s\r\n", MCCI_S_SEND, MCCI_S_ANCHOR, MCCI_S_AFTER); } lengthToSend = strlen((char *)buff); length = MCCIWrite(serverPort, buff, lengthToSend); if (length != lengthToSend) { /* error sending */ FREE(a); return(MCCI_FAIL); } /* add to callback list */ if (callBack) { a->serverPort = serverPort; a->callBack = callBack; a->callBackData = callBackData; ListAddEntry(anchorCBList,a); } else { FREE(a); } } else { sprintf(buff, "%s %s %s\r\n", MCCI_S_SEND, MCCI_S_ANCHOR, MCCI_S_STOP); lengthToSend = strlen((char *)buff); length = MCCIWrite(serverPort, buff, lengthToSend); if (length != lengthToSend) { /* error sending */ return(MCCI_FAIL); } /* remove from callback list */ a = (AnchorCallBack *) ListHead(anchorCBList); while (a) { if (a->serverPort == serverPort) { if (callBack) { if (callBack == a->callBack) { ListDeleteEntry(anchorCBList,a); } } else { ListDeleteEntry(anchorCBList,a); } a = (AnchorCallBack *)ListCurrent(anchorCBList); } else { a = (AnchorCallBack *) ListNext(anchorCBList); } } } line = MCCIGetResponse(serverPort); #ifdef DEBUG printf("SEND ANCHOR reply: %s\n",line); #endif if (!line) { return(MCCI_NETWORK_ERROR); } if (line[0]=='2') { return(MCCI_OK); } else { return(MCCI_REQUEST_FAIL); } } int MCCIGet(serverPort,uri,output,absRelative,additionalHeader) /*************************************************************************** * MCCIGet - Resolve a URL * uri - the URL to be resolved * output - where should the output go? * MCCI_DEFAULT - same as OUTPUT_CURRENT * MCCI_OUTPUT_NONE - Browser shouldn't display * MCCI_OUTPUT_CURRENT - Browser should display in current * MCCI_OUTPUT_NEW - Browser should display in new window * absRelative - url should be treated as either a relative or * or absolute link to the current document * MCCI_DEFAULT - set to absolute * MCCI_ABSOLUTE * MCCI_RELATIVE * additionalHeader - This is a string containing additional HTTP * header information to pass to the server. If this is * a standard HTTP GET, this field should be set to NULL. * Example: * MCCIGet(port,"http://host/file",0,MCCI_ABSOLUTE,0); ***************************************************************************/ MCCIPort serverPort; char *uri; int output; int absRelative; char *additionalHeader; { char *buff; char buff2[80]; int length,lengthToSend; char *line; int approxSize; if (!serverPort) { return(MCCI_FAIL); } if (!MCCIIsConnected(serverPort)) { return(MCCI_NETWORK_ERROR); } approxSize = 256; if (!uri) { /* required parameter */ return(MCCI_FAIL); } else { approxSize += strlen(uri); } if (additionalHeader) { approxSize += strlen(additionalHeader); } if (!(buff = (char *) MALLOC(approxSize))) { /* memory problems */ return(MCCI_OUTOFMEMORY); } sprintf(buff,"GET URL <%s>",uri); switch (output) { case MCCI_OUTPUT_NONE: strcat(buff," OUTPUT NONE"); break; case MCCI_OUTPUT_NEW: strcat(buff," OUTPUT NEW"); break; case MCCI_OUTPUT_CURRENT: default: strcat(buff," OUTPUT CURRENT"); break; } /* switch (absRelative) { case MCCI_RELATIVE: strcat(buff," RELATIVE"); break; case MCCI_ABSOLUTE: default: strcat(buff," ABSOLUTE"); break; } */ if (additionalHeader) { strcat(buff," HEADER\r\n"); sprintf(buff2,"Content-Length: %d\r\n", strlen(additionalHeader)); strcat(buff,buff2); strcat(buff,additionalHeader); } else { strcat(buff,"\r\n"); } lengthToSend = strlen(buff); length = MCCIWrite(serverPort, buff, lengthToSend); FREE(buff); if (length != lengthToSend) { /* error sending */ return(MCCI_FAIL); } /* get server response */ line = MCCIGetResponse(serverPort); #ifdef DEBUG printf("GET reply: %s\n",line); #endif if (!line) { return(MCCI_NETWORK_ERROR); } if (line[0]=='2') { return(MCCI_OK); } else { return(MCCI_REQUEST_FAIL); } } int MCCISendOutputStop(serverPort,mimeType) MCCIPort serverPort; char *mimeType; { char buff[128]; int length,lengthToSend; char *line; OutputCallBack *outCB; if (!serverPort) { return(MCCI_FAIL); } if (!MCCIIsConnected(serverPort)) { return(MCCI_NETWORK_ERROR); } sprintf(buff,"%s %s %s %s %s\r\n", MCCI_S_SEND, MCCI_S_OUTPUT, MCCI_S_STOP, mimeType,NetReturnAddress(serverPort)); lengthToSend = strlen(buff); length = MCCIWrite(serverPort, buff, lengthToSend); if (length != lengthToSend) { /* error sending */ return(MCCI_FAIL); } /* get server response */ line = MCCIGetResponse(serverPort); #ifdef DEBUG printf("SEND OUTPUT STOP reply: %s\n",line); #endif /* remove call back from list */ outCB = (OutputCallBack *)ListHead(outputCBList); while (outCB) { if ((outCB->serverPort == serverPort) && (!(strcmp(mimeType,outCB->type)))) { ListDeleteEntry(outputCBList,outCB); FREE(outCB->type); FREE(outCB); outCB = (OutputCallBack *) ListCurrent(outputCBList); } else { outCB = (OutputCallBack *) ListNext(outputCBList); } } if (!line) { return(MCCI_NETWORK_ERROR); } if (line[0]=='2') { return(MCCI_OK); } else { return(MCCI_REQUEST_FAIL); } } int MCCISendOutput(serverPort,mimeType,callBack,callBackData) /* Tell Mosaic to send output of type mimeType * When Mosaic sends this type of data, the cci client may be notified by * the callback. The callback is of the form: * * void SendOuputCallBack(char *mimeType,char *data,int length, * void *callBackData); * * The cci client is repsonsible for freeing the area allocated in the * data field. */ MCCIPort serverPort; char *mimeType; void (*callBack)(); void *callBackData; { char buff[128]; int length,lengthToSend; char *line; OutputCallBack *outCB; if (!serverPort) { return(MCCI_FAIL); } if (!MCCIIsConnected(serverPort)) { return(MCCI_NETWORK_ERROR); } if (!(outCB = (OutputCallBack *) MALLOC( sizeof(OutputCallBack)))) { return(MCCI_OUTOFMEMORY); } sprintf(buff,"%s %s %s TO %s\r\n", MCCI_S_SEND,MCCI_S_OUTPUT, mimeType, NetReturnAddress(serverPort)); lengthToSend = strlen(buff); length = MCCIWrite(serverPort, buff, lengthToSend); if (length != lengthToSend) { /* error sending */ FREE(outCB); return(MCCI_FAIL); } outCB->serverPort = serverPort; outCB->type = strdup(mimeType); outCB->callBack = callBack; outCB->callBackData = callBackData; ListAddEntry(outputCBList,outCB); /* get server response */ line = MCCIGetResponse(serverPort); #ifdef DEBUG printf("SEND OUTPUT reply: %s\n",line); #endif if (!line) { return(MCCI_NETWORK_ERROR); } if (line[0]=='2') { return(MCCI_OK); } else { return(MCCI_REQUEST_FAIL); } } int MCCIDisconnect(serverPort) MCCIPort serverPort; { char buff[80]; int length,lengthToSend; char *line; AnchorCallBack *a; OutputCallBack *outCB; BrowserViewCallBack *bvCB; if (!serverPort) { return(MCCI_FAIL); } if (!MCCIIsConnected(serverPort)) { return(MCCI_NETWORK_ERROR); } /* This routine could be called due to an error... besides, notify the server is redundant. sprintf(buff,"%s\r\n",MCCI_S_DISCONNECT); lengthToSend = strlen(buff); length = MCCIWrite(serverPort, buff, lengthToSend); if (length != lengthToSend) { return(MCCI_FAIL); } */ NetCloseConnection(serverPort); /* remove any anchor callbacks on this port */ a = (AnchorCallBack *) ListHead(anchorCBList); while (a) { if (a->serverPort == serverPort) { ListDeleteEntry(anchorCBList,a); FREE(a); a = (AnchorCallBack *) ListCurrent(anchorCBList); } else { a = (AnchorCallBack *) ListNext(anchorCBList); } } /* remove any send output callbacks on this port */ outCB = (OutputCallBack *) ListHead(outputCBList); while(outCB) { if (outCB->serverPort == serverPort) { ListDeleteEntry(outputCBList,outCB); FREE(outCB->type); FREE(outCB); outCB = (OutputCallBack *) ListCurrent(outputCBList); } else { outCB = (OutputCallBack *) ListNext(outputCBList); } } bvCB = (BrowserViewCallBack *) ListHead(browserViewCBList); while(bvCB) { if (bvCB->serverPort == serverPort) { ListDeleteEntry(browserViewCBList,bvCB); FREE(bvCB); bvCB = (BrowserViewCallBack *) ListCurrent(browserViewCBList); } else { bvCB = (BrowserViewCallBack*) ListNext(browserViewCBList); } } /* call close connection callback */ if (serverPort->callBack) { (void) (serverPort->callBack)(serverPort, serverPort->callBackData); } return(MCCI_OK); } int MCCINBGet(serverPort,uri,output,absRelative,additionalHeader) /*************************************************************************** * MCCIGet - Resolve a URL * uri - the URL to be resolved * output - where should the output go? * MCCI_DEFAULT - same as OUTPUT_CURRENT * MCCI_OUTPUT_NONE - Browser shouldn't display * MCCI_OUTPUT_CURRENT - Browser should display in current * MCCI_OUTPUT_NEW - Browser should display in new window * absRelative - url should be treated as either a relative or * or absolute link to the current document * MCCI_DEFAULT - set to absolute * MCCI_ABSOLUTE * MCCI_RELATIVE * additionalHeader - This is a string containing additional HTTP * header information to pass to the server. If this is * a standard HTTP GET, this field should be set to NULL. * Example: * MCCINBGet(port,"http://host/file",0,MCCI_ABSOLUTE,0); ***************************************************************************/ MCCIPort serverPort; char *uri; int output; int absRelative; char *additionalHeader; { char *buff; char buff2[80]; int length,lengthToSend; char *line; int approxSize; if (!serverPort) { return(MCCI_FAIL); } if (!MCCIIsConnected(serverPort)) { return(MCCI_NETWORK_ERROR); } approxSize = 256; if (!uri) { /* required parameter */ return(MCCI_FAIL); } else { approxSize += strlen(uri); } if (additionalHeader) { approxSize += strlen(additionalHeader); } if (!(buff = (char *) MALLOC(approxSize))) { /* memory problems */ return(MCCI_OUTOFMEMORY); } sprintf(buff,"GET URL <%s>",uri); switch (output) { case MCCI_OUTPUT_NONE: strcat(buff," OUTPUT NONE"); break; case MCCI_OUTPUT_NEW: strcat(buff," OUTPUT NEW"); break; case MCCI_OUTPUT_CURRENT: default: strcat(buff," OUTPUT CURRENT"); break; } /* switch (absRelative) { case MCCI_RELATIVE: strcat(buff," RELATIVE"); break; case MCCI_ABSOLUTE: default: strcat(buff," ABSOLUTE"); break; } */ if (additionalHeader) { strcat(buff," HEADER\r\n"); sprintf(buff2,"Content-Length: %d\r\n", strlen(additionalHeader)); strcat(buff,buff2); strcat(buff,additionalHeader); } else { strcat(buff,"\r\n"); } lengthToSend = strlen(buff); length = MCCIWrite(serverPort, buff, lengthToSend); FREE(buff); if (length != lengthToSend) { /* error sending */ return(MCCI_FAIL); } return(MCCI_OK); } int MCCIPost(serverPort,url,contentType,data,dataLength,output) /*************************************************************************** * MCCIPost- Post data to an HTTP server * url - the URL to be resolved * contentType: MIME type for data * data - the data to be posted to the HTTP server * dataLength - Length of the above data * output - where should the output go? * MCCI_DEFAULT - same as OUTPUT_CURRENT * MCCI_OUTPUT_NONE - Browser shouldn't display * MCCI_OUTPUT_CURRENT - Browser should display in current * MCCI_OUTPUT_NEW - Browser should display in new window */ MCCIPort serverPort; char *url; char *contentType; char *data; int dataLength; int output; { char *line; char *buff; int lengthToSend; int length; if (!serverPort) { return(MCCI_FAIL); } if (!MCCIIsConnected(serverPort)) { return(MCCI_NETWORK_ERROR); } if (!(buff = (char *) MALLOC(strlen(url) + 256))) { return(MCCI_OUTOFMEMORY); } sprintf(buff, "%s <%s> %s", MCCI_S_POST, url, contentType); switch(output) { case MCCI_OUTPUT_NEW: strcat(buff," OUTPUT NEW"); break; case MCCI_OUTPUT_NONE: strcat(buff," OUTPUT NONE"); break; case MCCI_OUTPUT_CURRENT: case MCCI_DEFAULT: strcat(buff," OUTPUT CURRENT"); break; } strcat(buff,"\r\n"); lengthToSend = strlen(buff); length = MCCIWrite(serverPort, buff, lengthToSend); if (length != lengthToSend) { return(MCCI_FAIL); } #ifdef DEBUG printf("Post Request: %s",buff); #endif sprintf(buff, "Content-Length: %d \r\n",dataLength); lengthToSend = strlen(buff); length = MCCIWrite(serverPort, buff, lengthToSend); if (length != lengthToSend) { return(MCCI_FAIL); } length = MCCIWrite(serverPort, data, dataLength); if (length != dataLength) { return(MCCI_FAIL); } #ifdef DEBUG printf("%s%s\n",buff,data); #endif /* get server response */ line = MCCIGetResponse(serverPort); #ifdef DEBUG printf("POST reply: %s\n",line); #endif free(buff); if (!line) { return(MCCI_NETWORK_ERROR); } if (line[0]=='2') { return(MCCI_OK); } else { return(MCCI_REQUEST_FAIL); } } /* MCCIPost() */ int MCCISendBrowserView(serverPort,status,callBack,callBackData) /*************************************************************************** * MCCISendBrowserView()- This routine requests the web browser to send * a copy of what would normally be displayed in the browser * window. This typically includes text/html and any inline * images. The callbacks are called as data comes in. * status: 1 to turn on, 0 turn off. * * The call back is of the form: * * * void SendBrowserViewCallBack(char *url, char *mimeType, * char *data, int dataLength, * void *callBackData) */ MCCIPort serverPort; int status; void (*callBack)(); void *callBackData; { char *line; char buff[80]; int lengthToSend; int length; BrowserViewCallBack *bvcb; if (!serverPort) { return(MCCI_FAIL); } if (!MCCIIsConnected(serverPort)) { return(MCCI_NETWORK_ERROR); } if (status) { sprintf(buff,"%s %s\r\n",MCCI_S_SEND, MCCI_S_BROWSERVIEW); } else { sprintf(buff,"%s %s %s\r\n",MCCI_S_SEND, MCCI_S_BROWSERVIEW, MCCI_S_STOP); } lengthToSend = strlen(buff); length = MCCIWrite(serverPort, buff, lengthToSend); if (length != lengthToSend) { return(MCCI_FAIL); } if (!status) { /* remove the callback from callback list */ bvcb = (BrowserViewCallBack *) ListHead(browserViewCBList); while(bvcb) { if ((bvcb->serverPort == serverPort) && (bvcb->callBack == callBack) && (bvcb->callBackData == callBackData)) { ListDeleteEntry(browserViewCBList,bvcb); bvcb = (BrowserViewCallBack *) ListCurrent(browserViewCBList); } else { bvcb = (BrowserViewCallBack *) ListNext(browserViewCBList); } } } else { /* add callback to callback list */ if (!(bvcb = (BrowserViewCallBack *) MALLOC(sizeof(BrowserViewCallBack)))) { return(MCCI_OUTOFMEMORY); } bvcb->serverPort = serverPort; bvcb->callBack = callBack; bvcb->callBackData = callBackData; ListAddEntry(browserViewCBList,bvcb); } /* get response from browser */ line = MCCIGetResponse(serverPort); #ifdef DEBUG printf("SEND BROWSERVIEW reply: %s\n",line); #endif if (!line) { return(MCCI_NETWORK_ERROR); } if (line[0]=='2') { return(MCCI_OK); } else { return(MCCI_REQUEST_FAIL); } } @EOF chmod 644 cciClient.c echo x - connect.c cat >connect.c <<'@EOF' #include #include #include #include #include #include #ifdef _AIX #include #endif #ifndef INADDR_NONE #define INADDR_NONE 0xffffffff #endif #ifndef NULL #define NULL (char *)0 #endif #include "port.h" #include "connect.h" #include "memStuffForPipSqueeks.h" PortDescriptor *NetClientConnect(serverAddress,serverTCPPort) char *serverAddress; int serverTCPPort; /* create an internet client socket connection to the server address * return PortDescriptor * return 0 on can't connect */ { int sockfd; struct sockaddr_in serv_addr; unsigned long inaddr; struct hostent *hp; PortDescriptor *s; bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(serverTCPPort); /* * First try to convert the host name as a dotted-decimal number. * Only if that fails do we call gethostbyname(). */ if ((inaddr = inet_addr(serverAddress)) != INADDR_NONE) { /* it's dotted-decimal */ bcopy((char *) &inaddr, (char *) &serv_addr.sin_addr, sizeof(inaddr)); } else { /* it's a dotted alphanum name */ if ((hp = gethostbyname(serverAddress)) == 0) { #ifdef DEBUG printf("Can't get IP from hostname %s\n",serverAddress); #endif return(0); } else { bcopy(hp->h_addr, (char *) &serv_addr.sin_addr, hp->h_length); } } if (( sockfd = socket(AF_INET, SOCK_STREAM, 0 )) < 0) { #ifdef DEBUG printf("NetClientConnect():Couldn't create socket\n"); #endif return(0); } if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { #ifdef DEBUG printf("NetClientConnect():Couldn't connect\n"); #endif return(0); } #ifdef DEBUG printf("NetClientConnect():Connection established\n"); #endif if (!(s = (PortDescriptor *) MALLOC(sizeof(PortDescriptor)))) { return(0); } s->socketFD = sockfd; if (!(s->serverAddress = (char *) STRDUP(serverAddress))) { return(0); /* out of memory */ } s->serverTCPPort = serverTCPPort; s->connected = 1; s->numInBuffer = 0; return(s); } void NetCloseConnection(s) /* Close connection and free up PortDescriptor */ PortDescriptor *s; { if (!s) return; close(s->socketFD); s->connected = 0; /* FREE(s->serverAddress); FREE(s); */ } int NetWrite(s,message,length) PortDescriptor *s; char *message; int length; /* return number of bytes written */ /* return -1 on error */ { int wlength; if ((!s) || (!s->connected)) { return(-1); } wlength = write(s->socketFD, message, length); if (wlength != length) { /* error */ NetCloseConnection(s); } return(wlength); } int NetIsThereInput(s) /* Do a non block check on socket for input and return 1 for yes, 0 for no */ PortDescriptor *s; { static struct timeval timeout = { 0L , 0L }; int val; fd_set readfds; if ((!s) || (!s->connected)) { return(-1); } FD_ZERO(&readfds); FD_SET(s->socketFD,&readfds); if (0 < select(32, &readfds, 0, 0, &timeout)){ return(1); } else { return(0); } } int NetRead(s,buffer,bufferSize) PortDescriptor *s; char *buffer; int bufferSize; /* return number of characters read */ /* if 0 is returned after select returned true, then connection has been * terminated on remote side */ /* return -1 on error */ { int length; if ((!s) || (!s->connected)) { return(-1); } length = read(s->socketFD, buffer, bufferSize); if (length == -1) { /* error */ NetCloseConnection(s); } return(length); } char *NetReturnAddress(s) PortDescriptor *s; /* return address of this port */ { static char address[80]; if (!s || (!s->connected)) { return((char *) 0); } sprintf(address,"%s:%d",s->serverAddress,s->serverTCPPort); return(address); } int NetGetSocketDescriptor(s) /* extract socket file descriptor from the Port structure */ PortDescriptor *s; { if (!s) { return(-1); } return(s->socketFD); } int NetIsConnected(s) /* if connected, return 1, else 0 */ PortDescriptor *s; { if (!s) return(0); return(s->connected); } @EOF chmod 644 connect.c echo x - list.c cat >list.c <<'@EOF' /* * Copyright (C) 1992, Board of Trustees of the University of Illinois. * * Permission is granted to copy and distribute source with out fee. * Commercialization of this product requires prior licensing * from the National Center for Supercomputing Applications of the * University of Illinois. Commercialization includes the integration of this * code in part or whole into a product for resale. Free distribution of * unmodified source and use of NCSA software is not considered * commercialization. * */ /* * list.c: This module contains list manipulation routines that cunstruct * and maintain a linked list of data items. The record at the head of each * list contains pointers to the head, tail, and current list position. * the list itsself is doubly linked with both next and previous pointers. */ #include #include "listP.h" #ifndef MALLOC #define MALLOC malloc #define FREE free #endif #define NIL 0 static void ListPrintErr(s) char *s; { fprintf(stderr,"%s",s); } /* * This function returns the data located at the head of the linked list, * or NIL if the list is empty. As a side effect current is also set to * the head of the list. */ char *ListHead(theList) List theList; { if (!theList) return(NIL); theList->current = theList->head; if (theList->head) return(theList->head->value); else return(NIL); } /* * This function returns the data located at the tail of the linked list, * or NIL if the list is empty. As a side effect current is also set to * the tail of the list. */ char *ListTail(theList) List theList; { if (!theList) return(NIL); theList->current = theList->tail; if (theList->tail) return(theList->tail->value); else return(NIL); } /* * This function returns the data located at the current position in the * linked list, or NIL if the list is empty. */ char *ListCurrent(theList) List theList; { if (!theList) return(NIL); if (theList->current) return(theList->current->value); else return(NIL); } /* * This function returns the data located at the next element of the linked * list after the current position, or NIL if the list is empty, or you * are at its end. * As a side effect current is also set to the next entry in the list. */ char *ListNext(theList) List theList; { if (!theList) return(NIL); if (theList->current) { theList->current = theList->current->next; return(ListCurrent(theList)); } else return(NIL); } /* * This function returns the data located at the previous element of the linked * list before the current position, or NIL if the list is empty. * As a side effect current is also set to the previous entry in the list. */ char *ListPrev(theList) List theList; { if (!theList) return(NIL); if (theList->current) { theList->current = theList->current->prev; return(ListCurrent(theList)); } else return(NIL); } /* * Create a list head and initialize it to NIL. */ List ListCreate() { List retVal; if (!(retVal = (List) MALLOC(sizeof(struct LISTSTRUCT)))) { ListPrintErr("Out of Memory\n"); return((List) 0); } retVal->head = NIL; retVal->tail = NIL; retVal->current = NIL; retVal->listCount = 0; return(retVal); } /* * Destroy a list head, and free all associated memory. */ void ListDestroy(theList) List theList; { struct LISTINSTANCE *l; struct LISTINSTANCE *m; if (!theList) return; l = theList->head; while(l) { m = l; l = l->next; FREE(m); } FREE(theList); } /* * Add an entry to the end of the linked list. Current is changed to point to * the added element. */ int ListAddEntry(theList,v) /* return 0 on failure */ List theList; char *v; /* data to be added */ { struct LISTINSTANCE *l; if (!(l =(struct LISTINSTANCE *) MALLOC(sizeof(struct LISTINSTANCE)))){ ListPrintErr("Out of Memory\n"); return(0); } l->value = v; l->next = NIL; l->prev = NIL; if (theList->head == NIL) theList->tail = theList->head = l; else { theList->tail->next = l; l->prev = theList->tail; theList->tail = l; } theList->current = l; theList->listCount++; return(1); } /* * Search the list for an entry with a matching value field, and return * a pointer to that list element. Current is changed to point to the * element returned. */ static struct LISTINSTANCE *SearchListByValue(theList,v) List theList; char *v; { struct LISTINSTANCE *l; l = theList->head; while (l != NIL) { if (l->value == v) { theList->current = l; return(l); } else { l = l->next; } } theList->current = l; return(NIL); } /* * Find the list entry with a matching value field, and delete it * from the list. Set current to point to the element after the deleted * element in the list. */ int ListDeleteEntry(theList,v) /* removes the first occurance of v from the list */ /* return 0 if value not in list else 1 */ List theList; char *v; { struct LISTINSTANCE *l; char *retV; if (!(l = SearchListByValue(theList,v))) return(0); if (l->prev) l->prev->next = l->next; else theList->head = l->next; if (l->next) l->next->prev = l->prev; else theList->tail = l->prev; theList->current = l->next; retV = l->value; FREE(l); theList->listCount--; return(1); } int ListMakeEntryCurrent(theList,entry) /* return 0 on failure */ List theList; char *entry; { struct LISTINSTANCE *l; if (theList) { if (!(l = SearchListByValue(theList,entry))) return(0); theList->current = l; return(1); } return(0); } int ListCount(theList) /* return the number of elements in the list */ /* current position pointer is not affected */ List theList; { char *entry; int count; struct LISTINSTANCE *saveCurrent; if (theList) { return(theList->listCount); } else { return(0); } } /* return indexed entry. Index starts at 0 */ /* the current list pointer will be set to this entry */ /* return 0 on failure */ char *ListGetIndexedEntry(theList,number) List theList; int number; { char *entry; register int x; if (!theList) { return(0); } entry = ListHead(theList); for (x = 0; x < number; x++) { if (!entry) { return(0); } entry = ListNext(theList); } return(entry); } @EOF chmod 644 list.c echo x - support.c cat >support.c <<'@EOF' #include #include #include "cci.h" int ReadBuffer(s,data,numBytesToRead) /* this routine reads from the specified port, but also considers contents read and in buffer from the GetLine() routine. return the number of chars read */ MCCIPort s; char *data; int numBytesToRead; { int numRead = 0; int n; if (numBytesToRead <= s->numInBuffer) { memcpy(data,s->buffer,numBytesToRead); s->numInBuffer -= numBytesToRead; return(numBytesToRead); } if (s->numInBuffer > 0) { memcpy(data,s->buffer,s->numInBuffer); data += s->numInBuffer; numBytesToRead -= s->numInBuffer; numRead = s->numInBuffer; s->numInBuffer = 0; } while (numBytesToRead) { n = NetRead(s, data, numBytesToRead); numBytesToRead -= n; numRead += n; data += n; } return(numRead); } char *GetLine(s) /****** this routine needs an overhaul.... */ MCCIPort s; /* This routine returns a line read in from the socket file descriptor. * The location of the string returned is good until the next call. * Limitation of this routine: A line read in must not be bigger than * the buffersize. * 0 returned on error */ { int numBytes; char buf2[PORTBUFFERSIZE +1]; char *endptr; static char returnLine[PORTBUFFERSIZE * 2 +2]; register char *rptr,*ptr; register int count; if (s->numInBuffer < 1) { /* no character in s->buffer, so fill it up */ /* if (!connectedToServer) { return(0); } */ if (1 > (numBytes = NetRead(s, s->buffer, PORTBUFFERSIZE))) { /* End Of Connection */ /* DisconnectFromServer(s); */ #ifdef DEBUG printf("GetLine: End of Connection\n"); #endif return(0); } s->numInBuffer = numBytes; } s->buffer[s->numInBuffer]='\0'; if (!(endptr = strstr(s->buffer, "\r\n"))) { /* There is no in s->buffer */ /* if (!connectedToServer) { #ifdef DEBUG printf("GetLine: return 0 at point 3\n"); #endif return(0); } */ /* if (! NetIsThereInput(s)) { #ifdef DEBUG printf("GetLine: return 0 at point 4\n"); #endif return(0); } */ /* read in */ if (1 > (numBytes = NetRead(s, buf2, PORTBUFFERSIZE))) { /* End Of Connection */ /* NNTPDisconnectFromServer(s); */ #ifdef DEBUG printf("GetLine: return 0 at point 5\n"); #endif return(0); } memcpy(&(s->buffer[s->numInBuffer]),buf2,numBytes); s->numInBuffer += numBytes; s->buffer[s->numInBuffer]='\0'; if (!(endptr = strstr(s->buffer, "\r\n"))) { /* protocol error on server end Everything sent should be terminated with a ... just return for now */ #ifdef DEBUG printf("GetLine: return NULL at point 6\n"); #endif return(NULL); } } endptr++;endptr++; /* should be included in line*/ /* copy the line to the returnLine s->buffer */ count = 0; rptr = returnLine; ptr = s->buffer; while (ptr != endptr) { *rptr++ = *ptr++; count++; } *rptr = '\0'; /* null terminate the return line */ /* shift the s->buffer contents to the front */ s->numInBuffer -= count; bcopy(ptr,s->buffer,s->numInBuffer); /* memmove(s->buffer, ptr, s->numInBuffer);*/ return(returnLine); } /* NNTPGetLine() */ /* return a word out of the text */ void GetWordFromString(text,retStart,retEnd) char *text; /* text to get a word out of */ char **retStart; /* RETURNED: start of word in text */ char **retEnd; /* RETURNED: end of word in text */ { char *start; char *end; if (!text) { *retStart = *retEnd = text; return; } start = text; while ((*start) && isspace(*start)){ /*skip over leading space*/ start++; } end = start; while((*end) && (!isspace(*end))){ /* find next space */ end++; } *retStart = start; *retEnd = end; return; } @EOF chmod 644 support.c echo x - cci.h cat >cci.h <<'@EOF' #define MCCI_MAX_RETURN_TEXT 1024 /* return codes from cci api */ #define MCCI_OK 0 #define MCCI_FAIL 1 #define MCCI_OUTOFMEMORY 2 #define MCCI_REQUEST_FAIL 3 #define MCCI_NETWORK_ERROR 4 /* internal defines */ #define MCCI_DEFAULT 0 #define MCCI_OUTPUT_NONE 100 #define MCCI_OUTPUT_CURRENT 101 #define MCCI_OUTPUT_NEW 102 #define MCCI_ABSOLUTE 110 #define MCCI_RELATIVE 111 #define MCCI_SEND_BEFORE 210 #define MCCI_SEND_AFTER 220 /* protocol token strings */ #define MCCI_S_GET "GET" #define MCCI_S_DISPLAY "DISPLAY" #define MCCI_S_DISCONNECT "DISCONNECT" #define MCCI_S_QUIT "QUIT" #define MCCI_S_SEND "SEND" #define MCCI_S_OUTPUT "OUTPUT" #define MCCI_S_ANCHOR "ANCHOR" #define MCCI_S_BEFORE "BEFORE" #define MCCI_S_AFTER "AFTER" #define MCCI_S_BROWSERVIEW "BROWSERVIEW" #define MCCI_S_TO "TO" #define MCCI_S_STOP "STOP" #define MCCI_S_CURRENT "CURRENT" #define MCCI_S_NEW "NEW" #define MCCI_S_NONE "NONE" #define MCCI_S_HEADER "HEADER" #define MCCI_S_POST "POST" /* successful return codes in protocol*/ #define MCCIR_OK 200 #define MCCIR_GET_OK 210 #define MCCIR_DISPLAY_OK 211 #define MCCIR_DISCONNECT_OK 212 #define MCCIR_QUIT_OK 213 #define MCCIR_SEND_OUTPUT_OK 214 #define MCCIR_SEND_O_STOP_OK 215 #define MCCIR_SEND_ANCHOR_OK 216 #define MCCIR_SEND_A_STOP_OK 217 #define MCCIR_POST_OK 218 #define MCCIR_BROWSERVIEW_OK 219 #define MCCIR_BROWSERVIEW_STOP_OK 220 /* Send Anchor Before return codes */ #define MCCIR_SEND_ANCH_BEF_LINK_OK 280 /* clicked link */ #define MCCIR_SEND_ANCH_BEF_OPEN_OK 281 /* used open dialog */ #define MCCIR_SEND_ANCH_BEF_EDIT_OK 282 /* edited URL field */ #define MCCIR_SEND_ANCH_BEF_FORW_OK 283 /* clicked forward */ #define MCCIR_SEND_ANCH_BEF_BACK_OK 284 /* clicked back */ #define MCCIR_SEND_ANCH_BEF_RELO_OK 285 /* clicked reload */ #define MCCIR_SEND_ANCH_BEF_HIST_OK 286 /* from history */ #define MCCIR_SEND_ANCH_BEF_HOTL_OK 287 /* from hotlist */ #define MCCIR_SEND_ANCH_BEF_MCCI_OK 288 /* from CCI */ #define MCCIR_SEND_ANCH_BEF_OTHR_OK 289 /* from other source */ /* sendAnchor After return codes */ #define MCCIR_SEND_ANCH_AFT_LINK_OK 290 /* clicked link */ #define MCCIR_SEND_ANCH_AFT_OPEN_OK 291 /* used open dialog */ #define MCCIR_SEND_ANCH_AFT_EDIT_OK 292 /* edited URL field */ #define MCCIR_SEND_ANCH_AFT_FORW_OK 293 /* clicked forward */ #define MCCIR_SEND_ANCH_AFT_BACK_OK 294 /* clicked back */ #define MCCIR_SEND_ANCH_AFT_RELO_OK 295 /* clicked reload */ #define MCCIR_SEND_ANCH_AFT_HIST_OK 296 /* from history */ #define MCCIR_SEND_ANCH_AFT_HOTL_OK 297 /* from hotlist */ #define MCCIR_SEND_ANCH_AFT_MCCI_OK 298 /* from CCI */ #define MCCIR_SEND_ANCH_AFT_OTHR_OK 299 /* from other source */ /* additional data follows repsonse code */ #define MCCIR_ANCHOR_INFO 301 /* anchor visited information */ #define MCCIR_SEND_DATA_OUTPUT 302 /* output from Send Output protocol */ #define MCCIR_SEND_BROWSERVIEW 303 /* output from Send Browserview proto */ #define MCCIR_POST_OUTPUT 304 /* output from post */ /* problem response codes... client problems*/ #define MCCIR_UNRECOGNIZED 401 /* what's this? */ #define MCCIR_ERROR 402 /* does not follow protocol */ /* problem response codes... broswer problems*/ #define MCCIR_REQ_FAILED 500 /* request failed */ #define MCCIR_GET_FAILED 501 /* request failed */ #include "port.h" typedef PortDescriptor *MCCIPort; @EOF chmod 644 cci.h echo x - connect.h cat >connect.h <<'@EOF' extern PortDescriptor *NetClientConnect(); extern int NetWrite(); extern int NetIsThereInput(); extern int NetRead(); extern void NetCloseConnection(); extern char *NetReturnAddress(); @EOF chmod 644 connect.h echo x - list.h cat >list.h <<'@EOF' /* * Copyright (C) 1992, Board of Trustees of the University of Illinois. * * Permission is granted to copy and distribute source with out fee. * Commercialization of this product requires prior licensing * from the National Center for Supercomputing Applications of the * University of Illinois. Commercialization includes the integration of this * code in part or whole into a product for resale. Free distribution of * unmodified source and use of NCSA software is not considered * commercialization. * */ typedef struct LISTSTRUCT *List; extern List ListCreate(); extern void ListDestroy(); extern int ListAddEntry(); extern int ListDeleteEntry(); extern int ListMakeEntryCurrent(); extern int ListCount(); extern char *ListHead(); extern char *ListTail(); extern char *ListCurrent(); extern char *ListNext(); extern char *ListPrev(); extern char *ListGetIndexedEntry(); @EOF chmod 644 list.h echo x - listP.h cat >listP.h <<'@EOF' /* * Copyright (C) 1992, Board of Trustees of the University of Illinois. * * Permission is granted to copy and distribute source with out fee. * Commercialization of this product requires prior licensing * from the National Center for Supercomputing Applications of the * University of Illinois. Commercialization includes the integration of this * code in part or whole into a product for resale. Free distribution of * unmodified source and use of NCSA software is not considered * commercialization. * */ #ifndef ___HAS_LIST_STUFF_BEEN_INCLUDED_BEFORE___ #define ___HAS_LIST_STUFF_BEEN_INCLUDED_BEFORE___ #include #include "list.h" struct LISTINSTANCE { char *value; struct LISTINSTANCE *next; struct LISTINSTANCE *prev; }; struct LISTSTRUCT { struct LISTINSTANCE *head; struct LISTINSTANCE *tail; struct LISTINSTANCE *current; int listCount; }; #endif @EOF chmod 644 listP.h echo x - memStuffForPipSqueeks.h cat >memStuffForPipSqueeks.h <<'@EOF' #ifndef MALLOC #define MALLOC(x) malloc(x) #define FREE(x) free(x) #define CALLOC(x) calloc(x) #define STRDUP(x) strdup(x) #endif @EOF chmod 644 memStuffForPipSqueeks.h echo x - port.h cat >port.h <<'@EOF' #ifndef PORT_DOT_H_BEEN_INCLUDED_BEFORE #define PORTBUFFERSIZE 1024 typedef struct { int socketFD; char *serverAddress; int serverTCPPort; int connected; int numInBuffer; char buffer[PORTBUFFERSIZE *2 +2]; /* callBack(void *callBackData) */ void (*callBack) (); /* called when connection dropped*/ void *callBackData; } PortDescriptor; #define PORT_DOT_H_BEEN_INCLUDED_BEFORE #endif @EOF chmod 644 port.h echo x - Makefile cat >Makefile <<'@EOF' CFLAGS=-DDEBUG RANLIB = /bin/ranlib #RANLIB = /usr/bin/ranlib # the location of ranlib is system dependent. SRC = connect.c cciClient.c list.c support.c OBJ = connect.o cciClient.o list.o support.o CC = gcc CFLAGS = -ggdb libcci.a: $(OBJ) rm -f $@ ar q $@ $(OBJ) $(RANLIB) $@ clean: rm -f libcci.a $(OBJ) @EOF chmod 644 Makefile exit 0 .