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