xref: /freebsd/contrib/sendmail/libsm/shm.c (revision 27c43fe1f3795622c5bd4bbfc465a29a800c0799)
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>
11 SM_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/shm.h>
19 
20 
21 /*
22 **  SM_SHMSTART -- initialize shared memory segment.
23 **
24 **	Parameters:
25 **		key -- key for shared memory.
26 **		size -- size of segment.
27 **		shmflag -- initial flags.
28 **		shmid -- pointer to return id.
29 **		owner -- create segment.
30 **
31 **	Returns:
32 **		pointer to shared memory segment,
33 **		NULL on failure.
34 **
35 **	Side Effects:
36 **		attaches shared memory segment.
37 */
38 
39 void *
40 sm_shmstart(key, size, shmflg, shmid, owner)
41 	key_t key;
42 	int size;
43 	int shmflg;
44 	int *shmid;
45 	bool owner;
46 {
47 	int save_errno;
48 	void *shm = SM_SHM_NULL;
49 
50 	/* default: user/group accessible */
51 	if (shmflg == 0)
52 		shmflg = SHM_R|SHM_W|(SHM_R>>3)|(SHM_W>>3);
53 	if (owner)
54 		shmflg |= IPC_CREAT|IPC_EXCL;
55 	*shmid = shmget(key, size, shmflg);
56 	if (*shmid < 0)
57 		goto error;
58 
59 	shm = shmat(*shmid, (void *) 0, 0);
60 	if (shm == SM_SHM_NULL)
61 		goto error;
62 
63 	return shm;
64 
65   error:
66 	save_errno = errno;
67 	if (shm != SM_SHM_NULL || *shmid >= 0)
68 		sm_shmstop(shm, *shmid, owner);
69 	*shmid = SM_SHM_NO_ID;
70 	errno = save_errno;
71 	return (void *) 0;
72 }
73 
74 
75 /*
76 **  SM_SHMSTOP -- stop using shared memory segment.
77 **
78 **	Parameters:
79 **		shm -- pointer to shared memory.
80 **		shmid -- id.
81 **		owner -- delete segment.
82 **
83 **	Returns:
84 **		0 on success.
85 **		< 0 on failure.
86 **
87 **	Side Effects:
88 **		detaches (and maybe removes) shared memory segment.
89 */
90 
91 
92 int
93 sm_shmstop(shm, shmid, owner)
94 	void *shm;
95 	int shmid;
96 	bool owner;
97 {
98 	int r;
99 
100 	if (shm != SM_SHM_NULL && (r = shmdt(shm)) < 0)
101 		return r;
102 	if (owner && shmid >= 0 && (r = shmctl(shmid, IPC_RMID, NULL)) < 0)
103 		return r;
104 	return 0;
105 }
106 
107 
108 /*
109 **  SM_SHMSETOWNER -- set owner/group/mode of shared memory segment.
110 **
111 **	Parameters:
112 **		shmid -- id.
113 **		uid -- uid to use
114 **		gid -- gid to use
115 **		mode -- mode to use
116 **
117 **	Returns:
118 **		0 on success.
119 **		< 0 on failure.
120 */
121 
122 int
123 sm_shmsetowner(shmid, uid, gid, mode)
124 	int shmid;
125 	uid_t uid;
126 	gid_t gid;
127 	mode_t mode;
128 {
129 	int r;
130 	struct shmid_ds shmid_ds;
131 
132 	memset(&shmid_ds, 0, sizeof(shmid_ds));
133 	if ((r = shmctl(shmid, IPC_STAT, &shmid_ds)) < 0)
134 		return r;
135 	shmid_ds.shm_perm.uid = uid;
136 	shmid_ds.shm_perm.gid = gid;
137 	shmid_ds.shm_perm.mode = mode;
138 	if ((r = shmctl(shmid, IPC_SET, &shmid_ds)) < 0)
139 		return r;
140 	return 0;
141 }
142 #endif /* SM_CONF_SHM */
143