1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
/*
* Copyright (c) 2000-2001, 2003, 2005 Proofpoint, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*/
#include <sm/gen.h>
SM_RCSID("@(#)$Id: shm.c,v 1.20 2013-11-22 20:51:43 ca Exp $")
#if SM_CONF_SHM
# include <stdlib.h>
# include <unistd.h>
# include <errno.h>
# include <sm/string.h>
# include <sm/conf.h>
# include <sm/shm.h>
/*
** SM_SHMSTART -- initialize shared memory segment.
**
** Parameters:
** key -- key for shared memory.
** size -- size of segment.
** shmflag -- initial flags.
** shmid -- pointer to return id.
** owner -- create segment.
**
** Returns:
** pointer to shared memory segment,
** NULL on failure.
**
** Side Effects:
** attaches shared memory segment.
*/
void *
sm_shmstart(key, size, shmflg, shmid, owner)
key_t key;
int size;
int shmflg;
int *shmid;
bool owner;
{
int save_errno;
void *shm = SM_SHM_NULL;
/* default: user/group accessible */
if (shmflg == 0)
shmflg = SHM_R|SHM_W|(SHM_R>>3)|(SHM_W>>3);
if (owner)
shmflg |= IPC_CREAT|IPC_EXCL;
*shmid = shmget(key, size, shmflg);
if (*shmid < 0)
goto error;
shm = shmat(*shmid, (void *) 0, 0);
if (shm == SM_SHM_NULL)
goto error;
return shm;
error:
save_errno = errno;
if (shm != SM_SHM_NULL || *shmid >= 0)
sm_shmstop(shm, *shmid, owner);
*shmid = SM_SHM_NO_ID;
errno = save_errno;
return (void *) 0;
}
/*
** SM_SHMSTOP -- stop using shared memory segment.
**
** Parameters:
** shm -- pointer to shared memory.
** shmid -- id.
** owner -- delete segment.
**
** Returns:
** 0 on success.
** < 0 on failure.
**
** Side Effects:
** detaches (and maybe removes) shared memory segment.
*/
int
sm_shmstop(shm, shmid, owner)
void *shm;
int shmid;
bool owner;
{
int r;
if (shm != SM_SHM_NULL && (r = shmdt(shm)) < 0)
return r;
if (owner && shmid >= 0 && (r = shmctl(shmid, IPC_RMID, NULL)) < 0)
return r;
return 0;
}
/*
** SM_SHMSETOWNER -- set owner/group/mode of shared memory segment.
**
** Parameters:
** shmid -- id.
** uid -- uid to use
** gid -- gid to use
** mode -- mode to use
**
** Returns:
** 0 on success.
** < 0 on failure.
*/
#ifdef __STDC__
int
sm_shmsetowner(int shmid, uid_t uid, gid_t gid, MODE_T mode)
#else /* __STDC__ */
int
sm_shmsetowner(shmid, uid, gid, mode)
int shmid;
uid_t uid;
gid_t gid;
MODE_T mode;
#endif /* __STDC__ */
{
int r;
struct shmid_ds shmid_ds;
memset(&shmid_ds, 0, sizeof(shmid_ds));
if ((r = shmctl(shmid, IPC_STAT, &shmid_ds)) < 0)
return r;
shmid_ds.shm_perm.uid = uid;
shmid_ds.shm_perm.gid = gid;
shmid_ds.shm_perm.mode = mode;
if ((r = shmctl(shmid, IPC_SET, &shmid_ds)) < 0)
return r;
return 0;
}
#endif /* SM_CONF_SHM */
|