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> 2313d88268SGregory Neil Shapiro # include <sm/sem.h> 2413d88268SGregory Neil Shapiro 25d0cef73dSGregory Neil Shapiro # define T_SM_SEM_KEY (4321L) 26d0cef73dSGregory Neil Shapiro 2713d88268SGregory Neil Shapiro static void 2813d88268SGregory Neil Shapiro delay(t, s) 2913d88268SGregory Neil Shapiro int t; 3013d88268SGregory Neil Shapiro char *s; 3113d88268SGregory Neil Shapiro { 3213d88268SGregory Neil Shapiro if (t > 0) 3313d88268SGregory Neil Shapiro { 3413d88268SGregory Neil Shapiro #if DEBUG 3513d88268SGregory Neil Shapiro fprintf(stderr, "sleep(%d) before %s\n", t, s); 36*5b0945b5SGregory Neil Shapiro #endif 3713d88268SGregory Neil Shapiro sleep(t); 3813d88268SGregory Neil Shapiro } 3913d88268SGregory Neil Shapiro #if DEBUG 4013d88268SGregory Neil Shapiro fprintf(stderr, "%s\n", s); 41*5b0945b5SGregory Neil Shapiro #endif 4213d88268SGregory Neil Shapiro } 4313d88268SGregory Neil Shapiro 4413d88268SGregory Neil Shapiro 4513d88268SGregory Neil Shapiro /* 4613d88268SGregory Neil Shapiro ** SEMINTER -- interactive testing of semaphores. 4713d88268SGregory Neil Shapiro ** 4813d88268SGregory Neil Shapiro ** Parameters: 4913d88268SGregory Neil Shapiro ** owner -- create semaphores. 5013d88268SGregory Neil Shapiro ** 5113d88268SGregory Neil Shapiro ** Returns: 5213d88268SGregory Neil Shapiro ** 0 on success 5313d88268SGregory Neil Shapiro ** < 0 on failure. 5413d88268SGregory Neil Shapiro */ 5513d88268SGregory Neil Shapiro 5613d88268SGregory Neil Shapiro static int 5713d88268SGregory Neil Shapiro seminter(owner) 5813d88268SGregory Neil Shapiro bool owner; 5913d88268SGregory Neil Shapiro { 6013d88268SGregory Neil Shapiro int semid; 6113d88268SGregory Neil Shapiro int t; 6213d88268SGregory Neil Shapiro 63d0cef73dSGregory Neil Shapiro semid = sm_sem_start(T_SM_SEM_KEY, SM_NSEM, 0, owner); 6413d88268SGregory Neil Shapiro if (semid < 0) 6513d88268SGregory Neil Shapiro { 6613d88268SGregory Neil Shapiro perror("sm_sem_start failed"); 6713d88268SGregory Neil Shapiro return 1; 6813d88268SGregory Neil Shapiro } 6913d88268SGregory Neil Shapiro 7013d88268SGregory Neil Shapiro while ((t = getchar()) != EOF) 7113d88268SGregory Neil Shapiro { 7213d88268SGregory Neil Shapiro switch (t) 7313d88268SGregory Neil Shapiro { 7413d88268SGregory Neil Shapiro case 'a': 7513d88268SGregory Neil Shapiro delay(0, "try to acq"); 7613d88268SGregory Neil Shapiro if (sm_sem_acq(semid, 0, 2) < 0) 7713d88268SGregory Neil Shapiro { 7813d88268SGregory Neil Shapiro perror("sm_sem_acq failed"); 7913d88268SGregory Neil Shapiro return 1; 8013d88268SGregory Neil Shapiro } 8113d88268SGregory Neil Shapiro delay(0, "acquired"); 8213d88268SGregory Neil Shapiro break; 8313d88268SGregory Neil Shapiro 8413d88268SGregory Neil Shapiro case 'r': 8513d88268SGregory Neil Shapiro delay(0, "try to rel"); 8613d88268SGregory Neil Shapiro if (sm_sem_rel(semid, 0, 2) < 0) 8713d88268SGregory Neil Shapiro { 8813d88268SGregory Neil Shapiro perror("sm_sem_rel failed"); 8913d88268SGregory Neil Shapiro return 1; 9013d88268SGregory Neil Shapiro } 9113d88268SGregory Neil Shapiro delay(0, "released"); 9213d88268SGregory Neil Shapiro break; 9313d88268SGregory Neil Shapiro 9413d88268SGregory Neil Shapiro case 'v': 9513d88268SGregory Neil Shapiro if ((t = sm_sem_get(semid, 0)) < 0) 9613d88268SGregory Neil Shapiro { 9713d88268SGregory Neil Shapiro perror("get_sem failed"); 9813d88268SGregory Neil Shapiro return 1; 9913d88268SGregory Neil Shapiro } 10013d88268SGregory Neil Shapiro printf("semval: %d\n", t); 10113d88268SGregory Neil Shapiro break; 10213d88268SGregory Neil Shapiro 10313d88268SGregory Neil Shapiro } 10413d88268SGregory Neil Shapiro } 10513d88268SGregory Neil Shapiro if (owner) 10613d88268SGregory Neil Shapiro return sm_sem_stop(semid); 10713d88268SGregory Neil Shapiro return 0; 10813d88268SGregory Neil Shapiro } 10913d88268SGregory Neil Shapiro 11013d88268SGregory Neil Shapiro /* 11113d88268SGregory Neil Shapiro ** SEM_CLEANUP -- cleanup if something breaks 11213d88268SGregory Neil Shapiro ** 11313d88268SGregory Neil Shapiro ** Parameters: 11413d88268SGregory Neil Shapiro ** sig -- signal. 11513d88268SGregory Neil Shapiro ** 11613d88268SGregory Neil Shapiro ** Returns: 11713d88268SGregory Neil Shapiro ** none. 11813d88268SGregory Neil Shapiro */ 11913d88268SGregory Neil Shapiro 12013d88268SGregory Neil Shapiro static int semid_c = -1; 12113d88268SGregory Neil Shapiro void 12213d88268SGregory Neil Shapiro sem_cleanup(sig) 12313d88268SGregory Neil Shapiro int sig; 12413d88268SGregory Neil Shapiro { 12513d88268SGregory Neil Shapiro if (semid_c >= 0) 12613d88268SGregory Neil Shapiro (void) sm_sem_stop(semid_c); 12713d88268SGregory Neil Shapiro exit(EX_UNAVAILABLE); 12813d88268SGregory Neil Shapiro } 12913d88268SGregory Neil Shapiro 1309bd497b8SGregory Neil Shapiro static int 1319bd497b8SGregory Neil Shapiro drop_priv(uid, gid) 1329bd497b8SGregory Neil Shapiro uid_t uid; 1339bd497b8SGregory Neil Shapiro gid_t gid; 1349bd497b8SGregory Neil Shapiro { 1359bd497b8SGregory Neil Shapiro int r; 1369bd497b8SGregory Neil Shapiro 1379bd497b8SGregory Neil Shapiro r = setgid(gid); 1389bd497b8SGregory Neil Shapiro if (r != 0) 1399bd497b8SGregory Neil Shapiro return r; 1409bd497b8SGregory Neil Shapiro r = setuid(uid); 1419bd497b8SGregory Neil Shapiro return r; 1429bd497b8SGregory Neil Shapiro } 1439bd497b8SGregory Neil Shapiro 14413d88268SGregory Neil Shapiro /* 14513d88268SGregory Neil Shapiro ** SEMTEST -- test of semaphores 14613d88268SGregory Neil Shapiro ** 14713d88268SGregory Neil Shapiro ** Parameters: 14813d88268SGregory Neil Shapiro ** owner -- create semaphores. 14913d88268SGregory Neil Shapiro ** 15013d88268SGregory Neil Shapiro ** Returns: 15113d88268SGregory Neil Shapiro ** 0 on success 15213d88268SGregory Neil Shapiro ** < 0 on failure. 15313d88268SGregory Neil Shapiro */ 15413d88268SGregory Neil Shapiro 15513d88268SGregory Neil Shapiro # define MAX_CNT 10 15613d88268SGregory Neil Shapiro 15713d88268SGregory Neil Shapiro static int 1589bd497b8SGregory Neil Shapiro semtest(owner, uid, gid) 15913d88268SGregory Neil Shapiro int owner; 1609bd497b8SGregory Neil Shapiro uid_t uid; 1619bd497b8SGregory Neil Shapiro gid_t gid; 16213d88268SGregory Neil Shapiro { 16313d88268SGregory Neil Shapiro int semid, r; 16413d88268SGregory Neil Shapiro int cnt = 0; 16513d88268SGregory Neil Shapiro 1669bd497b8SGregory Neil Shapiro if (!owner && uid != 0) 1679bd497b8SGregory Neil Shapiro { 1689bd497b8SGregory Neil Shapiro r = drop_priv(uid, gid); 1699bd497b8SGregory Neil Shapiro if (r < 0) 1709bd497b8SGregory Neil Shapiro { 1719bd497b8SGregory Neil Shapiro perror("drop_priv child failed"); 1729bd497b8SGregory Neil Shapiro return -1; 1739bd497b8SGregory Neil Shapiro } 1749bd497b8SGregory Neil Shapiro } 175d0cef73dSGregory Neil Shapiro semid = sm_sem_start(T_SM_SEM_KEY, 1, 0, owner); 17613d88268SGregory Neil Shapiro if (semid < 0) 17713d88268SGregory Neil Shapiro { 17813d88268SGregory Neil Shapiro perror("sm_sem_start failed"); 17913d88268SGregory Neil Shapiro return -1; 18013d88268SGregory Neil Shapiro } 18113d88268SGregory Neil Shapiro 18213d88268SGregory Neil Shapiro if (owner) 18313d88268SGregory Neil Shapiro { 1849bd497b8SGregory Neil Shapiro if (uid != 0) 1859bd497b8SGregory Neil Shapiro { 1869bd497b8SGregory Neil Shapiro r = sm_semsetowner(semid, uid, gid, 0660); 1879bd497b8SGregory Neil Shapiro if (r < 0) 1889bd497b8SGregory Neil Shapiro { 1899bd497b8SGregory Neil Shapiro perror("sm_semsetowner failed"); 1909bd497b8SGregory Neil Shapiro return -1; 1919bd497b8SGregory Neil Shapiro } 1929bd497b8SGregory Neil Shapiro r = drop_priv(uid, gid); 1939bd497b8SGregory Neil Shapiro if (r < 0) 1949bd497b8SGregory Neil Shapiro { 1959bd497b8SGregory Neil Shapiro perror("drop_priv owner failed"); 1969bd497b8SGregory Neil Shapiro return -1; 1979bd497b8SGregory Neil Shapiro } 1989bd497b8SGregory Neil Shapiro } 1999bd497b8SGregory Neil Shapiro 20013d88268SGregory Neil Shapiro /* just in case someone kills the program... */ 20113d88268SGregory Neil Shapiro semid_c = semid; 20213d88268SGregory Neil Shapiro (void) sm_signal(SIGHUP, sem_cleanup); 20313d88268SGregory Neil Shapiro (void) sm_signal(SIGINT, sem_cleanup); 20413d88268SGregory Neil Shapiro (void) sm_signal(SIGTERM, sem_cleanup); 20513d88268SGregory Neil Shapiro 20613d88268SGregory Neil Shapiro delay(1, "parent: acquire 1"); 20713d88268SGregory Neil Shapiro cnt = 0; 20813d88268SGregory Neil Shapiro do 20913d88268SGregory Neil Shapiro { 21013d88268SGregory Neil Shapiro r = sm_sem_acq(semid, 0, 0); 21113d88268SGregory Neil Shapiro if (r < 0) 21213d88268SGregory Neil Shapiro { 21313d88268SGregory Neil Shapiro sleep(1); 21413d88268SGregory Neil Shapiro ++cnt; 21513d88268SGregory Neil Shapiro } 21613d88268SGregory Neil Shapiro } while (r < 0 && cnt <= MAX_CNT); 21713d88268SGregory Neil Shapiro SM_TEST(r >= 0); 21813d88268SGregory Neil Shapiro if (r < 0) 21913d88268SGregory Neil Shapiro return r; 22013d88268SGregory Neil Shapiro 22113d88268SGregory Neil Shapiro delay(3, "parent: release 1"); 22213d88268SGregory Neil Shapiro cnt = 0; 22313d88268SGregory Neil Shapiro do 22413d88268SGregory Neil Shapiro { 22513d88268SGregory Neil Shapiro r = sm_sem_rel(semid, 0, 0); 22613d88268SGregory Neil Shapiro if (r < 0) 22713d88268SGregory Neil Shapiro { 22813d88268SGregory Neil Shapiro sleep(1); 22913d88268SGregory Neil Shapiro ++cnt; 23013d88268SGregory Neil Shapiro } 23113d88268SGregory Neil Shapiro } while (r < 0 && cnt <= MAX_CNT); 23213d88268SGregory Neil Shapiro SM_TEST(r >= 0); 23313d88268SGregory Neil Shapiro if (r < 0) 23413d88268SGregory Neil Shapiro return r; 23513d88268SGregory Neil Shapiro 23613d88268SGregory Neil Shapiro delay(1, "parent: getval"); 23713d88268SGregory Neil Shapiro cnt = 0; 23813d88268SGregory Neil Shapiro do 23913d88268SGregory Neil Shapiro { 24013d88268SGregory Neil Shapiro r = sm_sem_get(semid, 0); 24113d88268SGregory Neil Shapiro if (r <= 0) 24213d88268SGregory Neil Shapiro { 24313d88268SGregory Neil Shapiro sleep(1); 24413d88268SGregory Neil Shapiro ++cnt; 24513d88268SGregory Neil Shapiro } 24613d88268SGregory Neil Shapiro } while (r <= 0 && cnt <= MAX_CNT); 24713d88268SGregory Neil Shapiro SM_TEST(r > 0); 24813d88268SGregory Neil Shapiro if (r <= 0) 24913d88268SGregory Neil Shapiro return r; 25013d88268SGregory Neil Shapiro 25113d88268SGregory Neil Shapiro delay(1, "parent: acquire 2"); 25213d88268SGregory Neil Shapiro cnt = 0; 25313d88268SGregory Neil Shapiro do 25413d88268SGregory Neil Shapiro { 25513d88268SGregory Neil Shapiro r = sm_sem_acq(semid, 0, 0); 25613d88268SGregory Neil Shapiro if (r < 0) 25713d88268SGregory Neil Shapiro { 25813d88268SGregory Neil Shapiro sleep(1); 25913d88268SGregory Neil Shapiro ++cnt; 26013d88268SGregory Neil Shapiro } 26113d88268SGregory Neil Shapiro } while (r < 0 && cnt <= MAX_CNT); 26213d88268SGregory Neil Shapiro SM_TEST(r >= 0); 26313d88268SGregory Neil Shapiro if (r < 0) 26413d88268SGregory Neil Shapiro return r; 26513d88268SGregory Neil Shapiro 26613d88268SGregory Neil Shapiro cnt = 0; 26713d88268SGregory Neil Shapiro do 26813d88268SGregory Neil Shapiro { 26913d88268SGregory Neil Shapiro r = sm_sem_rel(semid, 0, 0); 27013d88268SGregory Neil Shapiro if (r < 0) 27113d88268SGregory Neil Shapiro { 27213d88268SGregory Neil Shapiro sleep(1); 27313d88268SGregory Neil Shapiro ++cnt; 27413d88268SGregory Neil Shapiro } 27513d88268SGregory Neil Shapiro } while (r < 0 && cnt <= MAX_CNT); 27613d88268SGregory Neil Shapiro SM_TEST(r >= 0); 27713d88268SGregory Neil Shapiro if (r < 0) 27813d88268SGregory Neil Shapiro return r; 27913d88268SGregory Neil Shapiro } 28013d88268SGregory Neil Shapiro else 28113d88268SGregory Neil Shapiro { 28213d88268SGregory Neil Shapiro delay(1, "child: acquire 1"); 28313d88268SGregory Neil Shapiro cnt = 0; 28413d88268SGregory Neil Shapiro do 28513d88268SGregory Neil Shapiro { 28613d88268SGregory Neil Shapiro r = sm_sem_acq(semid, 0, 0); 28713d88268SGregory Neil Shapiro if (r < 0) 28813d88268SGregory Neil Shapiro { 28913d88268SGregory Neil Shapiro sleep(1); 29013d88268SGregory Neil Shapiro ++cnt; 29113d88268SGregory Neil Shapiro } 29213d88268SGregory Neil Shapiro } while (r < 0 && cnt <= MAX_CNT); 29313d88268SGregory Neil Shapiro SM_TEST(r >= 0); 29413d88268SGregory Neil Shapiro if (r < 0) 29513d88268SGregory Neil Shapiro return r; 29613d88268SGregory Neil Shapiro 29713d88268SGregory Neil Shapiro delay(1, "child: release 1"); 29813d88268SGregory Neil Shapiro cnt = 0; 29913d88268SGregory Neil Shapiro do 30013d88268SGregory Neil Shapiro { 30113d88268SGregory Neil Shapiro r = sm_sem_rel(semid, 0, 0); 30213d88268SGregory Neil Shapiro if (r < 0) 30313d88268SGregory Neil Shapiro { 30413d88268SGregory Neil Shapiro sleep(1); 30513d88268SGregory Neil Shapiro ++cnt; 30613d88268SGregory Neil Shapiro } 30713d88268SGregory Neil Shapiro } while (r < 0 && cnt <= MAX_CNT); 30813d88268SGregory Neil Shapiro SM_TEST(r >= 0); 30913d88268SGregory Neil Shapiro if (r < 0) 31013d88268SGregory Neil Shapiro return r; 31113d88268SGregory Neil Shapiro 31213d88268SGregory Neil Shapiro } 31313d88268SGregory Neil Shapiro if (owner) 31413d88268SGregory Neil Shapiro return sm_sem_stop(semid); 31513d88268SGregory Neil Shapiro return 0; 31613d88268SGregory Neil Shapiro } 31713d88268SGregory Neil Shapiro 31813d88268SGregory Neil Shapiro int 31913d88268SGregory Neil Shapiro main(argc, argv) 32013d88268SGregory Neil Shapiro int argc; 32113d88268SGregory Neil Shapiro char *argv[]; 32213d88268SGregory Neil Shapiro { 32313d88268SGregory Neil Shapiro bool interactive = false; 32413d88268SGregory Neil Shapiro bool owner = false; 3259bd497b8SGregory Neil Shapiro int ch, r; 3269bd497b8SGregory Neil Shapiro uid_t uid; 3279bd497b8SGregory Neil Shapiro gid_t gid; 32813d88268SGregory Neil Shapiro 3299bd497b8SGregory Neil Shapiro uid = 0; 3309bd497b8SGregory Neil Shapiro gid = 0; 3319bd497b8SGregory Neil Shapiro r = 0; 3329bd497b8SGregory Neil Shapiro 3339bd497b8SGregory Neil Shapiro # define OPTIONS "iog:u:" 33413d88268SGregory Neil Shapiro while ((ch = getopt(argc, argv, OPTIONS)) != -1) 33513d88268SGregory Neil Shapiro { 33613d88268SGregory Neil Shapiro switch ((char) ch) 33713d88268SGregory Neil Shapiro { 3389bd497b8SGregory Neil Shapiro case 'g': 3399bd497b8SGregory Neil Shapiro gid = (gid_t)strtoul(optarg, 0, 0); 3409bd497b8SGregory Neil Shapiro break; 3419bd497b8SGregory Neil Shapiro 34213d88268SGregory Neil Shapiro case 'i': 34313d88268SGregory Neil Shapiro interactive = true; 34413d88268SGregory Neil Shapiro break; 34513d88268SGregory Neil Shapiro 3469bd497b8SGregory Neil Shapiro case 'u': 3479bd497b8SGregory Neil Shapiro uid = (uid_t)strtoul(optarg, 0, 0); 3489bd497b8SGregory Neil Shapiro break; 3499bd497b8SGregory Neil Shapiro 35013d88268SGregory Neil Shapiro case 'o': 35113d88268SGregory Neil Shapiro owner = true; 35213d88268SGregory Neil Shapiro break; 35313d88268SGregory Neil Shapiro 35413d88268SGregory Neil Shapiro default: 35513d88268SGregory Neil Shapiro break; 35613d88268SGregory Neil Shapiro } 35713d88268SGregory Neil Shapiro } 35813d88268SGregory Neil Shapiro 35913d88268SGregory Neil Shapiro if (interactive) 36013d88268SGregory Neil Shapiro r = seminter(owner); 36113d88268SGregory Neil Shapiro else 36213d88268SGregory Neil Shapiro { 36313d88268SGregory Neil Shapiro pid_t pid; 36413d88268SGregory Neil Shapiro 36513d88268SGregory Neil Shapiro printf("This test takes about 8 seconds.\n"); 3664e4196cbSGregory Neil Shapiro printf("If it takes longer than 30 seconds, please interrupt it\n"); 36713d88268SGregory Neil Shapiro printf("and compile again without semaphore support, i.e.,"); 36813d88268SGregory Neil Shapiro printf("-DSM_CONF_SEM=0\n"); 36913d88268SGregory Neil Shapiro if ((pid = fork()) < 0) 37013d88268SGregory Neil Shapiro { 37113d88268SGregory Neil Shapiro perror("fork failed\n"); 37213d88268SGregory Neil Shapiro return -1; 37313d88268SGregory Neil Shapiro } 37413d88268SGregory Neil Shapiro 37513d88268SGregory Neil Shapiro sm_test_begin(argc, argv, "test semaphores"); 37613d88268SGregory Neil Shapiro if (pid == 0) 37713d88268SGregory Neil Shapiro { 37813d88268SGregory Neil Shapiro /* give the parent the chance to setup data */ 37913d88268SGregory Neil Shapiro sleep(1); 3809bd497b8SGregory Neil Shapiro r = semtest(false, uid, gid); 38113d88268SGregory Neil Shapiro } 38213d88268SGregory Neil Shapiro else 38313d88268SGregory Neil Shapiro { 3849bd497b8SGregory Neil Shapiro r = semtest(true, uid, gid); 38513d88268SGregory Neil Shapiro } 38613d88268SGregory Neil Shapiro SM_TEST(r == 0); 38713d88268SGregory Neil Shapiro return sm_test_end(); 38813d88268SGregory Neil Shapiro } 38913d88268SGregory Neil Shapiro return r; 39013d88268SGregory Neil Shapiro } 39113d88268SGregory Neil Shapiro #else /* SM_CONF_SEM */ 39213d88268SGregory Neil Shapiro int 39313d88268SGregory Neil Shapiro main(argc, argv) 39413d88268SGregory Neil Shapiro int argc; 39513d88268SGregory Neil Shapiro char *argv[]; 39613d88268SGregory Neil Shapiro { 39713d88268SGregory Neil Shapiro printf("No support for semaphores configured on this machine\n"); 39813d88268SGregory Neil Shapiro return 0; 39913d88268SGregory Neil Shapiro } 40013d88268SGregory Neil Shapiro #endif /* SM_CONF_SEM */ 401