-/* $Id$ */
+/* $Id$
+ *
+ * Copyright (c) 1987-2009 by the citadel.org team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
#include "sysdep.h"
#if TIME_WITH_SYS_TIME
#ifdef THREADED_CLIENT
#include <pthread.h>
#endif
+#include <libcitadel.h>
#include "citadel.h"
#include "citadel_ipc.h"
#include "citadel_decls.h"
-#include "tools.h"
#include "citadel_dirs.h"
#ifdef THREADED_CLIENT
pthread_mutex_t rwlock;
#ifdef HAVE_OPENSSL
static void serv_read_ssl(CtdlIPC *ipc, char *buf, unsigned int bytes);
static void serv_write_ssl(CtdlIPC *ipc, const char *buf, unsigned int nbytes);
-static void ssl_lock(int mode, int n, const char *file, int line);
static void endtls(SSL *ssl);
#ifdef THREADED_CLIENT
static unsigned long id_callback(void);
static void CtdlIPC_putline(CtdlIPC *ipc, const char *buf);
+
+const char *svn_revision(void);
+
/*
* Does nothing. The server should always return 200.
*/
int CtdlIPCQuit(CtdlIPC *ipc)
{
register int ret = 221; /* Default to successful quit */
- char aaa[128];
+ char aaa[SIZ];
CtdlIPC_lock(ipc);
if (ipc->sock > -1) {
/*
- * Asks the server to logout. Should always return 200, even if no user
+ * Asks the server to log out. Should always return 200, even if no user
* was logged in. The user will not be logged in after this!
*/
int CtdlIPCLogout(CtdlIPC *ipc)
{
register int ret;
- char aaa[128];
+ char aaa[SIZ];
CtdlIPC_lock(ipc);
CtdlIPC_putline(ipc, "LOUT");
}
}
*listing = march;
+ if (bbb) free(bbb);
return ret;
}
}
+/* RENU */
+int CtdlIPCRenameUser(CtdlIPC *ipc, char *oldname, char *newname, char *cret)
+{
+ register int ret;
+ char cmd[256];
+
+ if (!oldname) return -2;
+ if (!newname) return -2;
+ if (!cret) return -2;
+
+ snprintf(cmd, sizeof cmd, "RENU %s|%s", oldname, newname);
+ ret = CtdlIPCGenericCommand(ipc, cmd, NULL, 0, NULL, NULL, cret);
+ return ret;
+}
+
+
/* GOTO */
int CtdlIPCGotoRoom(CtdlIPC *ipc, const char *room, const char *passwd,
struct ctdlipcroom **rret, char *cret)
rret[0]->RRaide = extract_int(cret, 8);
rret[0]->RRnewmail = extract_long(cret, 9);
rret[0]->RRfloor = extract_int(cret, 10);
+ rret[0]->RRflags2 = extract_int(cret, 14);
} else {
free(*rret);
+ *rret = NULL;
}
+ free(aaa);
return ret;
}
size_t bbb_len;
int multipart_hunting = 0;
char multipart_prefix[128];
+ char encoding[256];
if (!cret) return -1;
if (!mret) return -1;
if (!*mret) return -1;
if (!msgnum) return -1;
+ strcpy(encoding, "");
strcpy(mret[0]->content_type, "");
sprintf(aaa, "MSG%d %ld|%d", as_mime, msgnum, headers);
ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, &bbb, &bbb_len, cret);
safestrncpy(mret[0]->node, &aaa[5], SIZ);
else if (!strncasecmp(aaa, "rcpt=", 5))
safestrncpy(mret[0]->recipient, &aaa[5], SIZ);
+ else if (!strncasecmp(aaa, "wefw=", 5))
+ safestrncpy(mret[0]->references, &aaa[5], SIZ);
else if (!strncasecmp(aaa, "time=", 5))
mret[0]->time = atol(&aaa[5]);
/* If doing a MIME thing, pull out the extra headers */
if (as_mime == 4) {
do {
- if (!strncasecmp(bbb, "Content-type: ", 14)) {
+ if (!strncasecmp(bbb, "Content-type:", 13)) {
extract_token(mret[0]->content_type, bbb, 0, '\n', sizeof mret[0]->content_type);
- strcpy(mret[0]->content_type,
- &mret[0]->content_type[14]);
+ strcpy(mret[0]->content_type, &mret[0]->content_type[13]);
striplt(mret[0]->content_type);
/* strip out ";charset=" portion. FIXME do something with
}
}
+ if (!strncasecmp(bbb, "X-Citadel-MSG4-Partnum:", 23)) {
+ extract_token(mret[0]->mime_chosen, bbb, 0, '\n', sizeof mret[0]->mime_chosen);
+ strcpy(mret[0]->mime_chosen, &mret[0]->mime_chosen[23]);
+ striplt(mret[0]->mime_chosen);
+ }
+ if (!strncasecmp(bbb, "Content-transfer-encoding:", 26)) {
+ extract_token(encoding, bbb, 0, '\n', sizeof encoding);
+ strcpy(encoding, &encoding[26]);
+ striplt(encoding);
+ }
remove_token(bbb, 0, '\n');
} while ((bbb[0] != 0) && (bbb[0] != '\n'));
remove_token(bbb, 0, '\n');
}
if (strlen(bbb)) {
+
+ if ( (!strcasecmp(encoding, "base64")) || (!strcasecmp(encoding, "quoted-printable")) ) {
+ char *ccc = NULL;
+ int bytes_decoded = 0;
+ ccc = malloc(strlen(bbb) + 32768);
+ if (!strcasecmp(encoding, "base64")) {
+ bytes_decoded = CtdlDecodeBase64(ccc, bbb, strlen(bbb));
+ }
+ else if (!strcasecmp(encoding, "quoted-printable")) {
+ bytes_decoded = CtdlDecodeQuotedPrintable(ccc, bbb, strlen(bbb));
+ }
+ ccc[bytes_decoded] = 0;
+ free(bbb);
+ bbb = ccc;
+ }
+
/* FIXME: Strip trailing whitespace */
bbb = (char *)realloc(bbb, (size_t)(strlen(bbb) + 1));
+
} else {
bbb = (char *)realloc(bbb, 1);
*bbb = '\0';
break;
case 15: ipc->ServInfo.newuser_disabled = atoi(buf);
break;
+ case 16: strcpy(ipc->ServInfo.default_cal_zone, buf);
+ break;
+ case 17: ipc->ServInfo.load_avg = atof(buf);
+ break;
+ case 18: ipc->ServInfo.worker_avg = atof(buf);
+ break;
+ case 19: ipc->ServInfo.thread_count = atoi(buf);
+ break;
+ case 20: ipc->ServInfo.has_sieve = atoi(buf);
+ break;
+ case 21: ipc->ServInfo.fulltext_enabled = atoi(buf);
+ break;
+ case 22: strcpy(ipc->ServInfo.svn_revision, buf);
+ break;
}
}
}
+ if (listing) free(listing);
return ret;
}
/* ENT0 */
-int CtdlIPCPostMessage(CtdlIPC *ipc, int flag, const struct ctdlipcmessage *mr, char *cret)
+int CtdlIPCPostMessage(CtdlIPC *ipc, int flag, int *subject_required, struct ctdlipcmessage *mr, char *cret)
{
register int ret;
char cmd[SIZ];
+ char *ptr;
if (!cret) return -2;
if (!mr) return -2;
+ if (mr->references) {
+ for (ptr=mr->references; *ptr != 0; ++ptr) {
+ if (*ptr == '|') *ptr = '!';
+ }
+ }
+
snprintf(cmd, sizeof cmd,
- "ENT0 %d|%s|%d|%d|%s|%s", flag, mr->recipient,
- mr->anonymous, mr->type, mr->subject, mr->author);
+ "ENT0 %d|%s|%d|%d|%s|%s||||||%s|", flag, mr->recipient,
+ mr->anonymous, mr->type, mr->subject, mr->author, mr->references);
ret = CtdlIPCGenericCommand(ipc, cmd, mr->text, strlen(mr->text), NULL,
NULL, cret);
+ if ((flag == 0) && (subject_required != NULL)) {
+ /* Is the server strongly recommending that the user enter a message subject? */
+ if ((cret[3] != '\0') && (cret[4] != '\0')) {
+ *subject_required = extract_int(&cret[4], 1);
+ }
+
+
+ }
return ret;
}
}
-/* NETF */
-int CtdlIPCNetSendFile(CtdlIPC *ipc, const char *filename, const char *destnode, char *cret)
-{
- register int ret;
- char *aaa;
-
- if (!cret) return -2;
- if (!filename) return -2;
- if (!destnode) return -2;
-
- aaa = (char *)malloc(strlen(filename) + strlen(destnode) + 7);
- if (!aaa) return -1;
-
- sprintf(aaa, "NETF %s|%s", filename, destnode);
- ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
- free(aaa);
- return ret;
-}
-
-
/* RWHO */
int CtdlIPCOnlineUsers(CtdlIPC *ipc, char **listing, time_t *stamp, char *cret)
{
/* UOPN */
-int CtdlIPCFileUpload(CtdlIPC *ipc, const char *save_as, const char *comment,
- const char *path,
+int CtdlIPCFileUpload(CtdlIPC *ipc, const char *save_as, const char *comment,
+ const char *path,
void (*progress_gauge_callback)
(CtdlIPC*, unsigned long, unsigned long),
char *cret)
{
register int ret;
char *aaa;
+ FILE *uploadFP;
+ char MimeTestBuf[64];
+ const char *MimeType;
+ long len;
if (!cret) return -1;
if (!save_as) return -1;
if (!*path) return -1;
if (ipc->uploading) return -1;
+ uploadFP = fopen(path, "r");
+ if (!uploadFP) return -2;
+
+ len = fread(&MimeTestBuf[0], 1, 64, uploadFP);
+ rewind (uploadFP);
+ if (len < 0)
+ return -3;
+
+ MimeType = GuessMimeType(&MimeTestBuf[0], len);
aaa = (char *)malloc(strlen(save_as) + strlen(comment) + 7);
if (!aaa) return -1;
- sprintf(aaa, "UOPN %s|%s", save_as, comment);
+ sprintf(aaa, "UOPN %s|%s|%s", save_as, MimeType, comment);
ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
free(aaa);
if (ret / 100 == 2) {
ipc->uploading = 1;
- ret = CtdlIPCWriteUpload(ipc, path, progress_gauge_callback, cret);
+ ret = CtdlIPCWriteUpload(ipc, uploadFP, progress_gauge_callback, cret);
ret = CtdlIPCEndUpload(ipc, (ret == -2 ? 1 : 0), cret);
ipc->uploading = 0;
}
char *cret)
{
register int ret;
+ FILE *uploadFP;
char *aaa;
+ char MimeTestBuf[64];
+ const char *MimeType;
+ long len;
if (!cret) return -1;
if (!save_as) return -1;
aaa = (char *)malloc(strlen(save_as) + 17);
if (!aaa) return -1;
- sprintf(aaa, "UIMG %d|%s", for_real, save_as);
+ uploadFP = fopen(path, "r");
+ if (!uploadFP) return -2;
+
+ len = fread(&MimeTestBuf[0], 1, 64, uploadFP);
+ rewind (uploadFP);
+ if (len < 0)
+ return -3;
+ MimeType = GuessMimeType(&MimeTestBuf[0], 64);
+
+ sprintf(aaa, "UIMG %d|%s|%s", for_real, MimeType, save_as);
ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
free(aaa);
if (ret / 100 == 2 && for_real) {
ipc->uploading = 1;
- ret = CtdlIPCWriteUpload(ipc, path, progress_gauge_callback, cret);
+ ret = CtdlIPCWriteUpload(ipc, uploadFP, progress_gauge_callback, cret);
ret = CtdlIPCEndUpload(ipc, (ret == -2 ? 1 : 0), cret);
ipc->uploading = 0;
}
struct ExpirePolicy **policy, char *cret)
{
static char *proto[] = {"room", "floor", "site", "mailboxes" };
- char aaa[11];
+ char cmd[256];
register int ret;
if (!cret) return -2;
if (!*policy) return -1;
if (which < 0 || which > 3) return -2;
- sprintf(aaa, "GPEX %s", proto[which]);
- ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
+ sprintf(cmd, "GPEX %s", proto[which]);
+ ret = CtdlIPCGenericCommand(ipc, cmd, NULL, 0, NULL, NULL, cret);
if (ret / 100 == 2) {
policy[0]->expire_mode = extract_int(cret, 0);
policy[0]->expire_value = extract_int(cret, 1);
}
return ret;
-
}
int CtdlIPCGetSystemConfigByType(CtdlIPC *ipc, const char *mimetype,
char **listing, char *cret)
{
+ register int ret;
char *aaa;
size_t bytes;
aaa = malloc(strlen(mimetype) + 13);
if (!aaa) return -1;
sprintf(aaa, "CONF GETSYS|%s", mimetype);
- return CtdlIPCGenericCommand(ipc, aaa, NULL, 0,
+ ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0,
listing, &bytes, cret);
+ free(aaa);
+ return ret;
}
int CtdlIPCSetSystemConfigByType(CtdlIPC *ipc, const char *mimetype,
const char *listing, char *cret)
{
+ register int ret;
char *aaa;
if (!cret) return -2;
aaa = malloc(strlen(mimetype) + 13);
if (!aaa) return -1;
sprintf(aaa, "CONF PUTSYS|%s", mimetype);
- return CtdlIPCGenericCommand(ipc, aaa, listing, strlen(listing),
+ ret = CtdlIPCGenericCommand(ipc, aaa, listing, strlen(listing),
NULL, NULL, cret);
+ free(aaa);
+ return ret;
}
/* QDIR */
int CtdlIPCDirectoryLookup(CtdlIPC *ipc, const char *address, char *cret)
{
+ register int ret;
char *aaa;
if (!address) return -2;
if (!aaa) return -1;
sprintf(aaa, "QDIR %s", address);
- return CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
+ ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
+ free(aaa);
+ return ret;
}
/* WRIT */
-int CtdlIPCWriteUpload(CtdlIPC *ipc, const char *path,
+int CtdlIPCWriteUpload(CtdlIPC *ipc, FILE *uploadFP,
void (*progress_gauge_callback)
(CtdlIPC*, unsigned long, unsigned long),
char *cret)
size_t bytes;
char aaa[SIZ];
char buf[4096];
- FILE *fd;
+ FILE *fd = uploadFP;
+ int ferr;
if (!cret) return -1;
- if (!path) return -1;
- if (!*path) return -1;
-
- fd = fopen(path, "r");
- if (!fd) return -2;
fseek(fd, 0L, SEEK_END);
bytes = ftell(fd);
}
if (progress_gauge_callback)
progress_gauge_callback(ipc, 1, 1);
- return (!ferror(fd) ? ret : -2);
+ ferr = ferror(fd);
+ fclose(fd);
+ return (!ferr ? ret : -2);
}
/*
* send binary to server
*/
-static void serv_write(CtdlIPC *ipc, const char *buf, unsigned int nbytes)
+void serv_write(CtdlIPC *ipc, const char *buf, unsigned int nbytes)
{
unsigned int bytes_written = 0;
int retval;
sleep(1);
continue;
}
+/***
+ Not sure why we'd want to handle these error codes any differently,
+ but this definitely isn't the way to handle them. Someone must have
+ naively assumed that we could fall back to unencrypted communications,
+ but all it does is just recursively blow the stack.
if (errval == SSL_ERROR_ZERO_RETURN ||
errval == SSL_ERROR_SSL) {
serv_read(ipc, &buf[len], bytes - len);
return;
}
+ ***/
error_printf("SSL_read in serv_read: %s\n",
ERR_reason_error_string(ERR_peek_error()));
connection_died(ipc, 1);
}
+#ifdef THREADED_CLIENT
+static void ssl_lock(int mode, int n, const char *file, int line)
+{
+ if (mode & CRYPTO_LOCK)
+ pthread_mutex_lock(Critters[n]);
+ else
+ pthread_mutex_unlock(Critters[n]);
+}
+#endif /* THREADED_CLIENT */
+
+
static void CtdlIPC_init_OpenSSL(void)
{
int a;
}
-static void ssl_lock(int mode, int n, const char *file, int line)
-{
-#ifdef THREADED_CLIENT
- if (mode & CRYPTO_LOCK)
- pthread_mutex_lock(Critters[n]);
- else
- pthread_mutex_unlock(Critters[n]);
-#endif /* THREADED_CLIENT */
-}
#ifdef THREADED_CLIENT
static unsigned long id_callback(void) {
#endif /* HAVE_OPENSSL */
+int
+ReadNetworkChunk(CtdlIPC* ipc)
+{
+ fd_set read_fd;
+ int tries;
+ int ret = 0;
+ int err = 0;
+ struct timeval tv;
+ size_t n;
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 1000;
+ tries = 0;
+ n = 0;
+ while (1)
+ {
+ errno=0;
+ FD_ZERO(&read_fd);
+ FD_SET(ipc->sock, &read_fd);
+ ret = select(ipc->sock+1, &read_fd, NULL, NULL, &tv);
+
+// fprintf(stderr, "\nselect failed: %d %d %s\n", ret, err, strerror(err));
+
+ if (ret > 0) {
+
+ *(ipc->BufPtr) = '\0';
+// n = read(ipc->sock, ipc->BufPtr, ipc->BufSize - (ipc->BufPtr - ipc->Buf) - 1);
+ n = recv(ipc->sock, ipc->BufPtr, ipc->BufSize - (ipc->BufPtr - ipc->Buf) - 1, 0);
+ if (n > 0) {
+ ipc->BufPtr[n]='\0';
+ ipc->BufUsed += n;
+ return n;
+ }
+ else
+ return n;
+ }
+ else if (ret < 0) {
+ if (!(errno == EINTR || errno == EAGAIN))
+ error_printf( "\nselect failed: %d %s\n", err, strerror(err));
+ return -1;
+ }/*
+ else {
+ tries ++;
+ if (tries >= 10)
+ n = read(ipc->sock, ipc->BufPtr, ipc->BufSize - (ipc->BufPtr - ipc->Buf) - 1);
+ if (n > 0) {
+ ipc->BufPtr[n]='\0';
+ ipc->BufUsed += n;
+ return n;
+ }
+ else {
+ connection_died(ipc, 0);
+ return -1;
+ }
+ }*/
+ }
+}
+
/*
* input string from socket - implemented in terms of serv_read()
*/
+#ifdef CHUNKED_READ
+
+static void CtdlIPC_getline(CtdlIPC* ipc, char *buf)
+{
+ int i, ntries;
+ char *aptr, *bptr, *aeptr, *beptr;
+
+// error_printf("---\n");
+
+ beptr = buf + SIZ;
+#if defined(HAVE_OPENSSL)
+ if (ipc->ssl) {
+
+ /* Read one character at a time. */
+ for (i = 0;; i++) {
+ serv_read(ipc, &buf[i], 1);
+ if (buf[i] == '\n' || i == (SIZ-1))
+ break;
+ }
+
+ /* If we got a long line, discard characters until the newline. */
+ if (i == (SIZ-1))
+ while (buf[i] != '\n')
+ serv_read(ipc, &buf[i], 1);
+
+ /* Strip the trailing newline (and carriage return, if present) */
+ if (i>=0 && buf[i] == 10) buf[i--] = 0;
+ if (i>=0 && buf[i] == 13) buf[i--] = 0;
+ }
+ else
+#endif
+ {
+ if (ipc->Buf == NULL)
+ {
+ ipc->BufSize = SIZ;
+ ipc->Buf = (char*) malloc(ipc->BufSize + 10);
+ *(ipc->Buf) = '\0';
+ ipc->BufPtr = ipc->Buf;
+ }
+
+ ntries = 0;
+// while ((ipc->BufUsed == 0)||(ntries++ > 10))
+ if (ipc->BufUsed == 0)
+ ReadNetworkChunk(ipc);
+
+//// if (ipc->BufUsed != 0) while (1)
+ bptr = buf;
+
+ while (1)
+ {
+ aptr = ipc->BufPtr;
+ aeptr = ipc->Buf + ipc->BufSize;
+ while ((aptr < aeptr) &&
+ (bptr < beptr) &&
+ (*aptr != '\0') &&
+ (*aptr != '\n'))
+ *(bptr++) = *(aptr++);
+ if ((*aptr == '\n') && (aptr < aeptr))
+ {
+ /* Terminate it right, remove the line breaks */
+ while ((aptr < aeptr) && ((*aptr == '\n') || (*aptr == '\r')))
+ aptr ++;
+ while ((aptr < aeptr ) && (*(aptr + 1) == '\0') )
+ aptr ++;
+ *(bptr++) = '\0';
+// fprintf(stderr, "parsing %d %d %d - %d %d %d %s\n", ipc->BufPtr - ipc->Buf, aptr - ipc->BufPtr, ipc->BufUsed , *aptr, *(aptr-1), *(aptr+1), buf);
+ if ((bptr > buf + 1) && (*(bptr-1) == '\r'))
+ *(--bptr) = '\0';
+
+ /* is there more in the buffer we need to read later? */
+ if (ipc->Buf + ipc->BufUsed > aptr)
+ {
+ ipc->BufPtr = aptr;
+ }
+ else
+ {
+ ipc->BufUsed = 0;
+ ipc->BufPtr = ipc->Buf;
+ }
+// error_printf("----bla6\n");
+ return;
+
+ }/* should we move our read stuf to the bufferstart so we have more space at the end? */
+ else if ((ipc->BufPtr != ipc->Buf) &&
+ (ipc->BufUsed > (ipc->BufSize - (ipc->BufSize / 4))))
+ {
+ size_t NewBufSize = ipc->BufSize * 2;
+ int delta = (ipc->BufPtr - ipc->Buf);
+ char *NewBuf;
+
+ /* if the line would end after our buffer, we should use a bigger buffer. */
+ NewBuf = (char *)malloc (NewBufSize + 10);
+ memcpy (NewBuf, ipc->BufPtr, ipc->BufUsed - delta);
+ free(ipc->Buf);
+ ipc->Buf = ipc->BufPtr = NewBuf;
+ ipc->BufUsed -= delta;
+ ipc->BufSize = NewBufSize;
+ }
+ if (ReadNetworkChunk(ipc) <0)
+ {
+// error_printf("----bla\n");
+ return;
+ }
+ }
+/// error_printf("----bl45761%s\nipc->BufUsed");
+ }
+// error_printf("----bla1\n");
+}
+
+#else /* CHUNKED_READ */
+
static void CtdlIPC_getline(CtdlIPC* ipc, char *buf)
{
int i;
serv_read(ipc, &buf[i], 1);
/* Strip the trailing newline (and carriage return, if present) */
- if (buf[i] == 10) buf[i--] = 0;
- if (buf[i] == 13) buf[i--] = 0;
+ if (i>=0 && buf[i] == 10) buf[i--] = 0;
+ if (i>=0 && buf[i] == 13) buf[i--] = 0;
}
+
+#endif /* CHUNKED_READ */
+
+
void CtdlIPC_chat_recv(CtdlIPC* ipc, char* buf)
{
CtdlIPC_getline(ipc, buf);
ipc->uploading = 0;
ipc->last_command_sent = 0L;
ipc->network_status_cb = NULL;
+ ipc->Buf = NULL;
+ ipc->BufUsed = 0;
+ ipc->BufPtr = NULL;
strcpy(cithost, DEFAULT_HOST); /* default host */
strcpy(citport, DEFAULT_PORT); /* default port */
shutdown(ipc->sock, 2); /* Close it up */
ipc->sock = -1;
}
+ if (ipc->Buf != NULL)
+ free (ipc->Buf);
+ ipc->Buf = NULL;
+ ipc->BufPtr = NULL;
ifree(ipc);
}