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