/*********************************************************************\
* Copyright (c) 1991 by Wen-King Su (wen-king@vlsi.cs.caltech.edu) *
* Copyright (c) 1993 by Phil Richards (pgr@prg.ox.ac.uk) *
* Copyright (c) 2004 by Radim Kolar *
* *
* You may copy or modify this file in any manner you wish, provided *
* that this notice is always included, and that you hold the author *
* harmless for any loss or damage resulting from the installation or *
* use of this software. *
\*********************************************************************/
#include "client.h"
#include "lock.h"
#include <stdlib.h>
#ifndef FSP_NOLOCKING
static char key_string[sizeof(FSP_KEY_PREFIX)+32];
static char code_str[] =
"0123456789:_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
#include <setjmp.h>
static jmp_buf my_interrupt_env;
static RETSIGTYPE (*old_intr_handler)(int);
static RETSIGTYPE
interrupted_lock(int sig)
{
/* this prints the interrupt message *AND* resets the interrupt handler */
(*old_intr_handler)(sig);
if (client_intr_state > 1)
longjmp(my_interrupt_env, 0);
}
static void
make_key_string(u_long server_addr, u_int server_port)
{
u_long v1, v2;
char *p;
strcpy(key_string, FSP_KEY_PREFIX);
for (p = key_string; *p; p++)
;
v1 = server_addr;
v2 = server_port;
*p++ = code_str[v1 & 0x3f]; v1 >>= 6;
*p++ = code_str[v1 & 0x3f]; v1 >>= 6;
*p++ = code_str[v1 & 0x3f]; v1 >>= 6;
v1 = v1 | (v2 << (32-3*6));
*p++ = code_str[v1 & 0x3f]; v1 >>= 6;
*p++ = code_str[v1 & 0x3f]; v1 >>= 6;
*p++ = code_str[v1 & 0x3f]; v1 >>= 6;
*p++ = code_str[v1 & 0x3f]; v1 >>= 6;
*p++ = code_str[v1 & 0x3f]; v1 >>= 6;
*p = 0;
}
#endif
/********************************************************************/
/******* For those systems that has flock function call *************/
/********************************************************************/
#ifdef FSP_USE_FLOCK
/* this will cause an unfortunate redefinition of F_OK etc, but... */
#include <sys/file.h>
int key_persists = 1;
static int lock_fd;
static u_int okey;
u_int
client_get_key(void)
{
if (!setjmp(my_interrupt_env))
{
old_intr_handler = signal(SIGINT, interrupted_lock);
if (flock(lock_fd, LOCK_EX) < 0)
{
perror("flock");
exit(1);
}
(void)signal(SIGINT, old_intr_handler);
if (read(lock_fd, &okey, sizeof(okey)) < 0)
{
perror("read");
exit(1);
}
if (lseek(lock_fd, 0L, 0) < 0)
{
perror("seek");
exit(1);
}
return(okey);
}
ffprintf(STDERR, "?couldn't get key from lock\n");
return -1;
}
void
client_put_key(u_int key)
{
if (write(lock_fd, (char*)&key, sizeof(key)) < 0)
{
perror("write");
exit(1);
}
if (lseek(lock_fd, 0L, 0) < 0)
{
perror("seek");
exit(1);
}
if (flock(lock_fd, LOCK_UN) < 0)
{
perror("unflock");
exit(1);
}
}
void
client_init_key(u_long server_addr, u_int server_port, u_int key)
{
mode_t omask;
okey = key;
make_key_string(server_addr, server_port);
omask = umask(0);
lock_fd = open(key_string, O_RDWR | O_CREAT, 0666);
(void)umask(omask);
}
void
client_finish_key(void)
{
(void)close(lock_fd);
}
#endif
/********************************************************************/
/******* For those systems that has lockf function call *************/
/********************************************************************/
#ifdef FSP_USE_LOCKF
int key_persists = 1;
static u_int lock_fd;
static u_int okey;
u_int
client_get_key(void)
{
if (!setjmp(my_interrupt_env))
{
old_intr_handler = signal(SIGINT, interrupted_lock);
if (lockf(lock_fd, F_LOCK, sizeof(okey)) < 0)
{
perror("lockf");
exit(1);
}
(void)signal(SIGINT, old_intr_handler);
if (read(lock_fd, &okey, sizeof(okey)) < 0)
{
perror("readlk");
exit(1);
}
if (lseek(lock_fd, 0L, 0) < 0)
{
perror("seek");
exit(1);
}
return(okey);
}
ffprintf(STDERR, "?couldn't get key from lock\n");
return -1;
}
void
client_put_key(u_int key)
{
if (write(lock_fd, &key, sizeof(key)) < 0)
{
perror("write");
exit(1);
}
if (lseek(lock_fd, 0L, 0) < 0)
{
perror("seek");
exit(1);
}
if (lockf(lock_fd, F_ULOCK, sizeof(key)) < 0)
{
perror("unlockf");
exit(1);
}
}
void
client_init_key(u_long server_addr, u_int server_port, u_int key)
{
mode_t omask;
okey = key;
make_key_string(server_addr, server_port);
omask = umask(0);
lock_fd = open(key_string, O_RDWR | O_CREAT, 0666);
(void)umask(omask);
}
void
client_finish_key(void)
{
(void)close(lock_fd);
}
#endif
/********************************************************************/
/******* For those systems that has SysV shared memory + lockf ******/
/********************************************************************/
#ifdef FSP_USE_SHAREMEM_AND_LOCKF
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int key_persists = 1;
static u_int *share_key;
static u_int lock_fd;
static int lock_shm;
u_int
client_get_key(void)
{
if (!setjmp(my_interrupt_env))
{
old_intr_handler = signal(SIGINT, interrupted_lock);
if (lockf(lock_fd, F_LOCK, 2) < 0)
{
perror("lockf");
exit(1);
}
(void)signal(SIGINT, old_intr_handler);
return(*share_key);
}
ffprintf(STDERR, "?couldn't get key from lock\n");
return -1;
}
void
client_put_key(u_int key)
{
*share_key = key;
if (lockf(lock_fd, F_ULOCK, 2) < 0)
{
perror("unlockf");
exit(1);
}
}
void
client_init_key(u_long server_addr, u_int server_port, u_int key)
{
mode_t omask;
key_t lock_key;
make_key_string(server_addr, server_port);
omask = umask(0);
lock_fd = open(key_string, O_RDWR | O_CREAT, 0666);
umask(omask);
if ((lock_key = ftok(key_string, 238)) < 0)
{
perror("ftok");
exit(1);
}
if ((lock_shm = shmget(lock_key, 2*sizeof(u_int), IPC_CREAT | 0666)) < 0)
{
perror("shmget");
exit(1);
}
if (!(share_key = (u_int *)shmat(lock_shm, 0, 0)))
{
perror("shmat");
exit(1);
}
}
/* I haven't got a clue what I'm doing here -- this is all guesswork! */
void
client_finish_key(void)
{
if (shmdt((char *)share_key) < 0)
{
perror("shmdt");
exit(1);
}
shmctl(lock_shm,IPC_RMID,NULL);
(void)close(lock_fd);
}
#endif
/********************************************************************/
/******* For those who do not want to use locking *******************/
/********************************************************************/
#ifdef FSP_NOLOCKING
int key_persists = 0;
static u_int okey;
u_int
client_get_key(void)
{
return (int)okey;
}
void
client_put_key(u_int key)
{
okey = key;
}
void
client_init_key(u_long server_addr, u_int server_port, u_int key)
{
okey = key;
}
void
client_finish_key(void)
{
;
}
#endif
/********************************************************************/
/******* For those systems that has SysV shared memory + semop ******/
/********************************************************************/
#ifdef FSP_USE_SHAREMEM_AND_SEMOP
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#ifdef _SEM_SEMUN_UNDEFINED
union semun
{
int val;
struct semid_ds *buf;
unsigned short int *array;
struct seminfo *__buf;
};
#endif
int key_persists = 1;
static u_int *share_key;
static int lock_shm;
static int lock_sem;
u_int client_get_key (void)
{
struct sembuf sem;
sem.sem_num = 0;
sem.sem_op = -1;
sem.sem_flg = SEM_UNDO;
if (!setjmp(my_interrupt_env))
{
old_intr_handler = signal(SIGINT, interrupted_lock);
if(semop(lock_sem,&sem,1) == -1 )
{
perror("semop");
exit(1);
}
(void)signal(SIGINT, old_intr_handler);
return(*share_key);
}
ffprintf(STDERR, "?couldn't get key from lock\n");
return -1;
}
void client_put_key (u_int key)
{
struct sembuf sem;
sem.sem_num = 0;
sem.sem_op = 1;
sem.sem_flg = SEM_UNDO;
*share_key = key;
if(semop(lock_sem,&sem,1) == -1) {
perror("semop");
exit(1);
}
}
void client_init_key (u_long server_addr,
u_int server_port,
u_int key)
{
mode_t omask;
key_t lock_key;
int fd;
union semun sun;
struct sembuf sem;
make_key_string(server_addr,server_port);
omask = umask(0);
fd = open(key_string,O_RDWR|O_CREAT,0666);
umask(omask);
close(fd);
if((lock_key = ftok(key_string,238)) == -1) {
perror("ftok");
exit(1);
}
if((lock_shm = shmget(lock_key,2*sizeof(u_int),IPC_CREAT|0666)) == -1) {
perror("shmget");
exit(1);
}
if(!(share_key = (unsigned int *) shmat(lock_shm,(char*)0,0))) {
perror("shmat");
exit(1);
}
if((lock_sem = semget(lock_key,0,0)) == -1) {
/* create a new semaphore and init it */
if((lock_sem = semget(lock_key,2,IPC_CREAT|0666)) == -1) {
perror("semget");
}
/* we need to init this semaphore */
sun.val=1;
if(semctl(lock_sem,0,SETVAL,sun) == -1)
{
perror("semctl setval");
exit(1);
}
*share_key = key;
}
/* increase in use counter */
sem.sem_num = 1;
sem.sem_op = 1;
sem.sem_flg = SEM_UNDO;
if(semop(lock_sem,&sem,1) == -1) {
perror("semop");
exit(1);
}
}
void client_finish_key(void)
{
int rc;
struct sembuf sem;
if (shmdt((char *)share_key) < 0)
{
perror("shmdt");
exit(1);
}
/* check if we are only one process holding lock */
rc = semctl(lock_sem,1,GETVAL);
if (rc == -1)
{
perror("semctl");
exit(1);
}
if (rc == 1)
{
/* safe to destroy */
if (
(semctl(lock_sem,0,IPC_RMID) < 0) ||
(shmctl(lock_shm,IPC_RMID,NULL) < 0) ||
(unlink(key_string) < 0) )
rc++;/* ignore cleanup errors */
} else
if(rc > 1)
{
/* we need to decrease sem. */
sem.sem_num = 1;
sem.sem_op = -1;
sem.sem_flg = SEM_UNDO;
if(semop(lock_sem,&sem,1) == -1) {
perror("semop");
}
}
}
#endif
/********************************************************************/
/********************************************************************/
/********************************************************************/
syntax highlighted by Code2HTML, v. 0.9.1