]>
Commit | Line | Data |
---|---|---|
d4a28ab0 CW |
1 | /***************************************************************************** |
2 | Excerpt from "Linux Programmer's Guide - Chapter 6" | |
3 | (C)opyright 1994-1995, Scott Burkett | |
4 | ***************************************************************************** | |
5 | MODULE: semtool.c | |
6 | ***************************************************************************** | |
7 | A command line tool for tinkering with SysV style Semaphore Sets | |
8 | ||
9 | *****************************************************************************/ | |
bd695173 | 10 | /* |
7156ebbc CW |
11 | * This program is free software: you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License as published by | |
13 | * the Free Software Foundation, either version 3 of the License, or | |
14 | * (at your option) any later version. | |
bd695173 CW |
15 | * |
16 | * This program is distributed in the hope that it will be useful, | |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | * GNU General Public License for more details. | |
20 | * | |
21 | * You should have received a copy of the GNU General Public License | |
7156ebbc | 22 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
bd695173 | 23 | * |
7156ebbc | 24 | * See the COPYING file for full license information. |
bd695173 CW |
25 | */ |
26 | ||
27 | #if HAVE_CONFIG_H | |
fe3a7d70 | 28 | # include "config.h" |
bd695173 | 29 | #endif |
d4a28ab0 | 30 | |
d2b03e6a | 31 | #include "common.h" |
bd695173 CW |
32 | |
33 | #if HAVE_SYS_IPC_H | |
fe3a7d70 | 34 | # include <sys/ipc.h> |
bd695173 CW |
35 | #endif |
36 | #if HAVE_SYS_SEM_H | |
fe3a7d70 | 37 | # include <sys/sem.h> |
bd695173 | 38 | #endif |
d4a28ab0 | 39 | |
b5edac4c CW |
40 | /* cygserver doesn't define this constant where we |
41 | can get it, so just use the default configuration | |
42 | value */ | |
43 | #ifndef SEMMSL | |
44 | # define SEMMSL 60 | |
45 | #endif | |
46 | ||
d4a28ab0 | 47 | /* arg for semctl system calls. */ |
fe3a7d70 CW |
48 | union semun |
49 | { | |
50 | int val; /* value for SETVAL */ | |
51 | struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ | |
52 | ushort *array; /* array for GETALL & SETALL */ | |
53 | struct seminfo *__buf; /* buffer for IPC_INFO */ | |
d4a28ab0 CW |
54 | void *__pad; |
55 | }; | |
56 | ||
57 | #define SEM_RESOURCE_MAX 1 /* Initial value of all semaphores */ | |
58 | ||
fe3a7d70 CW |
59 | void opensem (int *sid, key_t key); |
60 | void createsem (int *sid, key_t key, int members); | |
61 | void locksem (int sid, int member); | |
62 | void unlocksem (int sid, int member); | |
63 | void removesem (int sid); | |
64 | unsigned short get_member_count (int sid); | |
65 | int getval (int sid, int member); | |
66 | void dispval (int sid, int member); | |
67 | void changemode (int sid, char *mode); | |
68 | void usage (void); | |
69 | ||
70 | int | |
71 | main (int argc, char *argv[]) | |
d4a28ab0 | 72 | { |
fe3a7d70 CW |
73 | key_t key; |
74 | int semset_id; | |
75 | ||
76 | if (argc == 1) | |
77 | usage (); | |
78 | ||
79 | /* Create unique key via call to ftok() */ | |
80 | key = ftok (".", 's'); | |
81 | ||
82 | switch (tolower (argv[1][0])) | |
83 | { | |
84 | case 'c': | |
85 | if (argc != 3) | |
86 | usage (); | |
87 | createsem (&semset_id, key, atoi (argv[2])); | |
88 | break; | |
89 | case 'l': | |
90 | if (argc != 3) | |
91 | usage (); | |
92 | opensem (&semset_id, key); | |
93 | locksem (semset_id, atoi (argv[2])); | |
94 | break; | |
95 | case 'u': | |
96 | if (argc != 3) | |
97 | usage (); | |
98 | opensem (&semset_id, key); | |
99 | unlocksem (semset_id, atoi (argv[2])); | |
100 | break; | |
101 | case 'd': | |
102 | opensem (&semset_id, key); | |
103 | removesem (semset_id); | |
104 | break; | |
105 | case 'm': | |
106 | opensem (&semset_id, key); | |
107 | changemode (semset_id, argv[2]); | |
108 | break; | |
109 | default: | |
110 | usage (); | |
111 | ||
112 | } | |
113 | ||
114 | return (0); | |
d4a28ab0 CW |
115 | } |
116 | ||
fe3a7d70 CW |
117 | void |
118 | opensem (int *sid, key_t key) | |
d4a28ab0 | 119 | { |
fe3a7d70 | 120 | /* Open the semaphore set - do not create! */ |
d4a28ab0 | 121 | |
fe3a7d70 CW |
122 | if ((*sid = semget (key, 0, 0666)) == -1) |
123 | { | |
124 | printf ("Semaphore set does not exist!\n"); | |
125 | exit (1); | |
126 | } | |
d4a28ab0 CW |
127 | |
128 | } | |
129 | ||
fe3a7d70 CW |
130 | void |
131 | createsem (int *sid, key_t key, int members) | |
d4a28ab0 | 132 | { |
fe3a7d70 CW |
133 | int cntr; |
134 | union semun semopts; | |
135 | ||
136 | if (members > SEMMSL) | |
137 | { | |
138 | printf ("Sorry, max number of semaphores in a set is %d\n", SEMMSL); | |
139 | exit (1); | |
140 | } | |
141 | ||
142 | printf ("Attempting to create new semaphore set with %d members\n", | |
143 | members); | |
144 | ||
145 | if ((*sid = semget (key, members, IPC_CREAT | IPC_EXCL | 0666)) == -1) | |
146 | { | |
147 | fprintf (stderr, "Semaphore set already exists!\n"); | |
148 | exit (1); | |
149 | } | |
150 | ||
151 | semopts.val = SEM_RESOURCE_MAX; | |
152 | ||
153 | /* Initialize all members (could be done with SETALL) */ | |
154 | for (cntr = 0; cntr < members; cntr++) | |
155 | semctl (*sid, cntr, SETVAL, semopts); | |
d4a28ab0 CW |
156 | } |
157 | ||
fe3a7d70 CW |
158 | void |
159 | locksem (int sid, int member) | |
d4a28ab0 | 160 | { |
fe3a7d70 CW |
161 | struct sembuf sem_lock = { 0, -1, IPC_NOWAIT }; |
162 | ||
163 | if (member < 0 || member > (get_member_count (sid) - 1)) | |
164 | { | |
165 | fprintf (stderr, "semaphore member %d out of range\n", member); | |
166 | return; | |
167 | } | |
168 | ||
169 | /* Attempt to lock the semaphore set */ | |
170 | if (!getval (sid, member)) | |
171 | { | |
172 | fprintf (stderr, "Semaphore resources exhausted (no lock)!\n"); | |
173 | exit (1); | |
174 | } | |
175 | ||
176 | sem_lock.sem_num = member; | |
177 | ||
178 | if ((semop (sid, &sem_lock, 1)) == -1) | |
179 | { | |
180 | fprintf (stderr, "Lock failed\n"); | |
181 | exit (1); | |
182 | } | |
183 | else | |
184 | printf ("Semaphore resources decremented by one (locked)\n"); | |
185 | ||
186 | dispval (sid, member); | |
d4a28ab0 CW |
187 | } |
188 | ||
fe3a7d70 CW |
189 | void |
190 | unlocksem (int sid, int member) | |
d4a28ab0 | 191 | { |
fe3a7d70 CW |
192 | struct sembuf sem_unlock = { member, 1, IPC_NOWAIT }; |
193 | int semval; | |
194 | ||
195 | if (member < 0 || member > (get_member_count (sid) - 1)) | |
196 | { | |
197 | fprintf (stderr, "semaphore member %d out of range\n", member); | |
198 | return; | |
199 | } | |
200 | ||
201 | /* Is the semaphore set locked? */ | |
202 | semval = getval (sid, member); | |
203 | if (semval == SEM_RESOURCE_MAX) | |
204 | { | |
205 | fprintf (stderr, "Semaphore not locked!\n"); | |
206 | exit (1); | |
207 | } | |
208 | ||
209 | sem_unlock.sem_num = member; | |
210 | ||
211 | /* Attempt to lock the semaphore set */ | |
212 | if ((semop (sid, &sem_unlock, 1)) == -1) | |
213 | { | |
214 | fprintf (stderr, "Unlock failed\n"); | |
215 | exit (1); | |
216 | } | |
217 | else | |
218 | printf ("Semaphore resources incremented by one (unlocked)\n"); | |
219 | ||
220 | dispval (sid, member); | |
d4a28ab0 CW |
221 | } |
222 | ||
fe3a7d70 CW |
223 | void |
224 | removesem (int sid) | |
d4a28ab0 | 225 | { |
fe3a7d70 CW |
226 | union semun semopts; |
227 | semopts.val = 0; | |
d4a28ab0 | 228 | |
fe3a7d70 CW |
229 | semctl (sid, 0, IPC_RMID, semopts); |
230 | printf ("Semaphore removed\n"); | |
d4a28ab0 CW |
231 | } |
232 | ||
fe3a7d70 CW |
233 | unsigned short |
234 | get_member_count (int sid) | |
d4a28ab0 | 235 | { |
fe3a7d70 CW |
236 | union semun semopts; |
237 | struct semid_ds mysemds; | |
d4a28ab0 | 238 | |
fe3a7d70 | 239 | semopts.buf = &mysemds; |
d4a28ab0 | 240 | |
fe3a7d70 CW |
241 | /* Return number of members in the semaphore set */ |
242 | return (semopts.buf->sem_nsems); | |
d4a28ab0 CW |
243 | } |
244 | ||
fe3a7d70 CW |
245 | int |
246 | getval (int sid, int member) | |
d4a28ab0 | 247 | { |
fe3a7d70 CW |
248 | int semval; |
249 | union semun semopts; | |
250 | semopts.val = 0; | |
d4a28ab0 | 251 | |
fe3a7d70 CW |
252 | semval = semctl (sid, member, GETVAL, semopts); |
253 | return (semval); | |
d4a28ab0 CW |
254 | } |
255 | ||
fe3a7d70 CW |
256 | void |
257 | changemode (int sid, char *mode) | |
d4a28ab0 | 258 | { |
fe3a7d70 CW |
259 | int rc; |
260 | union semun semopts; | |
261 | struct semid_ds mysemds; | |
262 | ||
263 | /* Get current values for internal data structure */ | |
264 | semopts.buf = &mysemds; | |
265 | ||
266 | rc = semctl (sid, 0, IPC_STAT, semopts); | |
d4a28ab0 | 267 | |
fe3a7d70 CW |
268 | if (rc == -1) |
269 | { | |
270 | perror ("semctl"); | |
271 | exit (1); | |
272 | } | |
d4a28ab0 | 273 | |
fe3a7d70 | 274 | printf ("Old permissions were %o\n", semopts.buf->sem_perm.mode); |
d4a28ab0 | 275 | |
fe3a7d70 CW |
276 | /* Change the permissions on the semaphore */ |
277 | sscanf (mode, "%ho", &semopts.buf->sem_perm.mode); | |
d4a28ab0 | 278 | |
fe3a7d70 CW |
279 | /* Update the internal data structure */ |
280 | semctl (sid, 0, IPC_SET, semopts); | |
d4a28ab0 | 281 | |
fe3a7d70 | 282 | printf ("Updated...\n"); |
d4a28ab0 CW |
283 | |
284 | } | |
285 | ||
fe3a7d70 CW |
286 | void |
287 | dispval (int sid, int member) | |
d4a28ab0 | 288 | { |
fe3a7d70 CW |
289 | int semval; |
290 | union semun semopts; | |
291 | semopts.val = 0; | |
d4a28ab0 | 292 | |
fe3a7d70 CW |
293 | semval = semctl (sid, member, GETVAL, semopts); |
294 | printf ("semval for member %d is %d\n", member, semval); | |
d4a28ab0 CW |
295 | } |
296 | ||
fe3a7d70 CW |
297 | void |
298 | usage (void) | |
d4a28ab0 | 299 | { |
fe3a7d70 CW |
300 | fprintf (stderr, "semtool - A utility for tinkering with semaphores\n"); |
301 | fprintf (stderr, "\nUSAGE: semtool (c)reate <semcount>\n"); | |
302 | fprintf (stderr, " (l)ock <sem #>\n"); | |
303 | fprintf (stderr, " (u)nlock <sem #>\n"); | |
304 | fprintf (stderr, " (d)elete\n"); | |
305 | fprintf (stderr, " (m)ode <mode>\n"); | |
306 | exit (1); | |
d4a28ab0 | 307 | } |