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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
/* $Id$ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include "config.h"
#include "pttstruct.h"
#include "modes.h"
#include "common.h"
#include "proto.h"
#ifndef SEM_R
#define SEM_R 0400
#endif
#ifndef SEM_A
#define SEM_A 0200
#endif
#ifndef __FreeBSD__
union semun {
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */
u_short *array; /* array for GETALL & SETALL */
struct seminfo *__buf; /* buffer for IPC_INFO */
};
#endif
static userec_t *passwd_image = NULL;
static int passwd_image_size;
static int semid = -1;
int passwd_mmap(void) {
int fd;
if(passwd_image!=NULL) return 0;
fd = open(FN_PASSWD, O_RDWR);
if(fd > 0) {
struct stat st;
fstat(fd, &st);
passwd_image_size = st.st_size;
passwd_image = mmap(NULL, passwd_image_size,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(passwd_image == (userec_t *)-1) {
perror("mmap");
return -1;
}
close(fd);
semid = semget(PASSWDSEM_KEY, 1, SEM_R | SEM_A | IPC_CREAT | IPC_EXCL);
if(semid == -1) {
if(errno == EEXIST) {
semid = semget(PASSWDSEM_KEY, 1, SEM_R | SEM_A);
if(semid == -1) {
perror("semget");
exit(1);
}
} else {
perror("semget");
exit(1);
}
} else {
union semun s;
s.val = 1;
if(semctl(semid, 0, SETVAL, s) == -1) {
perror("semctl");
exit(1);
}
}
} else {
perror(FN_PASSWD);
return -1;
}
return 0;
}
int passwd_update_money(int num) {
int money;
if(num < 1 || num > MAX_USERS)
return -1;
money = moneyof(num);
memcpy(&passwd_image[num - 1].money, &money, sizeof(int));
return 0;
}
int passwd_update(int num, userec_t *buf) {
if(num < 1 || num > MAX_USERS)
return -1;
buf->money = moneyof(num);
memcpy(&passwd_image[num - 1], buf, sizeof(userec_t));
return 0;
}
int passwd_query(int num, userec_t *buf) {
if(num < 1 || num > MAX_USERS)
return -1;
memcpy(buf, &passwd_image[num - 1], sizeof(userec_t));
return 0;
}
int passwd_apply(int (*fptr)(userec_t *)) {
int i;
for(i = 0; i < MAX_USERS; i++)
if((*fptr)(&passwd_image[i]) == QUIT)
return QUIT;
return 0;
}
int passwd_apply2(int (*fptr)(int, userec_t *)) {
int i;
for(i = 0; i < MAX_USERS; i++)
if((*fptr)(i, &passwd_image[i]) == QUIT)
return QUIT;
return 0;
}
void passwd_lock() {
struct sembuf buf = { 0, -1, SEM_UNDO };
if(semop(semid, &buf, 1)) {
perror("semop");
exit(1);
}
}
void passwd_unlock() {
struct sembuf buf = { 0, 1, SEM_UNDO };
if(semop(semid, &buf, 1)) {
perror("semop");
exit(1);
}
}
|