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 */
|