Category : C Source Code
Archive   : SEM10.ZIP
Filename : RWSEM.C

 
Output of file : RWSEM.C contained in archive : SEM10.ZIP
/* Citadel */
/* 241 East Eleventh Street * Brookville, IN 47012 * 317-647-4720 */
/* BBS 317-647-2403 */

/* #ident "rwsem.c 1.1 - 89/10/16" */

/* Supported operating systems: UNIX, MS-DOS */
#define UNIX (0)
#define MSDOS (1)
#define HOST MSDOS

/* Supported MS-DOS C compilers: Borland Turbo C */
#define TURBOC (0)
#define MSDOSC TURBOC

#include
#include
#ifndef PATH_MAX
#define PATH_MAX (256)
#endif
#include
#include
#if HOST == UNIX
#define PATHDLM ('/') /* path name delimiter */
#include
#include
#include
#include "syscalkr.h"
#include
#elif HOST == MSDOS
#define PATHDLM ('\\') /* path name delimiter */
#if MSDOSC == TURBOC
#include /* calloc, free declarations */
#include /* mkdir, rmdir declarations */
#include /* open declarations */
#include /* access, close, open declarations */
#include
#include /* file mode macros */
#define S_IPERM (S_IREAD | S_IWRITE | S_IEXEC)
#define R_OK (04) /* mode argument for access */
#define W_OK (02)
#define X_OK (01)
#define F_OK (00)
#endif
#endif
#include "rwsem.h"

/* function declarations */
int getcnt(/*char *file, int *cntp*/);
int putcnt(/*char *file, int cnt*/);
static int rws_valid(/*semset_t *ssp*/);

/* read/write semaphore set table definition */
static rwsset_t rwst[RWSOPEN_MAX];

/*man---------------------------------------------------------------------------
NAME
rwsclose - close read/write semaphore set

SYNOPSIS
#include "rwsem.h"

int rwsclose(rwsp)
rwsset_t *rwsp;

DESCRIPTION
The rwsclose function closes the read/write semaphore set pointed
to by rwsp. All locks held by the calling process should be
released before calling rwsclose.

rwsclose will fail if one or more of the following is true:

[EINVAL] rwsp does not point to a valid open read/write
semaphore set.

SEE ALSO
rwscount, rwslock, rwsopen, rwsremove.

DIAGNOSTICS
Upon successful completion, a value of 0 is returned. Otherwise,
a value of -1 is returned, and errno set to indicate the error.

------------------------------------------------------------------------------*/
int rwsclose(rwsp)
rwsset_t *rwsp;
{
/* validate arguments */
if (!rws_valid(rwsp) || (rwsp->rwsc == 0)) {
errno = EINVAL;
return -1;
}

/* close semaphore set */
if (semclose(rwsp->ssp) == -1) {
return -1;
}

/* free memory allocated for rwsp */
free(rwsp->lockheld);
rwsp->lockheld = NULL;

/* scrub slot in table then free it */
memset(rwsp, 0, sizeof(*rwsp));
rwsp->rwsc = 0;

errno = 0;
return 0;
}

/*man---------------------------------------------------------------------------
NAME
rwscount - read/write semaphore count

SYNOPSIS
#include "rwsem.h"

int rwscount(rwsp)
rwsset_t *rwsp;

DESCRIPTION
rwscount returns the number of read/write semaphores in set rwsp.
If rwsp does not point to a valid open semaphore set, the results
are undefined. rwscount is a macro.

SEE ALSO
rwsclose, rwslock, rwsopen, rwsremove.

------------------------------------------------------------------------------*/
/* rwscount is defined in rwsem.h */

/*man---------------------------------------------------------------------------
NAME
rwslock - read/write semaphore lock

SYNOPSIS
#include "rwslock.h"

int rwslock(rwsp, rwsno, ltype)
rwsset_t *rwsp;
int rwsno;
int ltype;

DESCRIPTION
The rwslock function will lock r/w semaphore number rwsno in
read/write semaphore set rwsp. ltype indicates the target status
of the lock. The lock types available are:

RWS_UNLCK unlock
RWS_RDLCK read lock
RWS_WRLCK write lock

rwslock will fail if one or more of the following is true:

[EAGAIN] The type of lock (ltype) is a read lock
(RWS_RDLCK) and the r/w semaphore is already
write locked.
[EAGAIN] The type of lock (ltype) is a write lock
(RWS_WRLCK) and the r/w semaphore is already
read locked.
[EINVAL] rwsp does not point to a valid open
read/write semaphore set.
[EINVAL] rwsno is less than zero or greater than
the highest r/w semaphore number in set rwsp.
[EINVAL] ltype is not a valid lock type.

SEE ALSO
rwscount, rwscount, rwsopen, rwsremove.

DIAGNOSTICS
Upon successful completion, a value of 0 is returned. Otherwise, a value
of -1 is returned, and errno set to indicate the error.

------------------------------------------------------------------------------*/
int rwslock(rwsp, rwsno, ltype)
rwsset_t *rwsp;
int rwsno;
int ltype;
{
int wsem = 0; /* write semaphore */
int rsem = 0; /* read semaphore */
int rc = 0; /* readcount */
char rcpath[PATH_MAX + 1]; /* readcount file path name */
int terrno = 0; /* temporary errno */

/* validate arguments */
if (!rws_valid(rwsp) || (rwsp->rwsc == 0)) {
errno = EINVAL;
return -1;
}
if ((rwsno < 0) || (rwsno >= rwsp->rwsc)) {
errno = EINVAL;
return -1;
}

/* identify write and read semaphores and read-count file */
wsem = rwsno * 2;
rsem = wsem + 1;
if (sprintf(rcpath, "%s%cr%d", rwsp->rwsdir, (int)PATHDLM, rwsno) == EOF) {
return NULL;
}

switch (ltype) {
case RWS_UNLCK: /* unlock */
switch (rwsp->lockheld[rwsno]) {
case RWS_UNLCK: /* unlock */
break; /* case RWS_UNLCK: */
case RWS_RDLCK: /* read lock */
if (semlower(rwsp->ssp, rsem) == -1) { /* allocate readcount */
return -1;
}
if (getcnt(rcpath, &rc) == -1) { /* get readcount */
terrno = errno;
semraise(rwsp->ssp, rsem);
errno = terrno;
return -1;
}
rc--; /* decrement readcount */
if (rc == 0) { /* if no other readers, */
if (semraise(rwsp->ssp, wsem) == -1) { /* free resource */
terrno = errno;
semraise(rwsp->ssp, rsem);
errno = terrno;
return -1;
}
}
if (putcnt(rcpath, rc) == -1) { /* store new readcount */
terrno = errno;
semraise(rwsp->ssp, rsem);
errno = terrno;
return -1;
}
if (semraise(rwsp->ssp, rsem) == -1) { /* free readcount */
return -1;
}
break; /* case RWS_RDLCK: */
case RWS_WRLCK: /* write lock */
if (semraise(rwsp->ssp, wsem) == -1) {
return -1;
}
break; /* case RWS_WRLCK: */
default:
errno = RWSPANIC;
return -1;
break; /* default: */
};
break; /* case RWS_UNLCK: */
case RWS_RDLCK: /* read lock */
if (rwsp->lockheld[rwsno] == RWS_RDLCK) {
errno = 0;
return 0;
}
if (semlower(rwsp->ssp, rsem) == -1) { /* allocate readcount */
return -1;
}
if (getcnt(rcpath, &rc) == -1) { /* get readcount */
terrno = errno;
semraise(rwsp->ssp, rsem);
errno = terrno;
return -1;
}
rc++; /* increment readcount */
if (rc == 1) { /* if no other readers, */
if (semlower(rwsp->ssp, wsem) == -1) { /* allocate resource */
terrno = errno;
semraise(rwsp->ssp, rsem);
errno = terrno;
return -1;
}
}
if (putcnt(rcpath, rc) == -1) { /* store new readcount */
terrno = errno;
semraise(rwsp->ssp, rsem);
if (rc == 1) semraise(rwsp->ssp, wsem);
errno = terrno;
return -1;
}
if (semraise(rwsp->ssp, rsem) == -1) { /* free readcount */
terrno = errno;
if (rc == 1) semraise(rwsp->ssp, wsem);
errno = terrno;
return -1;
}
break; /* case RWS_RDLCK: */
case RWS_WRLCK: /* write lock */
if (semlower(rwsp->ssp, wsem) == -1) { /* allocate resource */
return -1;
}
break; /* case RWS_WRLCK: */
default:
errno = EINVAL;
return -1;
break; /* default: */
};

/* save type of lock held */
rwsp->lockheld[rwsno] = ltype;

errno = 0;
return 0;
}

/*man---------------------------------------------------------------------------
NAME
rwsopen - open read/write semaphore set

SYNOPSIS
rwsset_t *rwsopen(rwsdir, flags, rwsc)
char *rwsdir;
int flags;
int rwsc;

DESCRIPTION
The rwsopen function opens a read/write semaphore set. rwsdir
points to the path name of the directory containing the files
for the set.

flags values are constructed by bitwise OR-ing command and
permission flags. The command flags are:

RWS_CREAT If the read/write semaphore set exists,
this flag has no effect. Otherwise, the
semaphore set is created and the access
permissions assigned according to the
permission bits of flags. All semaphores
are initialized to the unlocked state.
RWS_EXCL If RWS_EXCL and RWS_CREAT are set, rwsopen
will fail if the read/write semaphore set
already exists.

The macros defined in (e.g., S_IRUSR) should be used
for the permission flags.

rwsc is the number of r/w semaphores in the set. rwsc is ignored
if the set already exists.

rwsopen will fail if one or more of the following is true:

[EACCES] The read/write semaphore set exists and the
calling process does not have access
permission.
[EACCES] RWS_CREAT is set, the read/write semaphore
set does not exist, and the calling process
does not have permission to create.
[EAGAIN] The read/write semaphore set exists but has
not been completely created.
[EEXIST] RWS_CREAT and RWS_EXCL are set and the
named read/write semaphore set already
exists.
[EINVAL] rwsdir is the NULL pointer.
[EINVAL] The read/write semaphore set does not exist
and rwsc is less than one.
[ENOENT] RWS_CREAT is not set and the named read/write
semaphore set does not exist.
[RWSEMFILE] RWSOPEN_MAX read/write semaphore sets are
currently open.

SEE ALSO
rwscount, rwscount, rwslock, rwsremove.

DIAGNOSTICS
rwsopen returns a NULL pointer on failure, and errno is set to
indicate the error.

------------------------------------------------------------------------------*/
rwsset_t *rwsopen(rwsdir, flags, rwsc)
char *rwsdir;
int flags;
int rwsc;
{
int terrno = 0;
char path[PATH_MAX + 1];
rwsset_t *rwsp;
/*const */int mode = flags & S_IPERM;
int rwsno = 0;

/* validate arguments */
if (rwsdir == NULL) {
errno = EINVAL;
return NULL;
}

/* find free slot in sst table */
for (rwsp = rwst; rwsp < (rwst + RWSOPEN_MAX); rwsp++) {
if (rwsp->rwsc == 0) {
break; /* found */
}
}
if (rwsp >= (rwst + RWSOPEN_MAX)) {
errno = RWSEMFILE; /* no free slots */
return NULL;
}

/* load rwst structure */
rwsp->rwsc = rwsc;
strncpy(rwsp->rwsdir, rwsdir, sizeof(rwsp->rwsdir));
rwsp->rwsdir[sizeof(rwsp->rwsdir) - 1] = '\0';

/* if the create flag is not set, check access to rwsdir */
if (!(flags & RWS_CREAT)) {
#if HOST == UNIX
if (access(rwsp->rwsdir, W_OK) == -1) {
terrno = errno;
memset(rwsp, 0, sizeof(*rwsp));
rwsp->rwsc = 0;
errno = terrno;
return NULL;
}
#elif HOST == MSDOS
if (access(rwsp->rwsdir, W_OK) == -1) {
terrno = errno;
memset(rwsp, 0, sizeof(*rwsp));
rwsp->rwsc = 0;
errno = terrno;
return NULL;
}
#endif
/* r/w semaphore set exists -> get r/w semaphore count */
if (sprintf(path, "%s%crwsc", rwsdir, (int)PATHDLM) == EOF) {
return NULL;
}
if (getcnt(path, &(rwsp->rwsc)) == -1) {
if (errno == ENOENT) errno = EAGAIN;
return NULL;
}
if (rwsp->rwsc == 0) {
errno = EAGAIN;
return NULL;
}
/* open semaphore set */
if (sprintf(path, "%s%csemdir", rwsdir, (int)PATHDLM) == EOF) {
return NULL;
}
rwsp->ssp = semopen(path, 0, 0);
if (rwsp->ssp == NULL) {
return NULL;
}
rwsp->lockheld = (short *)calloc(rwsc, sizeof(*rwsp->lockheld));
if (rwsp->lockheld == NULL) {
errno = ENOMEM;
return NULL;
}
errno = 0;
return rwsp;
}

/* create rwsem directory */
#if HOST == UNIX
if (mkdir(rwsp->rwsdir, mode) == -1) {
#elif HOST == MSDOS
if (mkdir(rwsp->rwsdir) == -1) {
if (errno == EACCES) errno = EEXIST;
#endif
if (errno != EEXIST) {
terrno = errno;
memset(rwsp, 0, sizeof(*rwsp));
rwsp->rwsc = 0;
errno = terrno;
return NULL;
}
if (flags & RWS_EXCL) {
terrno = errno;
memset(rwsp, 0, sizeof(*rwsp));
rwsp->rwsc = 0;
errno = terrno;
return NULL;
} else {
/* set exists -> get r/w semaphore count */
if (sprintf(path, "%s%crwsc", rwsdir, PATHDLM) == EOF) {
return NULL;
}
if (getcnt(path, &(rwsp->rwsc)) == -1) {
if (errno == ENOENT) errno = EAGAIN;
return NULL;
}
if (rwsp->rwsc == 0) {
errno = EAGAIN;
return NULL;
}
/* open semaphore set */
if (sprintf(path, "%s%csemdir", rwsdir, (int)PATHDLM) == EOF) {
return NULL;
}
rwsp->ssp = semopen(path, 0, 0);
if (rwsp->ssp == NULL) {
return NULL;
}
rwsp->lockheld = (short *)calloc(rwsc, sizeof(*rwsp->lockheld));
if (rwsp->lockheld == NULL) {
return NULL;
}
errno = 0;
return rwsp;
}
}

/* validate rwsc argument */
if (rwsc < 1) {
memset(rwsp, 0, sizeof(*rwsp));
rwsp->rwsc = 0;
errno = EINVAL;
return NULL;
}

/* store r/w semaphore count */
if (sprintf(path, "%s%crwsc", rwsdir, PATHDLM) == EOF) {
terrno = errno;
memset(rwsp, 0, sizeof(*rwsp));
rwsp->rwsc = 0;
errno = terrno;
return NULL;
}
if (putcnt(path, rwsp->rwsc) == -1) {
terrno = errno;
memset(rwsp, 0, sizeof(*rwsp));
rwsp->rwsc = 0;
errno = terrno;
return NULL;
}
#if HOST == UNIX
if (chmod(path, mode & ~(S_IXUSR | S_IXGRP | S_IXOTH)) == -1) {
#elif HOST == MSDOS
if (chmod(path, mode & ~S_IEXEC) == -1) {
#endif
terrno = errno;
memset(rwsp, 0, sizeof(*rwsp));
rwsp->rwsc = 0;
errno = terrno;
return NULL;
}

/* create all readcount files */
for (rwsno = 0; rwsno < rwsp->rwsc; rwsno++) {
if (sprintf(path, "%s%cr%d", rwsdir, (int)PATHDLM, rwsno) == EOF) {
return NULL;
}
if (putcnt(path, 0) == -1) {
return NULL;
}
#if HOST == UNIX
if (chmod(path, mode & ~(S_IXUSR | S_IXGRP | S_IXOTH)) == -1) {
#elif HOST == MSDOS
if (chmod(path, mode & ~S_IEXEC) == -1) {
#endif
terrno = errno;
memset(rwsp, 0, sizeof(*rwsp));
rwsp->rwsc = 0;
errno = terrno;
return NULL;
}
}

/* create semaphore set */
if (sprintf(path, "%s%csemdir", rwsp->rwsdir, (int)PATHDLM) == EOF) {
free(rwsp->lockheld);
return NULL;
}
rwsp->ssp = semopen(path, SEM_CREAT | mode, rwsc * 2);
if (rwsp->ssp == NULL) {
free(rwsp->lockheld);
return NULL;
}

/* allocate storage */
rwsp->lockheld = (short *)calloc(rwsc, sizeof(*rwsp->lockheld));
if (rwsp->lockheld == NULL) {
return NULL;
}

errno = 0;
return rwsp;
}

/*man---------------------------------------------------------------------------
NAME
rwsremove - remove semaphore set

SYNOPSIS
#include "semaphor.h"

int rwsremove(rwsdir)
char *rwsdir;

DESCRIPTION
The rwsremove function removes a read/write semaphore set.
rwsdir points to the path name of the directory containing the
files for the set.

rwsremove will fail if one or more of the following is true:

[EACCES] The calling process does not have permission
to remove the read/write semaphore set.
[EINVAL] rwsdir is the NULL pointer.
[ENOENT] The named read/write semaphore set does not
exist.

SEE ALSO
rwscount, rwscount, rwslock, rwsopen.

DIAGNOSTICS
Upon successful completion, a value of 0 is returned. Otherwise,
a value of -1 is returned, and errno set to indicate the error.

------------------------------------------------------------------------------*/
int rwsremove(rwsdir)
char *rwsdir;
{
char path[PATH_MAX + 1];
int rwsc = 0;
int rwsno = 0;

/* validate arguments */
if (rwsdir == NULL) {
errno = EINVAL;
return -1;
}

/* read r/w semaphore count */
if (sprintf(path, "%s%crwsc", rwsdir, (int)PATHDLM) == EOF) {
return -1;
}
if (getcnt(path, &rwsc) == -1) {
if (errno == ENOENT) errno = EAGAIN;
return -1;
}
if (rwsc == 0) {
errno = EAGAIN;
return -1;
}

/* remove semaphore set */
if (sprintf(path, "%s%csemdir", rwsdir, (int)PATHDLM) == EOF) {
return -1;
}
if (semremove(path) == -1) {
return -1;
}

/* remove r/w semaphore count */
if (sprintf(path, "%s%crwsc", rwsdir, (int)PATHDLM) == EOF) {
return -1;
}
#if HOST == UNIX
if (unlink(path) == -1) {
return -1;
}
#elif HOST == MSDOS
if (unlink(path) == -1) {
return -1;
}
#endif

/* remove all readcount files */
for (rwsno = 0; rwsno < rwsc; rwsno++) {
if (sprintf(path, "%s%cr%d", rwsdir, (int)PATHDLM, rwsno) == EOF) {
return -1;
}
if (unlink(path) == -1) {
return -1;
}
}

/* remove rwsem directory */
#if HOST == UNIX
if (rmdir(rwsdir) == -1) {
return -1;
}
#elif HOST == MSDOS
if (rmdir(rwsdir) == -1) {
return -1;
}
#endif

errno = 0;
return 0;
}

/*------------------------------------------------------------------------------
NAME
rws_valid - validate read/write semaphore set

SYNOPSIS
#include "rwsem.h"

int rws_valid(rwsp)
rwsset_t *rwsp;

DESCRIPTION
The rws_valid function determines if rwsp points to a valid
read/write semaphore set control structure. If it is valid, 1 is
returned. If not, then 0 is returned.

------------------------------------------------------------------------------*/
static int rws_valid(rwsp)
rwsset_t *rwsp;
{
if ((rwsp < rwst) || (rwsp >= (rwst + RWSOPEN_MAX))) {
return 0;
}
if (((size_t)((char *)rwsp - (char *)rwst)) % sizeof(*rwst) != 0) {
return 0;
}

return 1;
}


  3 Responses to “Category : C Source Code
Archive   : SEM10.ZIP
Filename : RWSEM.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/