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