Import sendmail 8.14.1
[dragonfly.git] / contrib / sendmail-8.14 / libsm / t-sem.c
1 /*
2  * Copyright (c) 2000-2001, 2005-2007 Sendmail, Inc. and its suppliers.
3  *      All rights reserved.
4  *
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  */
9
10 #include <sm/gen.h>
11 SM_RCSID("@(#)$Id: t-sem.c,v 1.16 2007/03/21 23:22:10 ca Exp $")
12
13 #include <stdio.h>
14
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>
24
25 # define T_SM_SEM_KEY (4321L)
26
27 static void
28 delay(t, s)
29         int t;
30         char *s;
31 {
32         if (t > 0)
33         {
34 #if DEBUG
35                 fprintf(stderr, "sleep(%d) before %s\n", t, s);
36 #endif /* DEBUG */
37                 sleep(t);
38         }
39 #if DEBUG
40         fprintf(stderr, "%s\n", s);
41 #endif /* DEBUG */
42 }
43
44
45 /*
46 **  SEMINTER -- interactive testing of semaphores.
47 **
48 **      Parameters:
49 **              owner -- create semaphores.
50 **
51 **      Returns:
52 **              0 on success
53 **              < 0 on failure.
54 */
55
56 static int
57 seminter(owner)
58         bool owner;
59 {
60         int semid;
61         int t;
62
63         semid = sm_sem_start(T_SM_SEM_KEY, SM_NSEM, 0, owner);
64         if (semid < 0)
65         {
66                 perror("sm_sem_start failed");
67                 return 1;
68         }
69
70         while ((t = getchar()) != EOF)
71         {
72                 switch (t)
73                 {
74                   case 'a':
75                         delay(0, "try to acq");
76                         if (sm_sem_acq(semid, 0, 2) < 0)
77                         {
78                                 perror("sm_sem_acq failed");
79                                 return 1;
80                         }
81                         delay(0, "acquired");
82                         break;
83
84                   case 'r':
85                         delay(0, "try to rel");
86                         if (sm_sem_rel(semid, 0, 2) < 0)
87                         {
88                                 perror("sm_sem_rel failed");
89                                 return 1;
90                         }
91                         delay(0, "released");
92                         break;
93
94                   case 'v':
95                         if ((t = sm_sem_get(semid, 0)) < 0)
96                         {
97                                 perror("get_sem failed");
98                                 return 1;
99                         }
100                         printf("semval: %d\n", t);
101                         break;
102
103                 }
104         }
105         if (owner)
106                 return sm_sem_stop(semid);
107         return 0;
108 }
109
110 /*
111 **  SEM_CLEANUP -- cleanup if something breaks
112 **
113 **      Parameters:
114 **              sig -- signal.
115 **
116 **      Returns:
117 **              none.
118 */
119
120 static int semid_c = -1;
121 void
122 sem_cleanup(sig)
123         int sig;
124 {
125         if (semid_c >= 0)
126                 (void) sm_sem_stop(semid_c);
127         exit(EX_UNAVAILABLE);
128 }
129
130 /*
131 **  SEMTEST -- test of semaphores
132 **
133 **      Parameters:
134 **              owner -- create semaphores.
135 **
136 **      Returns:
137 **              0 on success
138 **              < 0 on failure.
139 */
140
141 # define MAX_CNT        10
142
143 static int
144 semtest(owner)
145         int owner;
146 {
147         int semid, r;
148         int cnt = 0;
149
150         semid = sm_sem_start(T_SM_SEM_KEY, 1, 0, owner);
151         if (semid < 0)
152         {
153                 perror("sm_sem_start failed");
154                 return -1;
155         }
156
157         if (owner)
158         {
159                 /* just in case someone kills the program... */
160                 semid_c = semid;
161                 (void) sm_signal(SIGHUP, sem_cleanup);
162                 (void) sm_signal(SIGINT, sem_cleanup);
163                 (void) sm_signal(SIGTERM, sem_cleanup);
164
165                 delay(1, "parent: acquire 1");
166                 cnt = 0;
167                 do
168                 {
169                         r = sm_sem_acq(semid, 0, 0);
170                         if (r < 0)
171                         {
172                                 sleep(1);
173                                 ++cnt;
174                         }
175                 } while (r < 0 && cnt <= MAX_CNT);
176                 SM_TEST(r >= 0);
177                 if (r < 0)
178                         return r;
179
180                 delay(3, "parent: release 1");
181                 cnt = 0;
182                 do
183                 {
184                         r = sm_sem_rel(semid, 0, 0);
185                         if (r < 0)
186                         {
187                                 sleep(1);
188                                 ++cnt;
189                         }
190                 } while (r < 0 && cnt <= MAX_CNT);
191                 SM_TEST(r >= 0);
192                 if (r < 0)
193                         return r;
194
195                 delay(1, "parent: getval");
196                 cnt = 0;
197                 do
198                 {
199                         r = sm_sem_get(semid, 0);
200                         if (r <= 0)
201                         {
202                                 sleep(1);
203                                 ++cnt;
204                         }
205                 } while (r <= 0 && cnt <= MAX_CNT);
206                 SM_TEST(r > 0);
207                 if (r <= 0)
208                         return r;
209
210                 delay(1, "parent: acquire 2");
211                 cnt = 0;
212                 do
213                 {
214                         r = sm_sem_acq(semid, 0, 0);
215                         if (r < 0)
216                         {
217                                 sleep(1);
218                                 ++cnt;
219                         }
220                 } while (r < 0 && cnt <= MAX_CNT);
221                 SM_TEST(r >= 0);
222                 if (r < 0)
223                         return r;
224
225                 cnt = 0;
226                 do
227                 {
228                         r = sm_sem_rel(semid, 0, 0);
229                         if (r < 0)
230                         {
231                                 sleep(1);
232                                 ++cnt;
233                         }
234                 } while (r < 0 && cnt <= MAX_CNT);
235                 SM_TEST(r >= 0);
236                 if (r < 0)
237                         return r;
238         }
239         else
240         {
241                 delay(1, "child: acquire 1");
242                 cnt = 0;
243                 do
244                 {
245                         r = sm_sem_acq(semid, 0, 0);
246                         if (r < 0)
247                         {
248                                 sleep(1);
249                                 ++cnt;
250                         }
251                 } while (r < 0 && cnt <= MAX_CNT);
252                 SM_TEST(r >= 0);
253                 if (r < 0)
254                         return r;
255
256                 delay(1, "child: release 1");
257                 cnt = 0;
258                 do
259                 {
260                         r = sm_sem_rel(semid, 0, 0);
261                         if (r < 0)
262                         {
263                                 sleep(1);
264                                 ++cnt;
265                         }
266                 } while (r < 0 && cnt <= MAX_CNT);
267                 SM_TEST(r >= 0);
268                 if (r < 0)
269                         return r;
270
271         }
272         if (owner)
273                 return sm_sem_stop(semid);
274         return 0;
275 }
276
277 int
278 main(argc, argv)
279         int argc;
280         char *argv[];
281 {
282         bool interactive = false;
283         bool owner = false;
284         int ch;
285         int r = 0;
286
287 # define OPTIONS        "io"
288         while ((ch = getopt(argc, argv, OPTIONS)) != -1)
289         {
290                 switch ((char) ch)
291                 {
292                   case 'i':
293                         interactive = true;
294                         break;
295
296                   case 'o':
297                         owner = true;
298                         break;
299
300                   default:
301                         break;
302                 }
303         }
304
305         if (interactive)
306                 r = seminter(owner);
307         else
308         {
309                 pid_t pid;
310
311                 printf("This test takes about 8 seconds.\n");
312                 printf("If it takes longer than 30 seconds, please interrupt it\n");
313                 printf("and compile again without semaphore support, i.e.,");
314                 printf("-DSM_CONF_SEM=0\n");
315                 if ((pid = fork()) < 0)
316                 {
317                         perror("fork failed\n");
318                         return -1;
319                 }
320
321                 sm_test_begin(argc, argv, "test semaphores");
322                 if (pid == 0)
323                 {
324                         /* give the parent the chance to setup data */
325                         sleep(1);
326                         r = semtest(false);
327                 }
328                 else
329                 {
330                         r = semtest(true);
331                 }
332                 SM_TEST(r == 0);
333                 return sm_test_end();
334         }
335         return r;
336 }
337 #else /* SM_CONF_SEM */
338 int
339 main(argc, argv)
340         int argc;
341         char *argv[];
342 {
343         printf("No support for semaphores configured on this machine\n");
344         return 0;
345 }
346 #endif /* SM_CONF_SEM */