]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/sendmail/libsm/shm.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / sendmail / libsm / shm.c
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.19 2005/07/14 22:34:28 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 */