190792Sgshapiro/*
2261370Sgshapiro * Copyright (c) 2000-2001, 2003, 2005 Proofpoint, Inc. and its suppliers.
390792Sgshapiro *      All rights reserved.
490792Sgshapiro *
590792Sgshapiro * By using this file, you agree to the terms and conditions set
690792Sgshapiro * forth in the LICENSE file which can be found at the top level of
790792Sgshapiro * the sendmail distribution.
890792Sgshapiro */
990792Sgshapiro
1090792Sgshapiro#include <sm/gen.h>
11266711SgshapiroSM_RCSID("@(#)$Id: shm.c,v 1.20 2013-11-22 20:51:43 ca Exp $")
1290792Sgshapiro
1390792Sgshapiro#if SM_CONF_SHM
1490792Sgshapiro# include <stdlib.h>
1590792Sgshapiro# include <unistd.h>
1690792Sgshapiro# include <errno.h>
17157001Sgshapiro# include <sm/string.h>
1890792Sgshapiro# include <sm/shm.h>
1990792Sgshapiro
20120256Sgshapiro
2190792Sgshapiro/*
2290792Sgshapiro**  SM_SHMSTART -- initialize shared memory segment.
2390792Sgshapiro**
2490792Sgshapiro**	Parameters:
2590792Sgshapiro**		key -- key for shared memory.
2690792Sgshapiro**		size -- size of segment.
2790792Sgshapiro**		shmflag -- initial flags.
2890792Sgshapiro**		shmid -- pointer to return id.
2990792Sgshapiro**		owner -- create segment.
3090792Sgshapiro**
3190792Sgshapiro**	Returns:
3290792Sgshapiro**		pointer to shared memory segment,
3390792Sgshapiro**		NULL on failure.
3490792Sgshapiro**
3590792Sgshapiro**	Side Effects:
3690792Sgshapiro**		attaches shared memory segment.
3790792Sgshapiro*/
3890792Sgshapiro
3990792Sgshapirovoid *
4090792Sgshapirosm_shmstart(key, size, shmflg, shmid, owner)
4190792Sgshapiro	key_t key;
4290792Sgshapiro	int size;
4390792Sgshapiro	int shmflg;
4490792Sgshapiro	int *shmid;
4590792Sgshapiro	bool owner;
4690792Sgshapiro{
4790792Sgshapiro	int save_errno;
4890792Sgshapiro	void *shm = SM_SHM_NULL;
4990792Sgshapiro
5090792Sgshapiro	/* default: user/group accessible */
5190792Sgshapiro	if (shmflg == 0)
5290792Sgshapiro		shmflg = SHM_R|SHM_W|(SHM_R>>3)|(SHM_W>>3);
5390792Sgshapiro	if (owner)
5490792Sgshapiro		shmflg |= IPC_CREAT|IPC_EXCL;
5590792Sgshapiro	*shmid = shmget(key, size, shmflg);
5690792Sgshapiro	if (*shmid < 0)
5790792Sgshapiro		goto error;
5890792Sgshapiro
5990792Sgshapiro	shm = shmat(*shmid, (void *) 0, 0);
6090792Sgshapiro	if (shm == SM_SHM_NULL)
6190792Sgshapiro		goto error;
6290792Sgshapiro
6390792Sgshapiro	return shm;
6490792Sgshapiro
6590792Sgshapiro  error:
6690792Sgshapiro	save_errno = errno;
6790792Sgshapiro	if (shm != SM_SHM_NULL || *shmid >= 0)
6890792Sgshapiro		sm_shmstop(shm, *shmid, owner);
6990792Sgshapiro	*shmid = SM_SHM_NO_ID;
7090792Sgshapiro	errno = save_errno;
7190792Sgshapiro	return (void *) 0;
7290792Sgshapiro}
7390792Sgshapiro
74120256Sgshapiro
7590792Sgshapiro/*
7690792Sgshapiro**  SM_SHMSTOP -- stop using shared memory segment.
7790792Sgshapiro**
7890792Sgshapiro**	Parameters:
7990792Sgshapiro**		shm -- pointer to shared memory.
8090792Sgshapiro**		shmid -- id.
8190792Sgshapiro**		owner -- delete segment.
8290792Sgshapiro**
8390792Sgshapiro**	Returns:
8490792Sgshapiro**		0 on success.
8590792Sgshapiro**		< 0 on failure.
8690792Sgshapiro**
8790792Sgshapiro**	Side Effects:
8890792Sgshapiro**		detaches (and maybe removes) shared memory segment.
8990792Sgshapiro*/
9090792Sgshapiro
91120256Sgshapiro
9290792Sgshapiroint
9390792Sgshapirosm_shmstop(shm, shmid, owner)
9490792Sgshapiro	void *shm;
9590792Sgshapiro	int shmid;
9690792Sgshapiro	bool owner;
9790792Sgshapiro{
9890792Sgshapiro	int r;
9990792Sgshapiro
10090792Sgshapiro	if (shm != SM_SHM_NULL && (r = shmdt(shm)) < 0)
10190792Sgshapiro		return r;
10290792Sgshapiro	if (owner && shmid >= 0 && (r = shmctl(shmid, IPC_RMID, NULL)) < 0)
10390792Sgshapiro		return r;
10490792Sgshapiro	return 0;
10590792Sgshapiro}
106120256Sgshapiro
107120256Sgshapiro
108147078Sgshapiro/*
109147078Sgshapiro**  SM_SHMSETOWNER -- set owner/group/mode of shared memory segment.
110147078Sgshapiro**
111147078Sgshapiro**	Parameters:
112147078Sgshapiro**		shmid -- id.
113147078Sgshapiro**		uid -- uid to use
114147078Sgshapiro**		gid -- gid to use
115147078Sgshapiro**		mode -- mode to use
116147078Sgshapiro**
117147078Sgshapiro**	Returns:
118147078Sgshapiro**		0 on success.
119147078Sgshapiro**		< 0 on failure.
120147078Sgshapiro*/
121147078Sgshapiro
122147078Sgshapiroint
123147078Sgshapirosm_shmsetowner(shmid, uid, gid, mode)
124147078Sgshapiro	int shmid;
125147078Sgshapiro	uid_t uid;
126147078Sgshapiro	gid_t gid;
127147078Sgshapiro	mode_t mode;
128147078Sgshapiro{
129147078Sgshapiro	int r;
130147078Sgshapiro	struct shmid_ds shmid_ds;
131147078Sgshapiro
132147078Sgshapiro	memset(&shmid_ds, 0, sizeof(shmid_ds));
133147078Sgshapiro	if ((r = shmctl(shmid, IPC_STAT, &shmid_ds)) < 0)
134147078Sgshapiro		return r;
135147078Sgshapiro	shmid_ds.shm_perm.uid = uid;
136147078Sgshapiro	shmid_ds.shm_perm.gid = gid;
137147078Sgshapiro	shmid_ds.shm_perm.mode = mode;
138147078Sgshapiro	if ((r = shmctl(shmid, IPC_SET, &shmid_ds)) < 0)
139147078Sgshapiro		return r;
140147078Sgshapiro	return 0;
141147078Sgshapiro}
14290792Sgshapiro#endif /* SM_CONF_SHM */
143