1147078Sgshapiro/* 2203004Sgshapiro * Copyright (c) 2000-2001, 2005-2008 Sendmail, Inc. and its suppliers. 3147078Sgshapiro * All rights reserved. 4147078Sgshapiro * 5147078Sgshapiro * By using this file, you agree to the terms and conditions set 6147078Sgshapiro * forth in the LICENSE file which can be found at the top level of 7147078Sgshapiro * the sendmail distribution. 8147078Sgshapiro */ 9147078Sgshapiro 10147078Sgshapiro#include <sm/gen.h> 11203004SgshapiroSM_RCSID("@(#)$Id: t-sem.c,v 1.17 2008/05/30 16:26:38 ca Exp $") 12147078Sgshapiro 13147078Sgshapiro#include <stdio.h> 14147078Sgshapiro 15147078Sgshapiro#if SM_CONF_SEM 16147078Sgshapiro# include <stdlib.h> 17147078Sgshapiro# include <unistd.h> 18147078Sgshapiro# include <sysexits.h> 19147078Sgshapiro# include <sm/heap.h> 20147078Sgshapiro# include <sm/string.h> 21147078Sgshapiro# include <sm/signal.h> 22147078Sgshapiro# include <sm/test.h> 23147078Sgshapiro# include <sm/sem.h> 24147078Sgshapiro 25168515Sgshapiro# define T_SM_SEM_KEY (4321L) 26168515Sgshapiro 27147078Sgshapirostatic void 28147078Sgshapirodelay(t, s) 29147078Sgshapiro int t; 30147078Sgshapiro char *s; 31147078Sgshapiro{ 32147078Sgshapiro if (t > 0) 33147078Sgshapiro { 34147078Sgshapiro#if DEBUG 35147078Sgshapiro fprintf(stderr, "sleep(%d) before %s\n", t, s); 36147078Sgshapiro#endif /* DEBUG */ 37147078Sgshapiro sleep(t); 38147078Sgshapiro } 39147078Sgshapiro#if DEBUG 40147078Sgshapiro fprintf(stderr, "%s\n", s); 41147078Sgshapiro#endif /* DEBUG */ 42147078Sgshapiro} 43147078Sgshapiro 44147078Sgshapiro 45147078Sgshapiro/* 46147078Sgshapiro** SEMINTER -- interactive testing of semaphores. 47147078Sgshapiro** 48147078Sgshapiro** Parameters: 49147078Sgshapiro** owner -- create semaphores. 50147078Sgshapiro** 51147078Sgshapiro** Returns: 52147078Sgshapiro** 0 on success 53147078Sgshapiro** < 0 on failure. 54147078Sgshapiro*/ 55147078Sgshapiro 56147078Sgshapirostatic int 57147078Sgshapiroseminter(owner) 58147078Sgshapiro bool owner; 59147078Sgshapiro{ 60147078Sgshapiro int semid; 61147078Sgshapiro int t; 62147078Sgshapiro 63168515Sgshapiro semid = sm_sem_start(T_SM_SEM_KEY, SM_NSEM, 0, owner); 64147078Sgshapiro if (semid < 0) 65147078Sgshapiro { 66147078Sgshapiro perror("sm_sem_start failed"); 67147078Sgshapiro return 1; 68147078Sgshapiro } 69147078Sgshapiro 70147078Sgshapiro while ((t = getchar()) != EOF) 71147078Sgshapiro { 72147078Sgshapiro switch (t) 73147078Sgshapiro { 74147078Sgshapiro case 'a': 75147078Sgshapiro delay(0, "try to acq"); 76147078Sgshapiro if (sm_sem_acq(semid, 0, 2) < 0) 77147078Sgshapiro { 78147078Sgshapiro perror("sm_sem_acq failed"); 79147078Sgshapiro return 1; 80147078Sgshapiro } 81147078Sgshapiro delay(0, "acquired"); 82147078Sgshapiro break; 83147078Sgshapiro 84147078Sgshapiro case 'r': 85147078Sgshapiro delay(0, "try to rel"); 86147078Sgshapiro if (sm_sem_rel(semid, 0, 2) < 0) 87147078Sgshapiro { 88147078Sgshapiro perror("sm_sem_rel failed"); 89147078Sgshapiro return 1; 90147078Sgshapiro } 91147078Sgshapiro delay(0, "released"); 92147078Sgshapiro break; 93147078Sgshapiro 94147078Sgshapiro case 'v': 95147078Sgshapiro if ((t = sm_sem_get(semid, 0)) < 0) 96147078Sgshapiro { 97147078Sgshapiro perror("get_sem failed"); 98147078Sgshapiro return 1; 99147078Sgshapiro } 100147078Sgshapiro printf("semval: %d\n", t); 101147078Sgshapiro break; 102147078Sgshapiro 103147078Sgshapiro } 104147078Sgshapiro } 105147078Sgshapiro if (owner) 106147078Sgshapiro return sm_sem_stop(semid); 107147078Sgshapiro return 0; 108147078Sgshapiro} 109147078Sgshapiro 110147078Sgshapiro/* 111147078Sgshapiro** SEM_CLEANUP -- cleanup if something breaks 112147078Sgshapiro** 113147078Sgshapiro** Parameters: 114147078Sgshapiro** sig -- signal. 115147078Sgshapiro** 116147078Sgshapiro** Returns: 117147078Sgshapiro** none. 118147078Sgshapiro*/ 119147078Sgshapiro 120147078Sgshapirostatic int semid_c = -1; 121147078Sgshapirovoid 122147078Sgshapirosem_cleanup(sig) 123147078Sgshapiro int sig; 124147078Sgshapiro{ 125147078Sgshapiro if (semid_c >= 0) 126147078Sgshapiro (void) sm_sem_stop(semid_c); 127147078Sgshapiro exit(EX_UNAVAILABLE); 128147078Sgshapiro} 129147078Sgshapiro 130203004Sgshapirostatic int 131203004Sgshapirodrop_priv(uid, gid) 132203004Sgshapiro uid_t uid; 133203004Sgshapiro gid_t gid; 134203004Sgshapiro{ 135203004Sgshapiro int r; 136203004Sgshapiro 137203004Sgshapiro r = setgid(gid); 138203004Sgshapiro if (r != 0) 139203004Sgshapiro return r; 140203004Sgshapiro r = setuid(uid); 141203004Sgshapiro return r; 142203004Sgshapiro} 143203004Sgshapiro 144147078Sgshapiro/* 145147078Sgshapiro** SEMTEST -- test of semaphores 146147078Sgshapiro** 147147078Sgshapiro** Parameters: 148147078Sgshapiro** owner -- create semaphores. 149147078Sgshapiro** 150147078Sgshapiro** Returns: 151147078Sgshapiro** 0 on success 152147078Sgshapiro** < 0 on failure. 153147078Sgshapiro*/ 154147078Sgshapiro 155147078Sgshapiro# define MAX_CNT 10 156147078Sgshapiro 157147078Sgshapirostatic int 158203004Sgshapirosemtest(owner, uid, gid) 159147078Sgshapiro int owner; 160203004Sgshapiro uid_t uid; 161203004Sgshapiro gid_t gid; 162147078Sgshapiro{ 163147078Sgshapiro int semid, r; 164147078Sgshapiro int cnt = 0; 165147078Sgshapiro 166203004Sgshapiro if (!owner && uid != 0) 167203004Sgshapiro { 168203004Sgshapiro r = drop_priv(uid, gid); 169203004Sgshapiro if (r < 0) 170203004Sgshapiro { 171203004Sgshapiro perror("drop_priv child failed"); 172203004Sgshapiro return -1; 173203004Sgshapiro } 174203004Sgshapiro } 175168515Sgshapiro semid = sm_sem_start(T_SM_SEM_KEY, 1, 0, owner); 176147078Sgshapiro if (semid < 0) 177147078Sgshapiro { 178147078Sgshapiro perror("sm_sem_start failed"); 179147078Sgshapiro return -1; 180147078Sgshapiro } 181147078Sgshapiro 182147078Sgshapiro if (owner) 183147078Sgshapiro { 184203004Sgshapiro if (uid != 0) 185203004Sgshapiro { 186203004Sgshapiro r = sm_semsetowner(semid, uid, gid, 0660); 187203004Sgshapiro if (r < 0) 188203004Sgshapiro { 189203004Sgshapiro perror("sm_semsetowner failed"); 190203004Sgshapiro return -1; 191203004Sgshapiro } 192203004Sgshapiro r = drop_priv(uid, gid); 193203004Sgshapiro if (r < 0) 194203004Sgshapiro { 195203004Sgshapiro perror("drop_priv owner failed"); 196203004Sgshapiro return -1; 197203004Sgshapiro } 198203004Sgshapiro } 199203004Sgshapiro 200147078Sgshapiro /* just in case someone kills the program... */ 201147078Sgshapiro semid_c = semid; 202147078Sgshapiro (void) sm_signal(SIGHUP, sem_cleanup); 203147078Sgshapiro (void) sm_signal(SIGINT, sem_cleanup); 204147078Sgshapiro (void) sm_signal(SIGTERM, sem_cleanup); 205147078Sgshapiro 206147078Sgshapiro delay(1, "parent: acquire 1"); 207147078Sgshapiro cnt = 0; 208147078Sgshapiro do 209147078Sgshapiro { 210147078Sgshapiro r = sm_sem_acq(semid, 0, 0); 211147078Sgshapiro if (r < 0) 212147078Sgshapiro { 213147078Sgshapiro sleep(1); 214147078Sgshapiro ++cnt; 215147078Sgshapiro } 216147078Sgshapiro } while (r < 0 && cnt <= MAX_CNT); 217147078Sgshapiro SM_TEST(r >= 0); 218147078Sgshapiro if (r < 0) 219147078Sgshapiro return r; 220147078Sgshapiro 221147078Sgshapiro delay(3, "parent: release 1"); 222147078Sgshapiro cnt = 0; 223147078Sgshapiro do 224147078Sgshapiro { 225147078Sgshapiro r = sm_sem_rel(semid, 0, 0); 226147078Sgshapiro if (r < 0) 227147078Sgshapiro { 228147078Sgshapiro sleep(1); 229147078Sgshapiro ++cnt; 230147078Sgshapiro } 231147078Sgshapiro } while (r < 0 && cnt <= MAX_CNT); 232147078Sgshapiro SM_TEST(r >= 0); 233147078Sgshapiro if (r < 0) 234147078Sgshapiro return r; 235147078Sgshapiro 236147078Sgshapiro delay(1, "parent: getval"); 237147078Sgshapiro cnt = 0; 238147078Sgshapiro do 239147078Sgshapiro { 240147078Sgshapiro r = sm_sem_get(semid, 0); 241147078Sgshapiro if (r <= 0) 242147078Sgshapiro { 243147078Sgshapiro sleep(1); 244147078Sgshapiro ++cnt; 245147078Sgshapiro } 246147078Sgshapiro } while (r <= 0 && cnt <= MAX_CNT); 247147078Sgshapiro SM_TEST(r > 0); 248147078Sgshapiro if (r <= 0) 249147078Sgshapiro return r; 250147078Sgshapiro 251147078Sgshapiro delay(1, "parent: acquire 2"); 252147078Sgshapiro cnt = 0; 253147078Sgshapiro do 254147078Sgshapiro { 255147078Sgshapiro r = sm_sem_acq(semid, 0, 0); 256147078Sgshapiro if (r < 0) 257147078Sgshapiro { 258147078Sgshapiro sleep(1); 259147078Sgshapiro ++cnt; 260147078Sgshapiro } 261147078Sgshapiro } while (r < 0 && cnt <= MAX_CNT); 262147078Sgshapiro SM_TEST(r >= 0); 263147078Sgshapiro if (r < 0) 264147078Sgshapiro return r; 265147078Sgshapiro 266147078Sgshapiro cnt = 0; 267147078Sgshapiro do 268147078Sgshapiro { 269147078Sgshapiro r = sm_sem_rel(semid, 0, 0); 270147078Sgshapiro if (r < 0) 271147078Sgshapiro { 272147078Sgshapiro sleep(1); 273147078Sgshapiro ++cnt; 274147078Sgshapiro } 275147078Sgshapiro } while (r < 0 && cnt <= MAX_CNT); 276147078Sgshapiro SM_TEST(r >= 0); 277147078Sgshapiro if (r < 0) 278147078Sgshapiro return r; 279147078Sgshapiro } 280147078Sgshapiro else 281147078Sgshapiro { 282147078Sgshapiro delay(1, "child: acquire 1"); 283147078Sgshapiro cnt = 0; 284147078Sgshapiro do 285147078Sgshapiro { 286147078Sgshapiro r = sm_sem_acq(semid, 0, 0); 287147078Sgshapiro if (r < 0) 288147078Sgshapiro { 289147078Sgshapiro sleep(1); 290147078Sgshapiro ++cnt; 291147078Sgshapiro } 292147078Sgshapiro } while (r < 0 && cnt <= MAX_CNT); 293147078Sgshapiro SM_TEST(r >= 0); 294147078Sgshapiro if (r < 0) 295147078Sgshapiro return r; 296147078Sgshapiro 297147078Sgshapiro delay(1, "child: release 1"); 298147078Sgshapiro cnt = 0; 299147078Sgshapiro do 300147078Sgshapiro { 301147078Sgshapiro r = sm_sem_rel(semid, 0, 0); 302147078Sgshapiro if (r < 0) 303147078Sgshapiro { 304147078Sgshapiro sleep(1); 305147078Sgshapiro ++cnt; 306147078Sgshapiro } 307147078Sgshapiro } while (r < 0 && cnt <= MAX_CNT); 308147078Sgshapiro SM_TEST(r >= 0); 309147078Sgshapiro if (r < 0) 310147078Sgshapiro return r; 311147078Sgshapiro 312147078Sgshapiro } 313147078Sgshapiro if (owner) 314147078Sgshapiro return sm_sem_stop(semid); 315147078Sgshapiro return 0; 316147078Sgshapiro} 317147078Sgshapiro 318147078Sgshapiroint 319147078Sgshapiromain(argc, argv) 320147078Sgshapiro int argc; 321147078Sgshapiro char *argv[]; 322147078Sgshapiro{ 323147078Sgshapiro bool interactive = false; 324147078Sgshapiro bool owner = false; 325203004Sgshapiro int ch, r; 326203004Sgshapiro uid_t uid; 327203004Sgshapiro gid_t gid; 328147078Sgshapiro 329203004Sgshapiro uid = 0; 330203004Sgshapiro gid = 0; 331203004Sgshapiro r = 0; 332203004Sgshapiro 333203004Sgshapiro# define OPTIONS "iog:u:" 334147078Sgshapiro while ((ch = getopt(argc, argv, OPTIONS)) != -1) 335147078Sgshapiro { 336147078Sgshapiro switch ((char) ch) 337147078Sgshapiro { 338203004Sgshapiro case 'g': 339203004Sgshapiro gid = (gid_t)strtoul(optarg, 0, 0); 340203004Sgshapiro break; 341203004Sgshapiro 342147078Sgshapiro case 'i': 343147078Sgshapiro interactive = true; 344147078Sgshapiro break; 345147078Sgshapiro 346203004Sgshapiro case 'u': 347203004Sgshapiro uid = (uid_t)strtoul(optarg, 0, 0); 348203004Sgshapiro break; 349203004Sgshapiro 350147078Sgshapiro case 'o': 351147078Sgshapiro owner = true; 352147078Sgshapiro break; 353147078Sgshapiro 354147078Sgshapiro default: 355147078Sgshapiro break; 356147078Sgshapiro } 357147078Sgshapiro } 358147078Sgshapiro 359147078Sgshapiro if (interactive) 360147078Sgshapiro r = seminter(owner); 361147078Sgshapiro else 362147078Sgshapiro { 363147078Sgshapiro pid_t pid; 364147078Sgshapiro 365147078Sgshapiro printf("This test takes about 8 seconds.\n"); 366157001Sgshapiro printf("If it takes longer than 30 seconds, please interrupt it\n"); 367147078Sgshapiro printf("and compile again without semaphore support, i.e.,"); 368147078Sgshapiro printf("-DSM_CONF_SEM=0\n"); 369147078Sgshapiro if ((pid = fork()) < 0) 370147078Sgshapiro { 371147078Sgshapiro perror("fork failed\n"); 372147078Sgshapiro return -1; 373147078Sgshapiro } 374147078Sgshapiro 375147078Sgshapiro sm_test_begin(argc, argv, "test semaphores"); 376147078Sgshapiro if (pid == 0) 377147078Sgshapiro { 378147078Sgshapiro /* give the parent the chance to setup data */ 379147078Sgshapiro sleep(1); 380203004Sgshapiro r = semtest(false, uid, gid); 381147078Sgshapiro } 382147078Sgshapiro else 383147078Sgshapiro { 384203004Sgshapiro r = semtest(true, uid, gid); 385147078Sgshapiro } 386147078Sgshapiro SM_TEST(r == 0); 387147078Sgshapiro return sm_test_end(); 388147078Sgshapiro } 389147078Sgshapiro return r; 390147078Sgshapiro} 391147078Sgshapiro#else /* SM_CONF_SEM */ 392147078Sgshapiroint 393147078Sgshapiromain(argc, argv) 394147078Sgshapiro int argc; 395147078Sgshapiro char *argv[]; 396147078Sgshapiro{ 397147078Sgshapiro printf("No support for semaphores configured on this machine\n"); 398147078Sgshapiro return 0; 399147078Sgshapiro} 400147078Sgshapiro#endif /* SM_CONF_SEM */ 401