#include "namespace.h"
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include "un-namespace.h"
#include <stdio.h>
#include "sysvipc_ipc.h"
#include "sysvipc_sockets.h"
#include "sysvipc_sem.h"
#include "sysvipc_shm.h"
#include "sysvipc_hash.h"
#include "sysvipc_lock.h"
#include "sysvipc_lock_generic.h"
#define SYSV_MUTEX_LOCK(x) if (__isthreaded) _pthread_mutex_lock(x)
#define SYSV_MUTEX_UNLOCK(x) if (__isthreaded) _pthread_mutex_unlock(x)
#define SYSV_MUTEX_DESTROY(x) if (__isthreaded) _pthread_mutex_destroy(x)
int daemon_fd = -1;
extern pthread_mutex_t lock_resources;
extern pthread_mutex_t lock_undo;
extern struct hashtable *shmaddrs;
int
send_message(int fd, int type, char *data, int size)
{
_write(fd, &type, sizeof(type));
return (send_msg_with_cred(fd, data, size));
}
int
receive_type_message(int fd)
{
int type;
int r = _read(fd, &type, sizeof(type));
return (r == 0 ? 0 : type);
}
int
receive_message(int fd, char *data, int size)
{
_read(fd, data, size);
return (0);
}
int
is_sysvinit(void)
{
return (daemon_fd == -1 ? 0:1);
}
static int
register_to_daemon(void)
{
int flags;
char test = 't';
daemon_fd = connect_to_daemon(LISTEN_SOCKET_FILE);
flags = _fcntl(daemon_fd, F_GETFD, 0);
if (_fcntl(daemon_fd, F_SETFD, flags & FD_CLOEXEC) == -1) {
sysv_print_err("fcntl error\n");
return (-1);
}
send_msg_with_cred(daemon_fd, &test, sizeof(test));
sysv_print("register to daemon: sock fd = %d\n", daemon_fd);
return (0);
}
static void
acquire_locks(void)
{
struct entries_list *list;
struct hashentry *tmp;
struct shm_data *data;
struct semid_pool *semaptr;
int i;
SYSV_MUTEX_LOCK(&lock_undo);
SYSV_MUTEX_LOCK(&lock_resources);
for (i=0; i<get_hash_size(MAXSIZE); i++) {
list = &shmaddrs->entries[i];
if (LIST_EMPTY(list))
continue;
LIST_FOREACH(tmp, list, entry_link) {
data = (struct shm_data*)tmp->value;
if (data->type == SEMGET) {
semaptr = (struct semid_pool *)data->internal;
#ifdef SYSV_RWLOCK
#ifdef SYSV_SEMS
#endif
sysv_rwlock_wrlock(&semaptr->rwlock);
#else
sysv_mutex_lock(&semaptr->mutex);
#endif
}
}
}
}
static void
parent_release_locks(void)
{
struct entries_list *list;
struct hashentry *tmp;
struct shm_data *data;
struct semid_pool *semaptr;
int i;
SYSV_MUTEX_UNLOCK(&lock_undo);
SYSV_MUTEX_UNLOCK(&lock_resources);
for (i=0; i<get_hash_size(MAXSIZE); i++) {
list = &shmaddrs->entries[i];
if (LIST_EMPTY(list))
continue;
LIST_FOREACH(tmp, list, entry_link) {
data = (struct shm_data*)tmp->value;
if (data->type == SEMGET) {
semaptr = (struct semid_pool *)data->internal;
#ifdef SYSV_RWLOCK
sysv_rwlock_unlock(&semaptr->rwlock);
#else
sysv_mutex_unlock(&semaptr->mutex);
#endif
}
}
}
}
static void
child_release_locks(void)
{
SYSV_MUTEX_UNLOCK(&lock_undo);
SYSV_MUTEX_UNLOCK(&lock_resources);
}
static void
prepare_parent_atfork(void)
{
if (!is_sysvinit())
return;
acquire_locks();
}
static void
parent_atfork(void)
{
if (!is_sysvinit())
return;
parent_release_locks();
}
static void
child_atfork(void)
{
if (!is_sysvinit())
return;
child_release_locks();
_close(daemon_fd);
if (register_to_daemon() < 0) {
sysv_print_err("register to daemon error\n");
exit(-1);
}
shmchild();
}
int
sysvinit(void)
{
if (is_sysvinit()) {
return (IPC_INITIALIZED);
}
if (register_to_daemon() < 0)
return (-1);
if (_pthread_atfork(prepare_parent_atfork, parent_atfork,
child_atfork) < 0) {
sysv_print_err("pthread_atfork error\n");
return (-1);
}
return 0;
}
int
sysvexit(void)
{
if (!is_sysvinit())
return (-1);
return (0);
}