+ cprintf("%d Message %s.\n", OK, (is_copy ? "copied" : "moved") );
+}
+
+
+
+/*
+ * GetSuppMsgInfo() - Get the supplementary record for a message
+ */
+void GetSuppMsgInfo(struct SuppMsgInfo *smibuf, long msgnum)
+{
+
+ struct cdbdata *cdbsmi;
+ long TheIndex;
+
+ memset(smibuf, 0, sizeof(struct SuppMsgInfo));
+ smibuf->smi_msgnum = msgnum;
+ smibuf->smi_refcount = 1; /* Default reference count is 1 */
+
+ /* Use the negative of the message number for its supp record index */
+ TheIndex = (0L - msgnum);
+
+ cdbsmi = cdb_fetch(CDB_MSGMAIN, &TheIndex, sizeof(long));
+ if (cdbsmi == NULL) {
+ return; /* record not found; go with defaults */
+ }
+ memcpy(smibuf, cdbsmi->ptr,
+ ((cdbsmi->len > sizeof(struct SuppMsgInfo)) ?
+ sizeof(struct SuppMsgInfo) : cdbsmi->len));
+ cdb_free(cdbsmi);
+ return;
+}
+
+
+/*
+ * PutSuppMsgInfo() - (re)write supplementary record for a message
+ */
+void PutSuppMsgInfo(struct SuppMsgInfo *smibuf)
+{
+ long TheIndex;
+
+ /* Use the negative of the message number for its supp record index */
+ TheIndex = (0L - smibuf->smi_msgnum);
+
+ lprintf(9, "PuttSuppMsgInfo(%ld) - ref count is %d\n",
+ smibuf->smi_msgnum, smibuf->smi_refcount);
+
+ cdb_store(CDB_MSGMAIN,
+ &TheIndex, sizeof(long),
+ smibuf, sizeof(struct SuppMsgInfo));
+
+}
+
+/*
+ * AdjRefCount - change the reference count for a message;
+ * delete the message if it reaches zero
+ */
+void AdjRefCount(long msgnum, int incr)
+{
+
+ struct SuppMsgInfo smi;
+ long delnum;
+
+ /* This is a *tight* critical section; please keep it that way, as
+ * it may get called while nested in other critical sections.
+ * Complicating this any further will surely cause deadlock!
+ */
+ begin_critical_section(S_SUPPMSGMAIN);
+ GetSuppMsgInfo(&smi, msgnum);
+ smi.smi_refcount += incr;
+ PutSuppMsgInfo(&smi);
+ end_critical_section(S_SUPPMSGMAIN);
+
+ lprintf(9, "Ref count for message <%ld> after write is <%d>\n",
+ msgnum, smi.smi_refcount);
+
+ /* If the reference count is now zero, delete the message
+ * (and its supplementary record as well).
+ */
+ if (smi.smi_refcount == 0) {
+ lprintf(9, "Deleting message <%ld>\n", msgnum);
+ delnum = msgnum;
+ cdb_delete(CDB_MSGMAIN, &delnum, sizeof(long));
+ delnum = (0L - msgnum);
+ cdb_delete(CDB_MSGMAIN, &delnum, sizeof(long));
+ }
+}
+
+/*
+ * Write a generic object to this room
+ *
+ * Note: this could be much more efficient. Right now we use two temporary
+ * files, and still pull the message into memory as with all others.
+ */
+void CtdlWriteObject(char *req_room, /* Room to stuff it in */
+ char *content_type, /* MIME type of this object */
+ char *tempfilename, /* Where to fetch it from */
+ struct usersupp *is_mailbox, /* Mailbox room? */
+ int is_binary, /* Is encoding necessary? */
+ int is_unique, /* Del others of this type? */
+ unsigned int flags /* Internal save flags */
+ )
+{
+
+ FILE *fp, *tempfp;
+ char filename[PATH_MAX];
+ char cmdbuf[256];
+ int ch;
+ struct quickroom qrbuf;
+ char roomname[ROOMNAMELEN];
+ struct CtdlMessage *msg;
+ size_t len;
+
+ if (is_mailbox != NULL)
+ MailboxName(roomname, is_mailbox, req_room);
+ else
+ safestrncpy(roomname, req_room, sizeof(roomname));
+ lprintf(9, "CtdlWriteObject() to <%s> (flags=%d)\n", roomname, flags);
+
+ strcpy(filename, tmpnam(NULL));
+ fp = fopen(filename, "w");
+ if (fp == NULL)