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