113d88268SGregory Neil Shapiro /*
25dd76dd0SGregory Neil Shapiro * Copyright (c) 2000-2001, 2005-2008 Proofpoint, Inc. and its suppliers.
313d88268SGregory Neil Shapiro * All rights reserved.
413d88268SGregory Neil Shapiro *
513d88268SGregory Neil Shapiro * By using this file, you agree to the terms and conditions set
613d88268SGregory Neil Shapiro * forth in the LICENSE file which can be found at the top level of
713d88268SGregory Neil Shapiro * the sendmail distribution.
813d88268SGregory Neil Shapiro */
913d88268SGregory Neil Shapiro
1013d88268SGregory Neil Shapiro #include <sm/gen.h>
114313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: t-sem.c,v 1.18 2013-11-22 20:51:43 ca Exp $")
1213d88268SGregory Neil Shapiro
1313d88268SGregory Neil Shapiro #include <stdio.h>
1413d88268SGregory Neil Shapiro
1513d88268SGregory Neil Shapiro #if SM_CONF_SEM
1613d88268SGregory Neil Shapiro # include <stdlib.h>
1713d88268SGregory Neil Shapiro # include <unistd.h>
1813d88268SGregory Neil Shapiro # include <sysexits.h>
1913d88268SGregory Neil Shapiro # include <sm/heap.h>
2013d88268SGregory Neil Shapiro # include <sm/string.h>
2113d88268SGregory Neil Shapiro # include <sm/signal.h>
2213d88268SGregory Neil Shapiro # include <sm/test.h>
23*2fb4f839SGregory Neil Shapiro # include <sm/conf.h>
2413d88268SGregory Neil Shapiro # include <sm/sem.h>
2513d88268SGregory Neil Shapiro
26d0cef73dSGregory Neil Shapiro # define T_SM_SEM_KEY (4321L)
27d0cef73dSGregory Neil Shapiro
2813d88268SGregory Neil Shapiro static void
2913d88268SGregory Neil Shapiro delay(t, s)
3013d88268SGregory Neil Shapiro int t;
3113d88268SGregory Neil Shapiro char *s;
3213d88268SGregory Neil Shapiro {
3313d88268SGregory Neil Shapiro if (t > 0)
3413d88268SGregory Neil Shapiro {
3513d88268SGregory Neil Shapiro # if DEBUG
3613d88268SGregory Neil Shapiro fprintf(stderr, "sleep(%d) before %s\n", t, s);
375b0945b5SGregory Neil Shapiro # endif
3813d88268SGregory Neil Shapiro sleep(t);
3913d88268SGregory Neil Shapiro }
4013d88268SGregory Neil Shapiro # if DEBUG
4113d88268SGregory Neil Shapiro fprintf(stderr, "%s\n", s);
425b0945b5SGregory Neil Shapiro # endif
4313d88268SGregory Neil Shapiro }
4413d88268SGregory Neil Shapiro
4513d88268SGregory Neil Shapiro
4613d88268SGregory Neil Shapiro /*
4713d88268SGregory Neil Shapiro ** SEMINTER -- interactive testing of semaphores.
4813d88268SGregory Neil Shapiro **
4913d88268SGregory Neil Shapiro ** Parameters:
5013d88268SGregory Neil Shapiro ** owner -- create semaphores.
5113d88268SGregory Neil Shapiro **
5213d88268SGregory Neil Shapiro ** Returns:
5313d88268SGregory Neil Shapiro ** 0 on success
5413d88268SGregory Neil Shapiro ** < 0 on failure.
5513d88268SGregory Neil Shapiro */
5613d88268SGregory Neil Shapiro
5713d88268SGregory Neil Shapiro static int
seminter(owner)5813d88268SGregory Neil Shapiro seminter(owner)
5913d88268SGregory Neil Shapiro bool owner;
6013d88268SGregory Neil Shapiro {
6113d88268SGregory Neil Shapiro int semid;
6213d88268SGregory Neil Shapiro int t;
6313d88268SGregory Neil Shapiro
64d0cef73dSGregory Neil Shapiro semid = sm_sem_start(T_SM_SEM_KEY, SM_NSEM, 0, owner);
6513d88268SGregory Neil Shapiro if (semid < 0)
6613d88268SGregory Neil Shapiro {
6713d88268SGregory Neil Shapiro perror("sm_sem_start failed");
6813d88268SGregory Neil Shapiro return 1;
6913d88268SGregory Neil Shapiro }
7013d88268SGregory Neil Shapiro
7113d88268SGregory Neil Shapiro while ((t = getchar()) != EOF)
7213d88268SGregory Neil Shapiro {
7313d88268SGregory Neil Shapiro switch (t)
7413d88268SGregory Neil Shapiro {
7513d88268SGregory Neil Shapiro case 'a':
7613d88268SGregory Neil Shapiro delay(0, "try to acq");
7713d88268SGregory Neil Shapiro if (sm_sem_acq(semid, 0, 2) < 0)
7813d88268SGregory Neil Shapiro {
7913d88268SGregory Neil Shapiro perror("sm_sem_acq failed");
8013d88268SGregory Neil Shapiro return 1;
8113d88268SGregory Neil Shapiro }
8213d88268SGregory Neil Shapiro delay(0, "acquired");
8313d88268SGregory Neil Shapiro break;
8413d88268SGregory Neil Shapiro
8513d88268SGregory Neil Shapiro case 'r':
8613d88268SGregory Neil Shapiro delay(0, "try to rel");
8713d88268SGregory Neil Shapiro if (sm_sem_rel(semid, 0, 2) < 0)
8813d88268SGregory Neil Shapiro {
8913d88268SGregory Neil Shapiro perror("sm_sem_rel failed");
9013d88268SGregory Neil Shapiro return 1;
9113d88268SGregory Neil Shapiro }
9213d88268SGregory Neil Shapiro delay(0, "released");
9313d88268SGregory Neil Shapiro break;
9413d88268SGregory Neil Shapiro
9513d88268SGregory Neil Shapiro case 'v':
9613d88268SGregory Neil Shapiro if ((t = sm_sem_get(semid, 0)) < 0)
9713d88268SGregory Neil Shapiro {
9813d88268SGregory Neil Shapiro perror("get_sem failed");
9913d88268SGregory Neil Shapiro return 1;
10013d88268SGregory Neil Shapiro }
10113d88268SGregory Neil Shapiro printf("semval: %d\n", t);
10213d88268SGregory Neil Shapiro break;
10313d88268SGregory Neil Shapiro
10413d88268SGregory Neil Shapiro }
10513d88268SGregory Neil Shapiro }
10613d88268SGregory Neil Shapiro if (owner)
10713d88268SGregory Neil Shapiro return sm_sem_stop(semid);
10813d88268SGregory Neil Shapiro return 0;
10913d88268SGregory Neil Shapiro }
11013d88268SGregory Neil Shapiro
11113d88268SGregory Neil Shapiro /*
11213d88268SGregory Neil Shapiro ** SEM_CLEANUP -- cleanup if something breaks
11313d88268SGregory Neil Shapiro **
11413d88268SGregory Neil Shapiro ** Parameters:
11513d88268SGregory Neil Shapiro ** sig -- signal.
11613d88268SGregory Neil Shapiro **
11713d88268SGregory Neil Shapiro ** Returns:
11813d88268SGregory Neil Shapiro ** none.
11913d88268SGregory Neil Shapiro */
12013d88268SGregory Neil Shapiro
12113d88268SGregory Neil Shapiro static int semid_c = -1;
12213d88268SGregory Neil Shapiro void
sem_cleanup(sig)12313d88268SGregory Neil Shapiro sem_cleanup(sig)
12413d88268SGregory Neil Shapiro int sig;
12513d88268SGregory Neil Shapiro {
12613d88268SGregory Neil Shapiro if (semid_c >= 0)
12713d88268SGregory Neil Shapiro (void) sm_sem_stop(semid_c);
12813d88268SGregory Neil Shapiro exit(EX_UNAVAILABLE);
12913d88268SGregory Neil Shapiro }
13013d88268SGregory Neil Shapiro
1319bd497b8SGregory Neil Shapiro static int
drop_priv(uid,gid)1329bd497b8SGregory Neil Shapiro drop_priv(uid, gid)
1339bd497b8SGregory Neil Shapiro uid_t uid;
1349bd497b8SGregory Neil Shapiro gid_t gid;
1359bd497b8SGregory Neil Shapiro {
1369bd497b8SGregory Neil Shapiro int r;
1379bd497b8SGregory Neil Shapiro
1389bd497b8SGregory Neil Shapiro r = setgid(gid);
1399bd497b8SGregory Neil Shapiro if (r != 0)
1409bd497b8SGregory Neil Shapiro return r;
1419bd497b8SGregory Neil Shapiro r = setuid(uid);
1429bd497b8SGregory Neil Shapiro return r;
1439bd497b8SGregory Neil Shapiro }
1449bd497b8SGregory Neil Shapiro
14513d88268SGregory Neil Shapiro /*
14613d88268SGregory Neil Shapiro ** SEMTEST -- test of semaphores
14713d88268SGregory Neil Shapiro **
14813d88268SGregory Neil Shapiro ** Parameters:
14913d88268SGregory Neil Shapiro ** owner -- create semaphores.
15013d88268SGregory Neil Shapiro **
15113d88268SGregory Neil Shapiro ** Returns:
15213d88268SGregory Neil Shapiro ** 0 on success
15313d88268SGregory Neil Shapiro ** < 0 on failure.
15413d88268SGregory Neil Shapiro */
15513d88268SGregory Neil Shapiro
15613d88268SGregory Neil Shapiro # define MAX_CNT 10
15713d88268SGregory Neil Shapiro
15813d88268SGregory Neil Shapiro static int
semtest(owner,uid,gid)1599bd497b8SGregory Neil Shapiro semtest(owner, uid, gid)
16013d88268SGregory Neil Shapiro int owner;
1619bd497b8SGregory Neil Shapiro uid_t uid;
1629bd497b8SGregory Neil Shapiro gid_t gid;
16313d88268SGregory Neil Shapiro {
16413d88268SGregory Neil Shapiro int semid, r;
16513d88268SGregory Neil Shapiro int cnt = 0;
16613d88268SGregory Neil Shapiro
1679bd497b8SGregory Neil Shapiro if (!owner && uid != 0)
1689bd497b8SGregory Neil Shapiro {
1699bd497b8SGregory Neil Shapiro r = drop_priv(uid, gid);
1709bd497b8SGregory Neil Shapiro if (r < 0)
1719bd497b8SGregory Neil Shapiro {
1729bd497b8SGregory Neil Shapiro perror("drop_priv child failed");
1739bd497b8SGregory Neil Shapiro return -1;
1749bd497b8SGregory Neil Shapiro }
1759bd497b8SGregory Neil Shapiro }
176d0cef73dSGregory Neil Shapiro semid = sm_sem_start(T_SM_SEM_KEY, 1, 0, owner);
17713d88268SGregory Neil Shapiro if (semid < 0)
17813d88268SGregory Neil Shapiro {
17913d88268SGregory Neil Shapiro perror("sm_sem_start failed");
18013d88268SGregory Neil Shapiro return -1;
18113d88268SGregory Neil Shapiro }
18213d88268SGregory Neil Shapiro
18313d88268SGregory Neil Shapiro if (owner)
18413d88268SGregory Neil Shapiro {
1859bd497b8SGregory Neil Shapiro if (uid != 0)
1869bd497b8SGregory Neil Shapiro {
1879bd497b8SGregory Neil Shapiro r = sm_semsetowner(semid, uid, gid, 0660);
1889bd497b8SGregory Neil Shapiro if (r < 0)
1899bd497b8SGregory Neil Shapiro {
1909bd497b8SGregory Neil Shapiro perror("sm_semsetowner failed");
1919bd497b8SGregory Neil Shapiro return -1;
1929bd497b8SGregory Neil Shapiro }
1939bd497b8SGregory Neil Shapiro r = drop_priv(uid, gid);
1949bd497b8SGregory Neil Shapiro if (r < 0)
1959bd497b8SGregory Neil Shapiro {
1969bd497b8SGregory Neil Shapiro perror("drop_priv owner failed");
1979bd497b8SGregory Neil Shapiro return -1;
1989bd497b8SGregory Neil Shapiro }
1999bd497b8SGregory Neil Shapiro }
2009bd497b8SGregory Neil Shapiro
20113d88268SGregory Neil Shapiro /* just in case someone kills the program... */
20213d88268SGregory Neil Shapiro semid_c = semid;
20313d88268SGregory Neil Shapiro (void) sm_signal(SIGHUP, sem_cleanup);
20413d88268SGregory Neil Shapiro (void) sm_signal(SIGINT, sem_cleanup);
20513d88268SGregory Neil Shapiro (void) sm_signal(SIGTERM, sem_cleanup);
20613d88268SGregory Neil Shapiro
20713d88268SGregory Neil Shapiro delay(1, "parent: acquire 1");
20813d88268SGregory Neil Shapiro cnt = 0;
20913d88268SGregory Neil Shapiro do
21013d88268SGregory Neil Shapiro {
21113d88268SGregory Neil Shapiro r = sm_sem_acq(semid, 0, 0);
21213d88268SGregory Neil Shapiro if (r < 0)
21313d88268SGregory Neil Shapiro {
21413d88268SGregory Neil Shapiro sleep(1);
21513d88268SGregory Neil Shapiro ++cnt;
21613d88268SGregory Neil Shapiro }
21713d88268SGregory Neil Shapiro } while (r < 0 && cnt <= MAX_CNT);
21813d88268SGregory Neil Shapiro SM_TEST(r >= 0);
21913d88268SGregory Neil Shapiro if (r < 0)
22013d88268SGregory Neil Shapiro return r;
22113d88268SGregory Neil Shapiro
22213d88268SGregory Neil Shapiro delay(3, "parent: release 1");
22313d88268SGregory Neil Shapiro cnt = 0;
22413d88268SGregory Neil Shapiro do
22513d88268SGregory Neil Shapiro {
22613d88268SGregory Neil Shapiro r = sm_sem_rel(semid, 0, 0);
22713d88268SGregory Neil Shapiro if (r < 0)
22813d88268SGregory Neil Shapiro {
22913d88268SGregory Neil Shapiro sleep(1);
23013d88268SGregory Neil Shapiro ++cnt;
23113d88268SGregory Neil Shapiro }
23213d88268SGregory Neil Shapiro } while (r < 0 && cnt <= MAX_CNT);
23313d88268SGregory Neil Shapiro SM_TEST(r >= 0);
23413d88268SGregory Neil Shapiro if (r < 0)
23513d88268SGregory Neil Shapiro return r;
23613d88268SGregory Neil Shapiro
23713d88268SGregory Neil Shapiro delay(1, "parent: getval");
23813d88268SGregory Neil Shapiro cnt = 0;
23913d88268SGregory Neil Shapiro do
24013d88268SGregory Neil Shapiro {
24113d88268SGregory Neil Shapiro r = sm_sem_get(semid, 0);
24213d88268SGregory Neil Shapiro if (r <= 0)
24313d88268SGregory Neil Shapiro {
24413d88268SGregory Neil Shapiro sleep(1);
24513d88268SGregory Neil Shapiro ++cnt;
24613d88268SGregory Neil Shapiro }
24713d88268SGregory Neil Shapiro } while (r <= 0 && cnt <= MAX_CNT);
24813d88268SGregory Neil Shapiro SM_TEST(r > 0);
24913d88268SGregory Neil Shapiro if (r <= 0)
25013d88268SGregory Neil Shapiro return r;
25113d88268SGregory Neil Shapiro
25213d88268SGregory Neil Shapiro delay(1, "parent: acquire 2");
25313d88268SGregory Neil Shapiro cnt = 0;
25413d88268SGregory Neil Shapiro do
25513d88268SGregory Neil Shapiro {
25613d88268SGregory Neil Shapiro r = sm_sem_acq(semid, 0, 0);
25713d88268SGregory Neil Shapiro if (r < 0)
25813d88268SGregory Neil Shapiro {
25913d88268SGregory Neil Shapiro sleep(1);
26013d88268SGregory Neil Shapiro ++cnt;
26113d88268SGregory Neil Shapiro }
26213d88268SGregory Neil Shapiro } while (r < 0 && cnt <= MAX_CNT);
26313d88268SGregory Neil Shapiro SM_TEST(r >= 0);
26413d88268SGregory Neil Shapiro if (r < 0)
26513d88268SGregory Neil Shapiro return r;
26613d88268SGregory Neil Shapiro
26713d88268SGregory Neil Shapiro cnt = 0;
26813d88268SGregory Neil Shapiro do
26913d88268SGregory Neil Shapiro {
27013d88268SGregory Neil Shapiro r = sm_sem_rel(semid, 0, 0);
27113d88268SGregory Neil Shapiro if (r < 0)
27213d88268SGregory Neil Shapiro {
27313d88268SGregory Neil Shapiro sleep(1);
27413d88268SGregory Neil Shapiro ++cnt;
27513d88268SGregory Neil Shapiro }
27613d88268SGregory Neil Shapiro } while (r < 0 && cnt <= MAX_CNT);
27713d88268SGregory Neil Shapiro SM_TEST(r >= 0);
27813d88268SGregory Neil Shapiro if (r < 0)
27913d88268SGregory Neil Shapiro return r;
28013d88268SGregory Neil Shapiro }
28113d88268SGregory Neil Shapiro else
28213d88268SGregory Neil Shapiro {
28313d88268SGregory Neil Shapiro delay(1, "child: acquire 1");
28413d88268SGregory Neil Shapiro cnt = 0;
28513d88268SGregory Neil Shapiro do
28613d88268SGregory Neil Shapiro {
28713d88268SGregory Neil Shapiro r = sm_sem_acq(semid, 0, 0);
28813d88268SGregory Neil Shapiro if (r < 0)
28913d88268SGregory Neil Shapiro {
29013d88268SGregory Neil Shapiro sleep(1);
29113d88268SGregory Neil Shapiro ++cnt;
29213d88268SGregory Neil Shapiro }
29313d88268SGregory Neil Shapiro } while (r < 0 && cnt <= MAX_CNT);
29413d88268SGregory Neil Shapiro SM_TEST(r >= 0);
29513d88268SGregory Neil Shapiro if (r < 0)
29613d88268SGregory Neil Shapiro return r;
29713d88268SGregory Neil Shapiro
29813d88268SGregory Neil Shapiro delay(1, "child: release 1");
29913d88268SGregory Neil Shapiro cnt = 0;
30013d88268SGregory Neil Shapiro do
30113d88268SGregory Neil Shapiro {
30213d88268SGregory Neil Shapiro r = sm_sem_rel(semid, 0, 0);
30313d88268SGregory Neil Shapiro if (r < 0)
30413d88268SGregory Neil Shapiro {
30513d88268SGregory Neil Shapiro sleep(1);
30613d88268SGregory Neil Shapiro ++cnt;
30713d88268SGregory Neil Shapiro }
30813d88268SGregory Neil Shapiro } while (r < 0 && cnt <= MAX_CNT);
30913d88268SGregory Neil Shapiro SM_TEST(r >= 0);
31013d88268SGregory Neil Shapiro if (r < 0)
31113d88268SGregory Neil Shapiro return r;
31213d88268SGregory Neil Shapiro
31313d88268SGregory Neil Shapiro }
31413d88268SGregory Neil Shapiro if (owner)
31513d88268SGregory Neil Shapiro return sm_sem_stop(semid);
31613d88268SGregory Neil Shapiro return 0;
31713d88268SGregory Neil Shapiro }
31813d88268SGregory Neil Shapiro
31913d88268SGregory Neil Shapiro int
main(argc,argv)32013d88268SGregory Neil Shapiro main(argc, argv)
32113d88268SGregory Neil Shapiro int argc;
32213d88268SGregory Neil Shapiro char *argv[];
32313d88268SGregory Neil Shapiro {
32413d88268SGregory Neil Shapiro bool interactive = false;
32513d88268SGregory Neil Shapiro bool owner = false;
3269bd497b8SGregory Neil Shapiro int ch, r;
3279bd497b8SGregory Neil Shapiro uid_t uid;
3289bd497b8SGregory Neil Shapiro gid_t gid;
32913d88268SGregory Neil Shapiro
3309bd497b8SGregory Neil Shapiro uid = 0;
3319bd497b8SGregory Neil Shapiro gid = 0;
3329bd497b8SGregory Neil Shapiro r = 0;
3339bd497b8SGregory Neil Shapiro
3349bd497b8SGregory Neil Shapiro # define OPTIONS "iog:u:"
33513d88268SGregory Neil Shapiro while ((ch = getopt(argc, argv, OPTIONS)) != -1)
33613d88268SGregory Neil Shapiro {
33713d88268SGregory Neil Shapiro switch ((char) ch)
33813d88268SGregory Neil Shapiro {
3399bd497b8SGregory Neil Shapiro case 'g':
3409bd497b8SGregory Neil Shapiro gid = (gid_t)strtoul(optarg, 0, 0);
3419bd497b8SGregory Neil Shapiro break;
3429bd497b8SGregory Neil Shapiro
34313d88268SGregory Neil Shapiro case 'i':
34413d88268SGregory Neil Shapiro interactive = true;
34513d88268SGregory Neil Shapiro break;
34613d88268SGregory Neil Shapiro
3479bd497b8SGregory Neil Shapiro case 'u':
3489bd497b8SGregory Neil Shapiro uid = (uid_t)strtoul(optarg, 0, 0);
3499bd497b8SGregory Neil Shapiro break;
3509bd497b8SGregory Neil Shapiro
35113d88268SGregory Neil Shapiro case 'o':
35213d88268SGregory Neil Shapiro owner = true;
35313d88268SGregory Neil Shapiro break;
35413d88268SGregory Neil Shapiro
35513d88268SGregory Neil Shapiro default:
35613d88268SGregory Neil Shapiro break;
35713d88268SGregory Neil Shapiro }
35813d88268SGregory Neil Shapiro }
35913d88268SGregory Neil Shapiro
36013d88268SGregory Neil Shapiro if (interactive)
36113d88268SGregory Neil Shapiro r = seminter(owner);
36213d88268SGregory Neil Shapiro else
36313d88268SGregory Neil Shapiro {
36413d88268SGregory Neil Shapiro pid_t pid;
36513d88268SGregory Neil Shapiro
36613d88268SGregory Neil Shapiro printf("This test takes about 8 seconds.\n");
3674e4196cbSGregory Neil Shapiro printf("If it takes longer than 30 seconds, please interrupt it\n");
36813d88268SGregory Neil Shapiro printf("and compile again without semaphore support, i.e.,");
36913d88268SGregory Neil Shapiro printf("-DSM_CONF_SEM=0\n");
37013d88268SGregory Neil Shapiro if ((pid = fork()) < 0)
37113d88268SGregory Neil Shapiro {
37213d88268SGregory Neil Shapiro perror("fork failed\n");
37313d88268SGregory Neil Shapiro return -1;
37413d88268SGregory Neil Shapiro }
37513d88268SGregory Neil Shapiro
37613d88268SGregory Neil Shapiro sm_test_begin(argc, argv, "test semaphores");
37713d88268SGregory Neil Shapiro if (pid == 0)
37813d88268SGregory Neil Shapiro {
37913d88268SGregory Neil Shapiro /* give the parent the chance to setup data */
38013d88268SGregory Neil Shapiro sleep(1);
3819bd497b8SGregory Neil Shapiro r = semtest(false, uid, gid);
38213d88268SGregory Neil Shapiro }
38313d88268SGregory Neil Shapiro else
38413d88268SGregory Neil Shapiro {
3859bd497b8SGregory Neil Shapiro r = semtest(true, uid, gid);
38613d88268SGregory Neil Shapiro }
38713d88268SGregory Neil Shapiro SM_TEST(r == 0);
38813d88268SGregory Neil Shapiro return sm_test_end();
38913d88268SGregory Neil Shapiro }
39013d88268SGregory Neil Shapiro return r;
39113d88268SGregory Neil Shapiro }
39213d88268SGregory Neil Shapiro #else /* SM_CONF_SEM */
39313d88268SGregory Neil Shapiro int
39413d88268SGregory Neil Shapiro main(argc, argv)
39513d88268SGregory Neil Shapiro int argc;
39613d88268SGregory Neil Shapiro char *argv[];
39713d88268SGregory Neil Shapiro {
39813d88268SGregory Neil Shapiro printf("No support for semaphores configured on this machine\n");
39913d88268SGregory Neil Shapiro return 0;
40013d88268SGregory Neil Shapiro }
40113d88268SGregory Neil Shapiro #endif /* SM_CONF_SEM */
402