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