8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / sendmail / libsm / t-sem.c
blob662b4f6d43cda2c3ab28b1d87f4a20e1fc7b71df
1 /*
2 * Copyright (c) 2000-2001, 2005-2008 Sendmail, Inc. and its suppliers.
3 * All rights reserved.
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
8 */
10 #include <sm/gen.h>
11 SM_RCSID("@(#)$Id: t-sem.c,v 1.17 2008/05/30 16:26:38 ca Exp $")
13 #include <stdio.h>
15 #if SM_CONF_SEM
16 # include <stdlib.h>
17 # include <unistd.h>
18 # include <sysexits.h>
19 # include <sm/heap.h>
20 # include <sm/string.h>
21 # include <sm/signal.h>
22 # include <sm/test.h>
23 # include <sm/sem.h>
25 # define T_SM_SEM_KEY (4321L)
27 static void
28 delay(t, s)
29 int t;
30 char *s;
32 if (t > 0)
34 #if DEBUG
35 fprintf(stderr, "sleep(%d) before %s\n", t, s);
36 #endif /* DEBUG */
37 sleep(t);
39 #if DEBUG
40 fprintf(stderr, "%s\n", s);
41 #endif /* DEBUG */
46 ** SEMINTER -- interactive testing of semaphores.
48 ** Parameters:
49 ** owner -- create semaphores.
51 ** Returns:
52 ** 0 on success
53 ** < 0 on failure.
56 static int
57 seminter(owner)
58 bool owner;
60 int semid;
61 int t;
63 semid = sm_sem_start(T_SM_SEM_KEY, SM_NSEM, 0, owner);
64 if (semid < 0)
66 perror("sm_sem_start failed");
67 return 1;
70 while ((t = getchar()) != EOF)
72 switch (t)
74 case 'a':
75 delay(0, "try to acq");
76 if (sm_sem_acq(semid, 0, 2) < 0)
78 perror("sm_sem_acq failed");
79 return 1;
81 delay(0, "acquired");
82 break;
84 case 'r':
85 delay(0, "try to rel");
86 if (sm_sem_rel(semid, 0, 2) < 0)
88 perror("sm_sem_rel failed");
89 return 1;
91 delay(0, "released");
92 break;
94 case 'v':
95 if ((t = sm_sem_get(semid, 0)) < 0)
97 perror("get_sem failed");
98 return 1;
100 printf("semval: %d\n", t);
101 break;
105 if (owner)
106 return sm_sem_stop(semid);
107 return 0;
111 ** SEM_CLEANUP -- cleanup if something breaks
113 ** Parameters:
114 ** sig -- signal.
116 ** Returns:
117 ** none.
120 static int semid_c = -1;
121 void
122 sem_cleanup(sig)
123 int sig;
125 if (semid_c >= 0)
126 (void) sm_sem_stop(semid_c);
127 exit(EX_UNAVAILABLE);
130 static int
131 drop_priv(uid, gid)
132 uid_t uid;
133 gid_t gid;
135 int r;
137 r = setgid(gid);
138 if (r != 0)
139 return r;
140 r = setuid(uid);
141 return r;
145 ** SEMTEST -- test of semaphores
147 ** Parameters:
148 ** owner -- create semaphores.
150 ** Returns:
151 ** 0 on success
152 ** < 0 on failure.
155 # define MAX_CNT 10
157 static int
158 semtest(owner, uid, gid)
159 int owner;
160 uid_t uid;
161 gid_t gid;
163 int semid, r;
164 int cnt = 0;
166 if (!owner && uid != 0)
168 r = drop_priv(uid, gid);
169 if (r < 0)
171 perror("drop_priv child failed");
172 return -1;
175 semid = sm_sem_start(T_SM_SEM_KEY, 1, 0, owner);
176 if (semid < 0)
178 perror("sm_sem_start failed");
179 return -1;
182 if (owner)
184 if (uid != 0)
186 r = sm_semsetowner(semid, uid, gid, 0660);
187 if (r < 0)
189 perror("sm_semsetowner failed");
190 return -1;
192 r = drop_priv(uid, gid);
193 if (r < 0)
195 perror("drop_priv owner failed");
196 return -1;
200 /* just in case someone kills the program... */
201 semid_c = semid;
202 (void) sm_signal(SIGHUP, sem_cleanup);
203 (void) sm_signal(SIGINT, sem_cleanup);
204 (void) sm_signal(SIGTERM, sem_cleanup);
206 delay(1, "parent: acquire 1");
207 cnt = 0;
210 r = sm_sem_acq(semid, 0, 0);
211 if (r < 0)
213 sleep(1);
214 ++cnt;
216 } while (r < 0 && cnt <= MAX_CNT);
217 SM_TEST(r >= 0);
218 if (r < 0)
219 return r;
221 delay(3, "parent: release 1");
222 cnt = 0;
225 r = sm_sem_rel(semid, 0, 0);
226 if (r < 0)
228 sleep(1);
229 ++cnt;
231 } while (r < 0 && cnt <= MAX_CNT);
232 SM_TEST(r >= 0);
233 if (r < 0)
234 return r;
236 delay(1, "parent: getval");
237 cnt = 0;
240 r = sm_sem_get(semid, 0);
241 if (r <= 0)
243 sleep(1);
244 ++cnt;
246 } while (r <= 0 && cnt <= MAX_CNT);
247 SM_TEST(r > 0);
248 if (r <= 0)
249 return r;
251 delay(1, "parent: acquire 2");
252 cnt = 0;
255 r = sm_sem_acq(semid, 0, 0);
256 if (r < 0)
258 sleep(1);
259 ++cnt;
261 } while (r < 0 && cnt <= MAX_CNT);
262 SM_TEST(r >= 0);
263 if (r < 0)
264 return r;
266 cnt = 0;
269 r = sm_sem_rel(semid, 0, 0);
270 if (r < 0)
272 sleep(1);
273 ++cnt;
275 } while (r < 0 && cnt <= MAX_CNT);
276 SM_TEST(r >= 0);
277 if (r < 0)
278 return r;
280 else
282 delay(1, "child: acquire 1");
283 cnt = 0;
286 r = sm_sem_acq(semid, 0, 0);
287 if (r < 0)
289 sleep(1);
290 ++cnt;
292 } while (r < 0 && cnt <= MAX_CNT);
293 SM_TEST(r >= 0);
294 if (r < 0)
295 return r;
297 delay(1, "child: release 1");
298 cnt = 0;
301 r = sm_sem_rel(semid, 0, 0);
302 if (r < 0)
304 sleep(1);
305 ++cnt;
307 } while (r < 0 && cnt <= MAX_CNT);
308 SM_TEST(r >= 0);
309 if (r < 0)
310 return r;
313 if (owner)
314 return sm_sem_stop(semid);
315 return 0;
319 main(argc, argv)
320 int argc;
321 char *argv[];
323 bool interactive = false;
324 bool owner = false;
325 int ch, r;
326 uid_t uid;
327 gid_t gid;
329 uid = 0;
330 gid = 0;
331 r = 0;
333 # define OPTIONS "iog:u:"
334 while ((ch = getopt(argc, argv, OPTIONS)) != -1)
336 switch ((char) ch)
338 case 'g':
339 gid = (gid_t)strtoul(optarg, 0, 0);
340 break;
342 case 'i':
343 interactive = true;
344 break;
346 case 'u':
347 uid = (uid_t)strtoul(optarg, 0, 0);
348 break;
350 case 'o':
351 owner = true;
352 break;
354 default:
355 break;
359 if (interactive)
360 r = seminter(owner);
361 else
363 pid_t pid;
365 printf("This test takes about 8 seconds.\n");
366 printf("If it takes longer than 30 seconds, please interrupt it\n");
367 printf("and compile again without semaphore support, i.e.,");
368 printf("-DSM_CONF_SEM=0\n");
369 if ((pid = fork()) < 0)
371 perror("fork failed\n");
372 return -1;
375 sm_test_begin(argc, argv, "test semaphores");
376 if (pid == 0)
378 /* give the parent the chance to setup data */
379 sleep(1);
380 r = semtest(false, uid, gid);
382 else
384 r = semtest(true, uid, gid);
386 SM_TEST(r == 0);
387 return sm_test_end();
389 return r;
391 #else /* SM_CONF_SEM */
393 main(argc, argv)
394 int argc;
395 char *argv[];
397 printf("No support for semaphores configured on this machine\n");
398 return 0;
400 #endif /* SM_CONF_SEM */