/*
 * Citadel/UX "system dependent" stuff
 *
 * By using #ifdef's, we try to make this code run on as many Unix variants
 * as possible.  Wherever possible, if a system-dependent function cannot be
 * used, we use a less efficient/reliable (but portable) construct.
 */

#include <stdio.h>
#include <fcntl.h>

/* 
 * If we're running on a system which supports file & record locking using the
 * fcntl() system call, then we don't need the flock() stuff.  It doesn't
 * matter whether HAVE_FLOCK is defined or not.  If the F_SETLKW flag exists,
 * then we ignore flock().
 */

#ifndef F_SETLKW
#ifdef HAVE_FLOCK
#include <sys/file.h>
#endif
#endif

#include "citadel.h"

int mms_fd;
int have_lock = 0;

#ifdef F_SETLKW
	struct flock lockbuf;
#endif

void lock_msgmain() {
	int a;
	struct msgmain msgmain;


	mms_fd=open("MMstructure",O_RDWR);

#ifdef F_SETLKW
	lockbuf.l_type = F_WRLCK;
	lockbuf.l_whence = 0;
	lockbuf.l_start = 0L;
	lockbuf.l_len = 0L;
	lockbuf.l_pid = 0L;
	fcntl(mms_fd,F_SETLKW,&lockbuf);
#else
#ifdef HAVE_FLOCK
	do {
		a=flock(mms_fd,LOCK_EX);
		if (a!=0) sleep(1);
		} while(a!=0);
#else
	do {
		lseek(mms_fd,0L,0);
		read(mms_fd,&msgmain,sizeof(struct msgmain));
		if (msgmain.MMflags & MM_BUSY) sleep(1);
		} while(msgmain.MMflags & MM_BUSY);

	lseek(mms_fd,0L,0);
	msgmain.MMflags=(msgmain.MMflags|MM_BUSY);
	write(mms_fd,&msgmain,sizeof(struct msgmain));
#endif
#endif
	have_lock = 1;
	}


void unlock_msgmain() {
	struct msgmain msgmain;

	if (have_lock == 0) {
		return;
		}

#ifdef F_SETLKW
	lockbuf.l_type = F_UNLCK;
	fcntl(mms_fd,F_SETLKW,&lockbuf);
#else
#ifdef HAVE_FLOCK
	if (flock(mms_fd,LOCK_UN)!=0) fprintf(stderr,"sysdep: unlock err\n");
#else
	lseek(mms_fd,0L,0);
	read(mms_fd,&msgmain,sizeof(struct msgmain));
	msgmain.MMflags=msgmain.MMflags & ~MM_BUSY;
	lseek(mms_fd,0L,0);
	write(mms_fd,&msgmain,sizeof(struct msgmain));
#endif
#endif
	close(mms_fd);
	have_lock = 0;
	}

