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: sem.c,v 1.15 2013-11-22 20:51:43 ca Exp $") 1213d88268SGregory Neil Shapiro 1313d88268SGregory Neil Shapiro #if SM_CONF_SEM 1413d88268SGregory Neil Shapiro # include <stdlib.h> 1513d88268SGregory Neil Shapiro # include <unistd.h> 169bd497b8SGregory Neil Shapiro # include <sm/string.h> 1713d88268SGregory Neil Shapiro # include <sm/sem.h> 1813d88268SGregory Neil Shapiro # include <sm/heap.h> 194e4196cbSGregory Neil Shapiro # include <errno.h> 2013d88268SGregory Neil Shapiro 2113d88268SGregory Neil Shapiro /* 2213d88268SGregory Neil Shapiro ** SM_SEM_START -- initialize semaphores 2313d88268SGregory Neil Shapiro ** 2413d88268SGregory Neil Shapiro ** Parameters: 2513d88268SGregory Neil Shapiro ** key -- key for semaphores. 2613d88268SGregory Neil Shapiro ** nsem -- number of semaphores. 2713d88268SGregory Neil Shapiro ** semflg -- flag for semget(), if 0, use a default. 2813d88268SGregory Neil Shapiro ** owner -- create semaphores. 2913d88268SGregory Neil Shapiro ** 3013d88268SGregory Neil Shapiro ** Returns: 3113d88268SGregory Neil Shapiro ** id for semaphores. 3213d88268SGregory Neil Shapiro ** < 0 on failure. 3313d88268SGregory Neil Shapiro */ 3413d88268SGregory Neil Shapiro 3513d88268SGregory Neil Shapiro int 3613d88268SGregory Neil Shapiro sm_sem_start(key, nsem, semflg, owner) 3713d88268SGregory Neil Shapiro key_t key; 3813d88268SGregory Neil Shapiro int nsem; 3913d88268SGregory Neil Shapiro int semflg; 4013d88268SGregory Neil Shapiro bool owner; 4113d88268SGregory Neil Shapiro { 424e4196cbSGregory Neil Shapiro int semid, i, err; 4313d88268SGregory Neil Shapiro unsigned short *semvals; 4413d88268SGregory Neil Shapiro 4513d88268SGregory Neil Shapiro semvals = NULL; 4613d88268SGregory Neil Shapiro if (semflg == 0) 4713d88268SGregory Neil Shapiro semflg = (SEM_A|SEM_R)|((SEM_A|SEM_R) >> 3); 4813d88268SGregory Neil Shapiro if (owner) 4913d88268SGregory Neil Shapiro semflg |= IPC_CREAT|IPC_EXCL; 5013d88268SGregory Neil Shapiro semid = semget(key, nsem, semflg); 5113d88268SGregory Neil Shapiro if (semid < 0) 5213d88268SGregory Neil Shapiro goto error; 5313d88268SGregory Neil Shapiro 5413d88268SGregory Neil Shapiro if (owner) 5513d88268SGregory Neil Shapiro { 5613d88268SGregory Neil Shapiro union semun semarg; 5713d88268SGregory Neil Shapiro 5813d88268SGregory Neil Shapiro semvals = (unsigned short *) sm_malloc(nsem * sizeof semvals); 5913d88268SGregory Neil Shapiro if (semvals == NULL) 6013d88268SGregory Neil Shapiro goto error; 6113d88268SGregory Neil Shapiro semarg.array = semvals; 6213d88268SGregory Neil Shapiro 6313d88268SGregory Neil Shapiro /* initialize semaphore values to be available */ 6413d88268SGregory Neil Shapiro for (i = 0; i < nsem; i++) 6513d88268SGregory Neil Shapiro semvals[i] = 1; 6613d88268SGregory Neil Shapiro if (semctl(semid, 0, SETALL, semarg) < 0) 6713d88268SGregory Neil Shapiro goto error; 6813d88268SGregory Neil Shapiro } 6913d88268SGregory Neil Shapiro return semid; 7013d88268SGregory Neil Shapiro 7113d88268SGregory Neil Shapiro error: 724e4196cbSGregory Neil Shapiro err = errno; 7313d88268SGregory Neil Shapiro if (semvals != NULL) 7413d88268SGregory Neil Shapiro sm_free(semvals); 7513d88268SGregory Neil Shapiro if (semid >= 0) 7613d88268SGregory Neil Shapiro sm_sem_stop(semid); 774e4196cbSGregory Neil Shapiro return (err > 0) ? (0 - err) : -1; 7813d88268SGregory Neil Shapiro } 7913d88268SGregory Neil Shapiro 8013d88268SGregory Neil Shapiro /* 8113d88268SGregory Neil Shapiro ** SM_SEM_STOP -- stop using semaphores. 8213d88268SGregory Neil Shapiro ** 8313d88268SGregory Neil Shapiro ** Parameters: 8413d88268SGregory Neil Shapiro ** semid -- id for semaphores. 8513d88268SGregory Neil Shapiro ** 8613d88268SGregory Neil Shapiro ** Returns: 8713d88268SGregory Neil Shapiro ** 0 on success. 8813d88268SGregory Neil Shapiro ** < 0 on failure. 8913d88268SGregory Neil Shapiro */ 9013d88268SGregory Neil Shapiro 9113d88268SGregory Neil Shapiro int 9213d88268SGregory Neil Shapiro sm_sem_stop(semid) 9313d88268SGregory Neil Shapiro int semid; 9413d88268SGregory Neil Shapiro { 9513d88268SGregory Neil Shapiro return semctl(semid, 0, IPC_RMID, NULL); 9613d88268SGregory Neil Shapiro } 9713d88268SGregory Neil Shapiro 9813d88268SGregory Neil Shapiro /* 9913d88268SGregory Neil Shapiro ** SM_SEM_ACQ -- acquire semaphore. 10013d88268SGregory Neil Shapiro ** 10113d88268SGregory Neil Shapiro ** Parameters: 10213d88268SGregory Neil Shapiro ** semid -- id for semaphores. 10313d88268SGregory Neil Shapiro ** semnum -- number of semaphore. 10413d88268SGregory Neil Shapiro ** timeout -- how long to wait for operation to succeed. 10513d88268SGregory Neil Shapiro ** 10613d88268SGregory Neil Shapiro ** Returns: 10713d88268SGregory Neil Shapiro ** 0 on success. 10813d88268SGregory Neil Shapiro ** < 0 on failure. 10913d88268SGregory Neil Shapiro */ 11013d88268SGregory Neil Shapiro 11113d88268SGregory Neil Shapiro int 11213d88268SGregory Neil Shapiro sm_sem_acq(semid, semnum, timeout) 11313d88268SGregory Neil Shapiro int semid; 11413d88268SGregory Neil Shapiro int semnum; 11513d88268SGregory Neil Shapiro int timeout; 11613d88268SGregory Neil Shapiro { 11713d88268SGregory Neil Shapiro int r; 11813d88268SGregory Neil Shapiro struct sembuf semops[1]; 11913d88268SGregory Neil Shapiro 12013d88268SGregory Neil Shapiro semops[0].sem_num = semnum; 12113d88268SGregory Neil Shapiro semops[0].sem_op = -1; 12213d88268SGregory Neil Shapiro semops[0].sem_flg = SEM_UNDO | 12313d88268SGregory Neil Shapiro (timeout != SM_TIME_FOREVER ? 0 : IPC_NOWAIT); 12413d88268SGregory Neil Shapiro if (timeout == SM_TIME_IMMEDIATE || timeout == SM_TIME_FOREVER) 12513d88268SGregory Neil Shapiro return semop(semid, semops, 1); 12613d88268SGregory Neil Shapiro do 12713d88268SGregory Neil Shapiro { 12813d88268SGregory Neil Shapiro r = semop(semid, semops, 1); 12913d88268SGregory Neil Shapiro if (r == 0) 13013d88268SGregory Neil Shapiro return r; 13113d88268SGregory Neil Shapiro sleep(1); 13213d88268SGregory Neil Shapiro --timeout; 13313d88268SGregory Neil Shapiro } while (timeout > 0); 13413d88268SGregory Neil Shapiro return r; 13513d88268SGregory Neil Shapiro } 13613d88268SGregory Neil Shapiro 13713d88268SGregory Neil Shapiro /* 13813d88268SGregory Neil Shapiro ** SM_SEM_REL -- release semaphore. 13913d88268SGregory Neil Shapiro ** 14013d88268SGregory Neil Shapiro ** Parameters: 14113d88268SGregory Neil Shapiro ** semid -- id for semaphores. 14213d88268SGregory Neil Shapiro ** semnum -- number of semaphore. 14313d88268SGregory Neil Shapiro ** timeout -- how long to wait for operation to succeed. 14413d88268SGregory Neil Shapiro ** 14513d88268SGregory Neil Shapiro ** Returns: 14613d88268SGregory Neil Shapiro ** 0 on success. 14713d88268SGregory Neil Shapiro ** < 0 on failure. 14813d88268SGregory Neil Shapiro */ 14913d88268SGregory Neil Shapiro 15013d88268SGregory Neil Shapiro int 15113d88268SGregory Neil Shapiro sm_sem_rel(semid, semnum, timeout) 15213d88268SGregory Neil Shapiro int semid; 15313d88268SGregory Neil Shapiro int semnum; 15413d88268SGregory Neil Shapiro int timeout; 15513d88268SGregory Neil Shapiro { 15613d88268SGregory Neil Shapiro int r; 15713d88268SGregory Neil Shapiro struct sembuf semops[1]; 15813d88268SGregory Neil Shapiro 15913d88268SGregory Neil Shapiro #if PARANOID 16013d88268SGregory Neil Shapiro /* XXX should we check whether the value is already 0 ? */ 16113d88268SGregory Neil Shapiro SM_REQUIRE(sm_get_sem(semid, semnum) > 0); 162*5b0945b5SGregory Neil Shapiro #endif 16313d88268SGregory Neil Shapiro 16413d88268SGregory Neil Shapiro semops[0].sem_num = semnum; 16513d88268SGregory Neil Shapiro semops[0].sem_op = 1; 16613d88268SGregory Neil Shapiro semops[0].sem_flg = SEM_UNDO | 16713d88268SGregory Neil Shapiro (timeout != SM_TIME_FOREVER ? 0 : IPC_NOWAIT); 16813d88268SGregory Neil Shapiro if (timeout == SM_TIME_IMMEDIATE || timeout == SM_TIME_FOREVER) 16913d88268SGregory Neil Shapiro return semop(semid, semops, 1); 17013d88268SGregory Neil Shapiro do 17113d88268SGregory Neil Shapiro { 17213d88268SGregory Neil Shapiro r = semop(semid, semops, 1); 17313d88268SGregory Neil Shapiro if (r == 0) 17413d88268SGregory Neil Shapiro return r; 17513d88268SGregory Neil Shapiro sleep(1); 17613d88268SGregory Neil Shapiro --timeout; 17713d88268SGregory Neil Shapiro } while (timeout > 0); 17813d88268SGregory Neil Shapiro return r; 17913d88268SGregory Neil Shapiro } 18013d88268SGregory Neil Shapiro 18113d88268SGregory Neil Shapiro /* 18213d88268SGregory Neil Shapiro ** SM_SEM_GET -- get semaphore value. 18313d88268SGregory Neil Shapiro ** 18413d88268SGregory Neil Shapiro ** Parameters: 18513d88268SGregory Neil Shapiro ** semid -- id for semaphores. 18613d88268SGregory Neil Shapiro ** semnum -- number of semaphore. 18713d88268SGregory Neil Shapiro ** 18813d88268SGregory Neil Shapiro ** Returns: 18913d88268SGregory Neil Shapiro ** value of semaphore on success. 19013d88268SGregory Neil Shapiro ** < 0 on failure. 19113d88268SGregory Neil Shapiro */ 19213d88268SGregory Neil Shapiro 19313d88268SGregory Neil Shapiro int 19413d88268SGregory Neil Shapiro sm_sem_get(semid, semnum) 19513d88268SGregory Neil Shapiro int semid; 19613d88268SGregory Neil Shapiro int semnum; 19713d88268SGregory Neil Shapiro { 19813d88268SGregory Neil Shapiro int semval; 19913d88268SGregory Neil Shapiro 20013d88268SGregory Neil Shapiro if ((semval = semctl(semid, semnum, GETVAL, NULL)) < 0) 20113d88268SGregory Neil Shapiro return -1; 20213d88268SGregory Neil Shapiro return semval; 20313d88268SGregory Neil Shapiro } 2049bd497b8SGregory Neil Shapiro 2059bd497b8SGregory Neil Shapiro /* 2069bd497b8SGregory Neil Shapiro ** SM_SEMSETOWNER -- set owner/group/mode of semaphores. 2079bd497b8SGregory Neil Shapiro ** 2089bd497b8SGregory Neil Shapiro ** Parameters: 2099bd497b8SGregory Neil Shapiro ** semid -- id for semaphores. 2109bd497b8SGregory Neil Shapiro ** uid -- uid to use 2119bd497b8SGregory Neil Shapiro ** gid -- gid to use 2129bd497b8SGregory Neil Shapiro ** mode -- mode to use 2139bd497b8SGregory Neil Shapiro ** 2149bd497b8SGregory Neil Shapiro ** Returns: 2159bd497b8SGregory Neil Shapiro ** 0 on success. 2169bd497b8SGregory Neil Shapiro ** < 0 on failure. 2179bd497b8SGregory Neil Shapiro */ 2189bd497b8SGregory Neil Shapiro 2199bd497b8SGregory Neil Shapiro int 2209bd497b8SGregory Neil Shapiro sm_semsetowner(semid, uid, gid, mode) 2219bd497b8SGregory Neil Shapiro int semid; 2229bd497b8SGregory Neil Shapiro uid_t uid; 2239bd497b8SGregory Neil Shapiro gid_t gid; 2249bd497b8SGregory Neil Shapiro mode_t mode; 2259bd497b8SGregory Neil Shapiro { 2269bd497b8SGregory Neil Shapiro int r; 2279bd497b8SGregory Neil Shapiro struct semid_ds semidds; 2289bd497b8SGregory Neil Shapiro union semun { 2299bd497b8SGregory Neil Shapiro int val; 2309bd497b8SGregory Neil Shapiro struct semid_ds *buf; 2319bd497b8SGregory Neil Shapiro ushort *array; 2329bd497b8SGregory Neil Shapiro } arg; 2339bd497b8SGregory Neil Shapiro 2349bd497b8SGregory Neil Shapiro memset(&semidds, 0, sizeof(semidds)); 2359bd497b8SGregory Neil Shapiro arg.buf = &semidds; 2369bd497b8SGregory Neil Shapiro if ((r = semctl(semid, 1, IPC_STAT, arg)) < 0) 2379bd497b8SGregory Neil Shapiro return r; 2389bd497b8SGregory Neil Shapiro semidds.sem_perm.uid = uid; 2399bd497b8SGregory Neil Shapiro semidds.sem_perm.gid = gid; 2409bd497b8SGregory Neil Shapiro semidds.sem_perm.mode = mode; 2419bd497b8SGregory Neil Shapiro if ((r = semctl(semid, 1, IPC_SET, arg)) < 0) 2429bd497b8SGregory Neil Shapiro return r; 2439bd497b8SGregory Neil Shapiro return 0; 2449bd497b8SGregory Neil Shapiro } 24513d88268SGregory Neil Shapiro #endif /* SM_CONF_SEM */ 246