home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 2 BBS
/
02-BBS.zip
/
msq31004.zip
/
FIDO.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-07-20
|
19KB
|
663 lines
/* fido.c
**
** released into the PUBLIC DOMAIN 30 jul 1990 by jim nutt
** Changes released into the PUBLIC DOMAIN 10 jul 1994 by John Dennis
**
** Fido/Opus style message base support functions for msgedsq.
** NOTE: These routines are slated for extinction in the near future.
** They're to be replaced by the Squish msgAPI. Possibly.
**
** 17/12/91 Added share support to all file routines and converted ansi file
** access code to low level read()/write().
** 26/01/92 Fixed bug in msg routines that seemed to cause a crash on zero
** length msgs (zero, as in no ctrl info and text).
** 23/02/92 Removed locking routines.
** 01/04/92 Made New msgs remain open until writing the text, also added
** some kludge code to handle the reading of opus msgs.
** 12/07/92 Added some more functions to make the interface solid.
** 03/12/92 Fix to WriteHeader.
**
*/
#define CHUNKSZ 256
#define TEXTLEN 96
#define NO_STDLIB /* causes conflicts with errno.h with MSC */
#define DEBUG 0
/*#include <msgapi.h>*/
#include "msged.h"
#include "date.h"
#include "stamp.h"
#include <errno.h>
#include <sys\types.h>
#include <sys\stat.h>
#ifdef __MSC__
# include <sys\locking.h>
#endif
#include <fcntl.h>
#include <share.h>
#if DEBUG
#include <assert.h>
#endif
/* file access shortcuts */
#define OPENC O_WRONLY|O_BINARY|O_CREAT /* open/create */
#define OPENRW O_RDWR|O_BINARY /* open read/write */
#define OPENR O_RDONLY|O_BINARY /* open read-only */
#define S_IMODE S_IREAD|S_IWRITE /* open mode */
/* prototypes */
#include "normal.h"
static int compare(const void *i, const void *j);
time_t stampToTimeT(struct _stamp *st);
struct _stamp *timeTToStamp(time_t);
/* externs */
extern char msgbuf[];
/* structures used in this module */
/* typedef struct _dosdate {
unsigned int day:5;
unsigned int mon:4;
unsigned int year:7;
unsigned int sec:5;
unsigned int min:6;
unsigned int hour:5;
} DOSDATE; */
typedef struct _fidoheader {
char from[36]; /* who from, */
char to[36]; /* who to, */
char subj[72]; /* message subject, */
char date[20]; /* creation date, */
unsigned char times[2]; /* number of times read, */
unsigned char dest[2]; /* destination node, */
unsigned char orig[2]; /* originating node */
unsigned char cost[2]; /* actual cost this msg */
unsigned char orig_net[2]; /* originating net */
unsigned char dest_net[2]; /* destination net */
unsigned char written[4]; /* when it was written */
unsigned char arrived[4]; /* when it arrived */
unsigned char reply[2]; /* thread to previous msg */
unsigned char attrib[2]; /* message attributes */
unsigned char up[2]; /* thread to next msg */
} MFIDO;
/* local vars */
static int fp = -1; /* current file handle */
static unsigned long *msgarr = NULL; /* array of *.msg numbers */
static unsigned long msgarrsz = 0; /* # of numbers in the array */
static unsigned long oldsz = 0; /* total size of the array */
static void timet_to_char(time_t now, unsigned char arr[])
{
struct tm *ts;
unsigned long x;
ts = localtime(&now);
x = ts->tm_year - 80;
x = (x << 4) | (ts->tm_mon + 1);
x = (x << 5) | ts->tm_mday;
x = (x << 5) | ts->tm_hour;
x = (x << 6) | ts->tm_min;
x = (x << 5) | (ts->tm_sec / 2);
arr[0] = (unsigned char)((x >> 16) & 0xff);
arr[1] = (unsigned char)((x >> 24) & 0xff);
arr[2] = (unsigned char)(x & 0xff);
arr[3] = (unsigned char)((x >> 8) & 0xff);
}
unsigned long FidoMsgnToUid(unsigned long n)
{
if (n > msgarrsz || n == 0)
return 0;
return msgarr[(size_t)(n - 1)];
}
unsigned long FidoUidToMsgn(unsigned long n)
{
unsigned long i;
for (i = 0; i < msgarrsz; i++)
if (msgarr[(size_t)i] == n)
break;
return (i == msgarrsz) ? 0 : i + 1;
}
int FidoMsgWriteText(char *text, unsigned long n, unsigned long mlen)
{
char i = 0;
unused(n);
unused(mlen);
#if DEBUG
assert(fp!=-1);
#endif
if (text == NULL)
{
write(fp, &i, sizeof(char));
return(TRUE);
}
write(fp, text, strlen(text));
return TRUE;
}
int FidoMsgWriteHeader(msg *m, int type)
{
MFIDO msghead;
char path[PATHLEN];
time_t now = time(NULL);
unsigned long n = m->msgnum;
int done = 0;
unsigned long x;
#if DEBUG
assert(fp==-1);
#endif
if (fp != -1)
{
close(fp);
fp = -1;
}
sprintf(path, "%s/%ld.MSG", CurArea.path, n);
if (m->new)
{
while (!done)
{
if ((fp = sopen(path, OPENR, SH_DENYNO, S_IMODE)) != -1)
{
close(fp); fp = -1; n++;
}
else
{
if ((fp = sopen(path, OPENC, SH_DENYNO, S_IMODE)) == -1)
return ERR_OPEN_MSG;
done = 1;
}
sprintf(path, "%s/%ld.MSG", CurArea.path, n);
}
}
else
{
if ((fp = sopen(path, OPENRW, SH_DENYNO, S_IMODE)) == -1)
return ERR_OPEN_MSG;
}
if (m->new)
{
if ((++msgarrsz) > oldsz)
{
unsigned long *t;
if ((t = calloc(1,
(size_t)((oldsz+=CHUNKSZ) * sizeof(unsigned long)))) == NULL)
outamemory();
memcpy(t, msgarr, (size_t)(sizeof(unsigned long) * msgarrsz));
release(msgarr);
msgarr = t;
}
msgarr[(size_t)(msgarrsz - 1)] = n;
}
memset(&msghead,0,sizeof msghead);
m->msgnum = n;
msghead.attrib[0] = (unsigned char)
((m->attrib.killsent << 7)
| (m->attrib.orphan << 6)
| (m->attrib.forward << 5)
| (m->attrib.attached << 4)
| (m->attrib.sent << 3)
| (m->attrib.recvd << 2)
| (m->attrib.crash << 1)
| (m->attrib.private));
msghead.attrib[1] = (unsigned char)
((m->attrib.ureq << 7)
| (m->attrib.areq << 6)
| (m->attrib.rcpt << 5)
| (m->attrib.rreq << 4)
| (m->attrib.freq << 3)
| (m->attrib.direct << 2)
| (m->attrib.hold << 1)
| (m->attrib.local));
x = FidoMsgnToUid((unsigned long) m->replyto);
msghead.reply[0] = (unsigned char)(x & 0xff);
msghead.reply[1] = (unsigned char)((x >> 8) & 0xff);
x = FidoMsgnToUid((unsigned long) m->replies[0]);
msghead.up[0] = (unsigned char)(x & 0xff);
msghead.up[1] = (unsigned char)((x >> 8) & 0xff);
msghead.times[0] = (unsigned char)(m->times_read & 0xff);
msghead.times[1] = (unsigned char)((m->times_read >> 8) & 0xff);
msghead.cost[0] = (unsigned char)(m->cost & 0xff);
msghead.cost[1] = (unsigned char)((m->cost >> 8) & 0xff);
msghead.dest_net[0] = (unsigned char)(m->to.net & 0xff);
msghead.dest_net[1] = (unsigned char)((m->to.net >> 8) & 0xff);
msghead.dest[0] = (unsigned char)(m->to.node & 0xff);
msghead.dest[1] = (unsigned char)((m->to.node >> 8) & 0xff);
if (m->isfrom != NULL)
{
memcpy(msghead.from,
m->isfrom,
min(sizeof msghead.from, strlen(m->isfrom)));
}
else
{
msghead.from[0] = '\0';
}
if (m->isto != NULL)
{
memcpy(msghead.to,
m->isto,
min(sizeof msghead.to, strlen(m->isto)));
}
else
{
msghead.to[0] = '\0';
}
if (m->subj != NULL)
{
memcpy(msghead.subj, m->subj, min(sizeof msghead.subj, strlen(m->subj)));
}
else
{
msghead.subj[0] = '\0';
}
memcpy(msghead.date, mtime(m->timestamp), 20);
msghead.orig_net[0] = (unsigned char)(m->from.net & 0xff);
msghead.orig_net[1] = (unsigned char)((m->from.net >> 8) & 0xff);
msghead.orig[0] = (unsigned char)(m->from.node & 0xff);
msghead.orig[1] = (unsigned char)((m->from.node >> 8) & 0xff);
if (SW->opusdate)
{
timet_to_char(now, msghead.written);
memcpy(msghead.arrived, msghead.written, sizeof msghead.arrived);
}
else
{
timet_to_char(m->timestamp, msghead.written);
if (m->time_arvd)
{
timet_to_char(m->time_arvd, msghead.written);
}
}
write(fp, (char *) &msghead, sizeof(MFIDO));
if (type == WR_HEADER)
{
close(fp);
fp = -1;
}
return TRUE;
}
msg *FidoMsgReadHeader(unsigned long n, int type)
{
MFIDO msghead;
char path[PATHLEN];
unsigned long msgn = msgarr[(size_t)(n - 1)];
msg *m;
#if DEBUG
assert(fp==-1);
#endif
if (fp != -1)
{
close(fp);
fp = -1;
}
memset(&msghead,0,sizeof msghead);
sprintf(path, "%s/%ld.MSG", CurArea.path, msgn);
if ((fp = sopen(path, OPENR, SH_DENYNO, S_IMODE)) == -1)
return NULL;
if ((m = calloc(1, sizeof(msg))) == NULL)
outamemory();
read(fp, (char *) &msghead, (int) sizeof(MFIDO));
m->msgnum = msgn;
m->from.net = (msghead.orig_net[1] << 8) | msghead.orig_net[0];
m->from.node = (msghead.orig[1] << 8) | msghead.orig[0];
m->to.net = (msghead.dest_net[1] << 8) | msghead.dest_net[0];
m->to.node = (msghead.dest[1] << 8) | msghead.dest[0];
memset(path, 0, sizeof path);
memcpy(path,msghead.date,sizeof msghead.date);
m->timestamp = parsedate(path);
if (msghead.arrived[0] != 0 || msghead.arrived[1] != 0 || msghead.arrived[2] != 0 || msghead.arrived[3] != 0)
{
m->time_arvd = stampToTimeT((struct _stamp *)msghead.arrived);
}
if ((m->isto = calloc(1, sizeof msghead.to + 1)) == NULL) outamemory();
if ((m->isfrom = calloc(1, sizeof msghead.from + 1)) == NULL) outamemory();
if ((m->subj = calloc(1, sizeof msghead.subj + 1)) == NULL) outamemory();
memcpy(m->isto, msghead.to, sizeof msghead.to);
memcpy(m->isfrom, msghead.from, sizeof msghead.from);
memcpy(m->subj, msghead.subj, sizeof msghead.subj);
m->replyto = FidoUidToMsgn((unsigned long) ((msghead.reply[1] << 8)
| msghead.reply[0]));
m->replies[0] = FidoUidToMsgn((unsigned long) ((msghead.up[1] << 8)
| msghead.up[0]));
m->attrib.ureq = ((msghead.attrib[1] >> 7) & 0x01);
m->attrib.areq = ((msghead.attrib[1] >> 6) & 0x01);
m->attrib.rcpt = ((msghead.attrib[1] >> 5) & 0x01);
m->attrib.rreq = ((msghead.attrib[1] >> 4) & 0x01);
m->attrib.freq = ((msghead.attrib[1] >> 3) & 0x01);
m->attrib.direct = ((msghead.attrib[1] >> 2) & 0x01);
m->attrib.hold = ((msghead.attrib[1] >> 1) & 0x01);
m->attrib.local = ((msghead.attrib[1]) & 0x01);
m->attrib.killsent = ((msghead.attrib[0] >> 7) & 0x01);
m->attrib.orphan = ((msghead.attrib[0] >> 6) & 0x01);
m->attrib.forward = ((msghead.attrib[0] >> 5) & 0x01);
m->attrib.attached = ((msghead.attrib[0] >> 4) & 0x01);
m->attrib.sent = ((msghead.attrib[0] >> 3) & 0x01);
m->attrib.recvd = ((msghead.attrib[0] >> 2) & 0x01);
m->attrib.crash = ((msghead.attrib[0] >> 1) & 0x01);
m->attrib.private = ((msghead.attrib[0]) & 0x01);
m->from.zone = CurArea.addr.zone;
m->to.zone = CurArea.addr.zone;
m->cost = (msghead.cost[1] << 8) | msghead.cost[0];
m->times_read = (msghead.times[1] << 8) | msghead.times[0];
m->to.fidonet = 1;
m->from.fidonet = 1;
m->text = NULL;
if (type == RD_HEADER) {
close(fp);
fp = -1;
}
return m;
}
char *FidoMsgReadText(unsigned long n)
{
static char *next = NULL;
static char *end = NULL;
static unsigned long s = 0;
int i, l;
char *t = NULL;
char *text = NULL;
char eol = '\0';
#if DEBUG
assert(fp!=-1);
assert(n>0);
#else
unused(n);
#endif
if (next == NULL && s != 0) { /* we are finished */
s = 0;
return NULL;
}
if (s == 0) {
s = BUFLEN;
memset(msgbuf, 0, (size_t)(s-1));
lseek(fp, (long) sizeof(MFIDO), SEEK_SET);
}
if (next == NULL) {
i = read(fp, msgbuf, (size_t)(s - 1));
if (i < 1) {
next = NULL;
s = 0;
return(NULL);
}
next = msgbuf;
while (i && (*next == '\0'))
i--, next++;
normalize(next);
end = msgbuf + strlen(msgbuf);
if (end < next)
next = end;
}
if ((end - next) == 0) t = NULL;
else t = memchr(next,'\n',(int) (end - next));
if (t == NULL) {
l = strlen(next);
memcpy(msgbuf,next,l+1);
i = read(fp,msgbuf+l, (size_t)(s - l - 1));
if (i < 1) {
next = NULL;
return(strdup(msgbuf));
}
*(msgbuf + l + i) = '\0';
normalize(msgbuf+l);
end = msgbuf + strlen(msgbuf);
next = msgbuf;
t = memchr(next,'\n', l + i);
}
if (t != NULL) {
eol = *(t+1);
*(t+1) = '\0';
}
text = strdup(next);
if (t != NULL) {
*(t+1) = eol;
next = t+1;
}
else
next = NULL;
return text;
}
int FidoMsgClose(void)
{
if (fp != -1)
{
close(fp);
fp = -1;
}
return TRUE;
}
int FidoMsgAreaClose(void)
{
CurArea.status = 0;
return TRUE;
}
int compare(const void *i, const void *j)
{
return ((int)(* (unsigned long *) i - * (unsigned long *) j));
}
void ScanArea(char *path)
{
struct _dta fileinfo;
int status;
unsigned long msgnum;
unsigned long *t = NULL;
status = dir_findfirst(path, 0, &fileinfo);
msgarrsz = 0;
while (status != -1)
{
if (fileinfo.size >= sizeof(MFIDO))
{
msgnum = atol(fileinfo.name);
msgarrsz++;
if (msgarrsz >= oldsz)
{
if ((t = (unsigned long *) calloc((size_t)(oldsz += CHUNKSZ),
sizeof(unsigned long))) == NULL) {
outamemory();
}
if (msgarr != NULL) /* copy old array accross */
{
memcpy(t, msgarr, (size_t)(sizeof(unsigned long) * msgarrsz));
}
release(msgarr);
msgarr = t;
}
msgarr[(size_t)(msgarrsz - 1)] = msgnum; /* assign new msgnumber */
}
status = dir_findnext(&fileinfo);
}
if (msgarr == NULL) { /* no files at all in dir */
msgarr = malloc(sizeof(unsigned long)*CHUNKSZ);
}
else {
qsort((void *) msgarr, (int) msgarrsz, (size_t) sizeof(unsigned long), compare);
}
}
long FidoMsgAreaOpen(AREA *a)
{
char path[PATHLEN];
short int c = 10, l;
unsigned long msgnum;
sprintf(path,"%s/*.msg",a->path);
a->last = a->first = 1;
a->current = a->lastread = 1;
a->status = 1;
ScanArea(path);
sprintf(path, "%s/%s",a->path, ST->lastread);
if ((fp = sopen(path, OPENR, SH_DENYNO, S_IMODE)) != -1)
{
read(fp, &c, sizeof c);
if (read(fp, &l, sizeof l) != sizeof l)
l = c;
close(fp);
fp = -1;
}
else
l = c = 0;
if (msgarrsz != 0)
{
a->last = msgarrsz;
msgnum = a->last;
for (msgnum=msgarrsz;
(msgnum>1) && (msgarr[(size_t)(msgnum-1)] != (unsigned long) c);
msgnum--) ;
/* void loop */
a->current = (!msgnum) ? a->last : msgnum;
msgnum = a->last;
for (msgnum=msgarrsz;
(msgnum>1) && (msgarr[(size_t)(msgnum-1)] != (unsigned long) l);
msgnum--);
/* void loop */
a->lastread = (!msgnum) ? a->last : msgnum;
}
return msgarrsz;
}
int FidoAreaSetLast(AREA *a)
{
int fp;
char path[PATHLEN];
short i = 0;
sprintf(path, "%s/%s", a->path, ST->lastread);
if ((fp = sopen(path, OPENRW, SH_DENYNO, S_IMODE)) == -1)
{
if (fp == -1 && (errno != EACCES && errno != EMFILE))
{
if ((fp = sopen(path, OPENC, SH_DENYNO, S_IMODE)) == -1)
return FALSE;
lseek(fp,0L,SEEK_SET);
write(fp, &i, sizeof(short));
write(fp, &i, sizeof(short));
close(fp);
return TRUE;
}
return FALSE;
}
lseek(fp, 0L, SEEK_SET);
if (msgarr)
{
i = (short)msgarr[(size_t)(a->current - 1)];
write(fp, (char *)&i, sizeof(short));
i = (short)msgarr[(size_t)(a->lastread - 1)];
write(fp, (char *)&i, sizeof(short));
}
else
{
write(fp, &i, sizeof(short));
write(fp, &i, sizeof(short));
}
close(fp);
return TRUE;
}
int FidoMsgDelete(unsigned long n)
{
char path[TEXTLEN];
/* delete the message */
sprintf(path, "%s/%lu.msg", CurArea.path, n);
remove(path);
/* we now re-scan the area just for the sake of it */
sprintf(path, "%s/*.msg", CurArea.path);
ScanArea(path);
return TRUE;
}
/* --- end of file --- */