/*
	bbscfile.c

*/

/* #define DEBUG 1 */

#include "bbscdef.h"
#include <string.h>
#include <sys/types.h>     /* For compatibility */
#include <fcntl.h>
#ifdef linux
#include "nolock.h"
#else
#include <sys/locking.h>
#endif

#define LASTDATE  " 04/21/90 "

#define PGMNAME "BBSCFILE "
#define VERSION " 7.92 "
extern int user_priv;

	static	char	bufmsg0[MSG1MAX+1],
		buftmp[MSGSECT+256],
		this1[11],
		next1[11];
hdrwrt()		/* write the header from memory variables */
	{		/* header is a 1 record file */
	int	fd;
	int	fd1;

	strcpy(who_am_i, m_pathname);
	strcat(who_am_i, HEADER);
	if ((fd = open(who_am_i,WRITE,0666)) < 0)	/* open i/o */
		{
		portsout("Can't open header-file, will create it!") ;
		portsout(CRLF) ;
		if ((fd = creat(who_am_i,0666)) < 0)
			{
			portsout("Can't create header-file, aborting!") ;
			portsout(CRLF) ;
			return(ERROR) ;
			}
		}
	lseek(fd, 0L, 0);
	locking(fd, LK_LOCK, 0L);
	strcpy(who_am_i, m_pathname);
	strcat(who_am_i, CROSSREF);
	if ((fd1 = open(who_am_i,WRITE,0666)) < 0)
		{
		portsout("Can't open xref file, will create it!");
		portsout(CRLF) ;
		if ((fd1 = creat(who_am_i,0666)) < 0)
			{
			portsout(" XREF creation error! -- abort!");
			portsout(CRLF);
			return(ERROR) ;
			}
		}
	lseek(fd1, 0L, 0);
	locking(fd1, LK_LOCK, 0L);
	itoa(h_next_msg,h_next) ;	/* convert int to char */
	itoa(h_act_msg,h_act) ;
	strfill(buf128,26,MSGSECT) ;	/* init buf128 to all hex 1a */
	sprintf(buf128,"%s~%s~%s~",	/* build record */
		h_next_msg,
		h_act_msg,
		h_date) ;
	write(fd,buf128,MSGSECT) ;	/* write it */
	lseek(fd, 0L, 0);
	locking(fd, LK_UNLCK, 0L);
	close(fd) ;			/* no need to leave it open */
	write(fd1,xtable,4000);
	lseek(fd1, 0L, 0);
	locking(fd1, LK_UNLCK, 0L);
	close(fd1) ;
	return(OK) ;
	}

hdrread()		/* read the header file into memory */
	{
	int	fd,
		i,
		cnt1,
		cnt;

	strcpy(who_am_i, m_pathname);
	strcat(who_am_i, HEADER);
	if ((fd = open(who_am_i,READ,0666)) < 0)	/* open input */
		{
		portsout("Can't open header-file, using inital values!") ;
		portsout(CRLF) ;
		h_next = 1 ;
		h_next_msg[0] = '1' ; h_next_msg[1] = 0 ;
		h_act = 1 ;
		h_act_msg[0] = '1' ; h_act_msg[1] = 0 ;
		h_date[0] = '0' ; h_date[1] = 0 ;
		hdrwrt() ; goto next;
		}
	lseek(fd, 0L, 0);
	locking(fd, LK_LOCK, 0L);
	if((cnt=read(fd,buf128,MSGSECT)) != MSGSECT)
		{
		portsout(CRLF) ;
    		portsout("<<< header read error >>>") ;
		portsout(CRLF) ;
		return(ERROR) ;
		}
	cnt = sscanf(buf128,"%[^~]~%[^~]~%[^~]~", 
			h_next_msg,
			h_act_msg,
			h_date) ;
next:
	lseek(fd, 0L, 0);
	locking(fd, LK_UNLCK, 0L);
	close(fd) ;		/* no need to leave it open */
	strcpy(who_am_i, m_pathname);
	strcat(who_am_i, CROSSREF);
	if ((fd = open(who_am_i,READ,0666)) < 0)
		{
		portsout("Can't open xref file --- setting values!");
		portsout(CRLF);
		xtable[0] = 1L;
		for (i = 1; i <= 999; i++)
			xtable[i] = 0L;
		return ;
		}
	lseek(fd, 0L, 0);
	locking(fd, LK_LOCK, 0L);
	if ((cnt1=read(fd, xtable, 4000)) != 4000)
		{
		portsout(CRLF) ;
		portsout("<<< xref read error >>>");
		portsout(CRLF);
		return(ERROR);
		}
	lseek(fd, 0L, 0);
	locking(fd, LK_UNLCK, 0L);
	close (fd);
/*

	if (cnt != 2)
		{
		return(ERROR) ;
		}
*/
	h_next = atoi(h_next_msg) ;
	h_act = atoi(h_act_msg) ;
	return(OK) ;
	}

msgopen(how)
int	how ;		/* how to open 0=input, 1=output, 2=i/o */
	{
	int	fd ;

	strcpy(who_am_i, m_pathname);
	strcat(who_am_i, MESSAGES);
	if ((fd = open(who_am_i,how,0666)) < 0)	/* open i/o */
		{
		portsout("can't open message-file, will create it!") ;
		portsout(CRLF) ;
		if ((fd = creat(who_am_i,0666)) < 0)
			{
			portsout("can't create message-file, aborting!") ;
			portsout(CRLF) ;
			return(ERROR) ;
			}
		}
	lseek(fd, 0L, 0);
	locking(fd, LK_RLCK, 0L);
	return(fd) ;
	}

msgclose(fd)
int	fd ;
	{
	lseek(fd, 0L, 0);
	locking(fd, LK_UNLCK, 0L);
	return(close(fd)) ;
	}

msgwrt(fd)		/* write the message file from memory variables */
int	fd;		/* writes a message starting with the h_next msg # */
	{
	int	rc,			/* return code */
		cnt1,
		cnt2,
		len;

	rc = cnt1 = len = cnt2 = 0 ;
	itoa(this1,h_next) ;	            /* convert int to char */
	xtable[h_act - 1] = h_next;
	for( len=h_act; len < 1000; len++)
		xtable[len] = 0L;	    /* guarantee clean table */
	h_act++;
	rc = seek(fd,h_next - 1,0) ;        /* seek next available sector */
	h_next++ ;
	itoa(next1,h_next) ;
	strfill(buf128,0,MSGSECT) ;		/* init buf128 to all hex 00 */
/*
*			build first piece of msg record
*/
	sprintf(buf128,"%-10s~%-10s~%-2s~%-9s~%-15s~%-21s~%-21s~%-11s~%-21s~",
		this1,					/* this rcd # */
		next1,					/*  points next rcd # */
		msg_delete,				/* delete byte */
		msg_date,
		msg_time,
		msg_to,
		msg_from,
		msg_pass,
		msg_subject);
	rc = write(fd,buf128,MSGSECT);	/* write the first 128 byte record */
					/*  for a message record */
/*
*			build the n+1 piece of msg record
*/

	len = (strlen(msg_text) / MSG1MAX) + 1; /* calc how many more 128 */
						/*  byte records to write */
	cnt2 = 1 ;				/* init for substr */
	while (len--)
		{
		itoa(this1,h_next);		/* calc/convert record #'s */
		h_next++;                      
		if (len == 0)
			{
			strcpy(next1,"0");	/* marks last 128 byte piece */
			}			/*  of a msg */
		else
			{
			itoa(next1,h_next);
			}
		strfill(bufmsg0,0,MSG1MAX);
		substr(msg_text,bufmsg0,cnt2,MSG1MAX); /* mv MSG1MAX to buff */
		cnt2 += MSG1MAX;		/* up cnt2 by MSG1MAX */
		strfill(buf128,0,MSGSECT);	/* init buf128 to all hex 00 */
		sprintf(buf128,"%-10s~%-10s~%-2s~%-102s~",
			this1,			/* this rcd # */
			next1,			/* point to next rcd # */
			msg_delete,		/* delete byte */
			bufmsg0);		/* piece of msg */
		rc = write(fd,buf128,MSGSECT);	/* write n+1 128 byte record */
		}

	strfill(buf128,26,MSGSECT);		/* fill with all hex 1a */
	rc = write(fd,buf128,MSGSECT);	/* write all hex 1a 128 byte record */
	return(OK);
	}

msgrewrt(fd,r_msg)	/* re-write the message file from memory variables */
int	fd,		/* re-writes only the 1st part of a message */
	r_msg;		/* used to update the delete byte */
	{
	int	rc,			/* return code */
		cnt1,
		file_size;

	rc = cnt1 = 0;
	if (r_msg > h_next)	/* don't try to seek past end of file */
		{
		return(ERROR);
		}
	if ((rc = seek(fd,r_msg-1,0)) == ERROR)	/* seek to requested sector */
		{
		return(ERROR);
		}
	itoa(this1,r_msg);		/* convert int to char */
	r_msg++;
	itoa(next1,r_msg);
	strfill(buf128,0,MSGSECT);		/* init buf128 to all hex 00 */
/*
*			build first piece of msg record
*/
	sprintf(buf128,"%-10s~%-10s~%-2s~%-9s~%-15s~%-21s~%-21s~%-11s~%-21s~",
		this1,					/* this rcd # */
		next1,					/* points next rcd # */
		msg_delete,				/* delete byte */
		msg_date,
		msg_time,
		msg_to,
		msg_from,
		msg_pass,
		msg_subject);
	rc = write(fd,buf128,MSGSECT);	/* write the first 128 byte record */
					/*  for a message record */
	return(OK);
	}


msgread(fd,msgno)		/* read message number requested */
int	fd,			/* returns ERROR if msg past eof */
	msgno;			/* returns 0 if msg is not 1st piece */
				/*   of a message */
				/* returns 0 if msg is deleted */
				/* returns msg # if successful */
	{
	int	rc,			/* return code */
		msgac,
		cnt1,
		cnt2,
		len,
		next,
		ret_this,
		file_size;
	char	 act[11];

	msgac = xtable[msgno - 1];
	if (msgac > h_next)		/* don't try to seek past end of file */
		{
		return(ERROR);
		}
	if (msgac == 0)
		{
		return(ERROR);
		}
	if ((rc = seek(fd,msgac-1,0)) == ERROR)
		{
		portsout(CRLF) ;
		portsout("Can't seek on message-file!") ;
		portsout(CRLF) ;
		return(ERROR);		/* when cant find it */
		}
	if (read(fd,buf128,MSGSECT) != MSGSECT) /* read 128 byte sector */
		{
		portsout(CRLF) ;
		portsout("Can't read in message-file!") ;
		portsout(CRLF) ;
		return(ERROR);
		}
/*
*			get first piece of msg record
*/
/* do trial read, since if not first record, fields might overflow */
rc = sscanf(buf128,"%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~",
	buftmp,buftmp,buftmp,buftmp,buftmp,buftmp,buftmp,buftmp,buftmp) ;
	if (rc != 9)		/* makes sure we read the 1st piece */
		{		/*  of a message and not in the middle */
		return(0);	/* 0 when is not the msg header */
		}
/* now do the real read since looks like is a good record */
rc = sscanf(buf128,"%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~",
		this1,				/* this rcd # */
		next1,				/*  points to next rcd # */
		msg_delete,			/* delete byte */
		msg_date,
		msg_time,
		msg_to,
		msg_from,
		msg_pass,
		msg_subject);
	if (rc != 9)		/* makes sure we read the 1st piece */
		{		/*  of a message and not in the middle */
		return(0);	/* 0 when is not the msg header */
		}

	if (msg_delete[0] == '9')	/* check for deleted messages */
		{			/*  if so, return as if not found */
		return(0);
		}

	ret_this = atoi(this1);	/* return this msg no. */
	next = atoi(next1);
	itoa(act,msgno);
	strcpy(msg_no,act);
	if(msg_delete[0] == '5')
		{
		strcat(msg_no,"*");
		strcpy(msg_subject,"< Private Msg >");
		}
	msg_text[0] = '\0';
	while (next)			/* read until no more pieces for */
		{			/*  this message */
		if (read(fd,buf128,MSGSECT) != MSGSECT) /* read next sector */
			{
			portsout(CRLF) ;
			portsout("Can't read in message-file(2)!") ;
			portsout(CRLF) ;
			return(ERROR);
			}
		strfill(bufmsg0,0,MSG1MAX);	/* init bufmsg0 to all hex 00 */
		rc = sscanf(buf128,"%[^~]~%[^~]~%[^~]~%[^~]~",
			this1,			/* this rcd # */
			next1,			/* point to next rcd # */
			msg_delete,		/* delete byte */
			bufmsg0);		/* piece of msg */
		next = atoi(next1);
		strcat(msg_text,bufmsg0);	/* tag piece of msg to */
						/*  whole msg array */
		}
	return(ret_this);	/* if all ok, return the msg no. found */
	}

msgreadx(fd,msgno)		/* read message number requested */
int	fd,			/* returns ERROR if msg past eof */
	msgno;			/* returns 0 if msg is not 1st piece */
				/*   of a message */
				/* returns 0 if msg is deleted */
				/* returns msg # if successful */
	{
	int	rc,			/* return code */
		msgac,
		cnt1,
		cnt2,
		len,
		next,
		ret_this,
		t1,
		t2,
		t3,
		file_size;
	char	who_am_i[99],
		who_am_I[99],
		sysop[99],
		Sysop[99],
		act[11];

	msgac = xtable[msgno - 1];
	if (msgac > h_next)		/* don't try to seek past end of file */
		{
		return(ERROR);
		}
	if (msgac == 0)
		{
		return(ERROR);
		}
	if ((rc = seek(fd,msgac-1,0)) == ERROR)
		{
		portsout(CRLF) ;
		portsout("Can't seek on message-file!") ;
		portsout(CRLF) ;
		return(ERROR);		/* when cant find it */
		}
	if (read(fd,buf128,MSGSECT) != MSGSECT) /* read 128 byte sector */
		{
		portsout(CRLF) ;
		portsout("Can't read in message-file!") ;
		portsout(CRLF) ;
		return(ERROR);
		}
/*
*			get first piece of msg record
*/
/* do trial read, since if not first record, fields might overflow */
rc = sscanf(buf128,"%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~",
	buftmp,buftmp,buftmp,buftmp,buftmp,buftmp,buftmp,buftmp,buftmp) ;
	if (rc != 9)		/* makes sure we read the 1st piece */
		{		/*  of a message and not in the middle */
		return(0);	/* 0 when is not the msg header */
		}
/* now do the real read since looks like is a good record */
rc = sscanf(buf128,"%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~",
		this1,
		next1,				/*  points to next rcd # */
		msg_delete,			/* delete byte */
		msg_date,
		msg_time,
		msg_to,
		msg_from,
		msg_pass,
		msg_subject);
	if (rc != 9)		/* makes sure we read the 1st piece */
		{		/*  of a message and not in the middle */
		return(0);	/* 0 when is not the msg header */
		}

	if (msg_delete[0] == '9')	/* check for deleted messages */
		{			/*  if so, return as if not found */
		return(0);
		}
	if (msg_delete[0] == '5')	/* protected msg */
		{
		strcpy(who_am_i,w_fname);
		strcat(who_am_i," ");
		strcat(who_am_i,w_lname);
		strcpy(Sysop,SYSOP);
		sprintf(sysop,"%-21s",Sysop);
		sprintf(who_am_I,"%-21s",who_am_i);
		t1=strcmp(who_am_I,sysop);
		t2=strcmp(who_am_I,msg_to);
		t3=strcmp(who_am_I,msg_from);
		if (t1 == 0 || t2 == 0 || t3 == 0 || user_priv == 32767)
			{
			goto zzzz;
			}
		return(-10);
		}
zzzz:

	ret_this = atoi(this1);	/* return this msg no. */
	next = atoi(next1);
	itoa(act,msgno);
	strcpy(msg_no,act);
	msg_text[0] = '\0';
	while (next)			/* read until no more pieces for */
		{			/*  this message */
		if (read(fd,buf128,MSGSECT) != MSGSECT) /* read next sector */
			{
			portsout(CRLF) ;
			portsout("Can't read in message-file(2)!") ;
			portsout(CRLF) ;
			return(ERROR);
			}
		strfill(bufmsg0,0,MSG1MAX);	/* init bufmsg0 to all hex 00 */
		rc = sscanf(buf128,"%[^~]~%[^~]~%[^~]~%[^~]~",
			this1,			/* this rcd # */
			next1,			/* point to next rcd # */
			msg_delete,		/* delete byte */
			bufmsg0);		/* piece of msg */
		next = atoi(next1);
		strcat(msg_text,bufmsg0);	/* tag piece of msg to */
						/*  whole msg array */
		}
	return(ret_this);	/* if all ok, return the msg no. found */
	}
msgreadk(fd,msgno)		/* read message number requested */
int	fd,			/* returns ERROR if msg past eof */
	msgno;			/* returns 0 if msg is not 1st piece */
				/*   of a message */
				/* returns 0 if msg is deleted */
				/* returns msg # if successful */
	{
	int	rc,			/* return code */
		msgac,
		cnt1,
		cnt2,
		len,
		next,
		ret_this,
		t1,
		t2,
		t3,
		file_size;
	char	who_am_i[99],
		who_am_I[99],
		sysop[99],
		Sysop[99],
		act[11];

	msgac = xtable[msgno - 1];
	if (msgac > h_next)		/* don't try to seek past end of file */
		{
		return(ERROR);
		}
	if (msgac == 0)
		{
		return(ERROR);
		}
	if ((rc = seek(fd,msgac-1,0)) == ERROR)
		{
		portsout(CRLF) ;
		portsout("Can't seek on message-file!") ;
		portsout(CRLF) ;
		return(ERROR);		/* when cant find it */
		}
	if (read(fd,buf128,MSGSECT) != MSGSECT) /* read 128 byte sector */
		{
		portsout(CRLF) ;
		portsout("Can't read in message-file!") ;
		portsout(CRLF) ;
		return(ERROR);
		}
/*
*			get first piece of msg record
*/
/* do trial read, since if not first record, fields might overflow */
rc = sscanf(buf128,"%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~",
	buftmp,buftmp,buftmp,buftmp,buftmp,buftmp,buftmp,buftmp,buftmp) ;
	if (rc != 9)		/* makes sure we read the 1st piece */
		{		/*  of a message and not in the middle */
		return(0);	/* 0 when is not the msg header */
		}
/* now do the real read since looks like is a good record */
rc = sscanf(buf128,"%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~%[^~]~",
		this1,
		next1,				/*  points to next rcd # */
		msg_delete,			/* delete byte */
		msg_date,
		msg_time,
		msg_to,
		msg_from,
		msg_pass,
		msg_subject);
	if (rc != 9)		/* makes sure we read the 1st piece */
		{		/*  of a message and not in the middle */
		return(0);	/* 0 when is not the msg header */
		}

	if (msg_delete[0] == '9')	/* check for deleted messages */
		{			/*  if so, return as if not found */
		return(0);
		}
	strcpy(who_am_i,w_fname);
	strcat(who_am_i," ");
	strcat(who_am_i,w_lname);
	strcpy(Sysop,SYSOP);
	sprintf(sysop,"%-21s",Sysop);
	sprintf(who_am_I,"%-21s",who_am_i);
	t1=strcmp(who_am_I,sysop);
	t2=strcmp(who_am_I,msg_to);
	t3=strcmp(who_am_I,msg_from);
	if (t1 == 0 || t2 == 0 || t3 == 0 || user_priv == 32767)
		{
		goto yyyy;
		}
	return(-10);
yyyy:

	ret_this = atoi(this1);	/* return this msg no. */
	next = atoi(next1);
	itoa(act,msgno);
	strcpy(msg_no,act);
	msg_text[0] = '\0';
	while (next)			/* read until no more pieces for */
		{			/*  this message */
		if (read(fd,buf128,MSGSECT) != MSGSECT) /* read next sector */
			{
			portsout(CRLF) ;
			portsout("Can't read in message-file(2)!") ;
			portsout(CRLF) ;
			return(ERROR);
			}
		strfill(bufmsg0,0,MSG1MAX);	/* init bufmsg0 to all hex 00 */
		rc = sscanf(buf128,"%[^~]~%[^~]~%[^~]~%[^~]~",
			this1,			/* this rcd # */
			next1,			/* point to next rcd # */
			msg_delete,		/* delete byte */
			bufmsg0);		/* piece of msg */
		next = atoi(next1);
		strcat(msg_text,bufmsg0);	/* tag piece of msg to */
						/*  whole msg array */
		}
	return(ret_this);	/* if all ok, return the msg no. found */
	}
/*	end of program  	*/
