Release 950727
[wine/multimedia.git] / ipc / shm_main_blk.c
blob3fb798e6f50681c9d75f7b2c588bc0dad7394835
1 /***************************************************************************
2 * Copyright 1995, Technion, Israel Institute of Technology
3 * Electrical Eng, Software Lab.
4 * Author: Michael Veksler.
5 ***************************************************************************
6 * File: shm_main_blk.c
7 * Purpose: Main Wine's shared memory block
8 ***************************************************************************
9 */
10 #define inline __inline__
11 #include <sys/sem.h>
12 #include <stdio.h>
13 #include <time.h>
14 #include <assert.h>
15 #include <unistd.h>
16 #include <errno.h>
17 #include <signal.h>
18 #include <stddebug.h>
19 #include <debug.h>
20 #include "shm_fragment.h"
21 #include "shm_block.h"
22 #include "shm_main_blk.h"
23 #include "shm_semaph.h"
25 #define WineKey ( 'W'+((int)'i'<<8)+((int)'n'<<16)+((int)'e'<<24) )
26 #define SHM_KEY_RANGE 8
28 /* main block (set during initialization) */
29 struct shm_main_block *main_block=NULL;
30 static char *shm_header="Wine - Windows emulator DDE mechanism";
31 static int main_shm_id;
33 static void shm_main_refresh();
35 /* for debugging only */
36 static void print_perm(struct ipc_perm *perm)
38 printf("Permission:\n");
39 printf("\tKey=%d, mode=%03o, sequence #=%d\n",
40 (int)perm->key,perm->mode, perm->seq);
41 printf("\towner: uid=%d, gid=%d ;" ,perm->uid, perm->gid);
42 printf(" creator: uid=%d, gid=%d\n",perm->cuid,perm->cgid);
45 /* for debugging only */
46 /* print_shm_info: print shared memory descriptor info */
47 static void print_shm_info(int shm_id)
49 struct shmid_ds ds;
50 shmctl(shm_id, IPC_STAT, &ds );
52 printf("shm_id=%d, Size=0x%08x , Number of attaches=%d\n",
53 shm_id, ds.shm_segsz, (int)ds.shm_nattch);
54 if (ds.shm_atime)
55 printf("Last attach=%s",ctime(&ds.shm_atime));
56 if (ds.shm_dtime)
57 printf("Last detach=%s",ctime(&ds.shm_dtime));
58 printf("Last change=%s",ctime(&ds.shm_ctime));
59 printf("pid: creator=%d, last operator=%d\n",
60 (int)ds.shm_cpid,(int)ds.shm_lpid);
61 print_perm( &ds.shm_perm);
65 int proc_exist(__pid_t pid)
67 if ( kill(pid,0) == 0) /* dummy signal to test existence */
68 return 1;
69 else if (errno==ESRCH) /* "no such process" */
70 return 0;
71 else
72 return 1;
75 /* setup a new main shm block (only construct a shm block object). */
76 static void shm_setup_main_block()
78 dprintf_shm(stddeb,"creating data structure\n");
79 main_block->build_lock=1;
80 strcpy(main_block->magic, shm_header);
82 shm_setup_block(&main_block->block,sizeof(*main_block),SHM_MINBLOCK);
84 dde_proc_init(main_block->proc);
85 ATOM_GlobalInit();
86 shm_sem_init(&main_block->sem);
88 /* main block set and data structure is stable now */
89 main_block->build_lock=0;
92 /* Delete everything related to main_block */
93 void shm_delete_all(int shmid)
95 int proc_idx;
97 if (shmid == -1)
98 shmid= main_shm_id;
100 shmctl( shmid, IPC_RMID, NULL);
102 for (proc_idx= 0 ; proc_idx < DDE_PROCS ; proc_idx++)
103 dde_proc_done( &main_block->proc[proc_idx] );
105 shm_sem_done(&main_block->sem);
106 shmdt( (void *) main_block);
107 main_block= NULL;
110 int DDE_no_of_attached()
112 struct shmid_ds shm_info;
114 if (shmctl(main_shm_id, IPC_STAT, &shm_info) == -1)
115 return -1;
117 return shm_info.shm_nattch;
120 ** Test if shm_id is MainBlock and attach it (if it is),
121 ** Return 1 if ok, 0 otherwise.
123 static int attach_MainBlock(int shm_id)
125 struct shmid_ds shm_info;
127 if (shmctl(shm_id, IPC_STAT, &shm_info) == -1)
128 return 0;
130 /* Make sure we don't work on somebody else's block */
131 if (shm_info.shm_perm.cuid != getuid()) { /* creator is not me */
132 dprintf_shm(stddeb,"Creator is not me!\n");
133 return 0;
136 dprintf_shm(stddeb,"shared memory exist, attaching anywhere\n");
137 main_block=(struct shm_main_block *)shmat(shm_id, 0, 0);
138 if ( (int)main_block==-1) {
139 dprintf_shm(stddeb,"Attach failed\n");
140 return 0;
143 if (strcmp(main_block->magic, shm_header) != 0) {
144 dprintf_shm(stddeb,"Detaching, wrong magic\n");
145 shmdt((void *)main_block);
146 return 0;
149 if (debugging_shm)
150 print_shm_info(shm_id);
152 /* Is it an old unused block ? */
153 if (shm_info.shm_nattch == 0) {
154 dprintf_shm(stddeb,"No attaches, deleting old data\n");
155 shm_delete_all(shm_id);
156 return 0;
159 /* Wait for data structure to stabilize */
160 while (main_block->build_lock)
161 usleep(10000);
163 main_shm_id= shm_id;
165 shm_main_refresh();
166 return 1;
169 /* (Function used by the constructor)
170 * Try to get existing shared memory with key="Wine", size=SHM_MINBLOCK
171 * complete user permission.
172 * If such block is found - return true (1), else return false (0)
174 static int shm_locate_MainBlock(key_t shm_key)
176 int shm_id; /* Descriptor to this shared memory */
177 int i;
179 dprintf_shm(stddeb,"shm_locate_MainBlock: trying to attach, key=0x%x\n",
180 shm_key);
181 for (i=0 ; i < SHM_KEY_RANGE ; i++) {
182 dprintf_shm(stddeb,"iteration=%d\n", i);
184 shm_id= shmget ( shm_key+i, SHM_MINBLOCK ,0700);
186 if (shm_id != -1) {
187 if ( attach_MainBlock(shm_id) ) {
188 return 1; /* success! */
190 } else {
191 switch(errno) {
192 case EIDRM: /* segment destroyed */
193 case EACCES: /* no user permision */
194 break;
196 case ENOMEM: /* no free memory */
197 case ENOENT: /* this key does not exist */
198 default :
199 dprintf_shm(stddeb,"shmget failed, errno=%d, %s\n",
200 errno, strerror(errno) );
201 return 0; /* Failed */
203 } /* if .. else */
204 } /* for */
205 return 0;
208 /* (Function used by the constructor)
209 * Try to allocate new shared memory with key="Wine", size=SHM_MINBLOCK
210 * with complete user permission.
211 * If allocation succeeds - return true (1), else return false (0)
213 static int shm_create_MainBlock(key_t MainShmKey)
215 int shm_id;
216 int flags= 0700 | IPC_CREAT | IPC_EXCL;
217 int i;
219 dprintf_shm(stddeb,"creating shared memory\n");
221 /* try to allocate shared memory with key="Wine", size=SHM_MINBLOCK, */
222 /* complete user permission */
223 for (i=0 ; i < SHM_KEY_RANGE ; i++) {
224 shm_id= shmget ( (key_t) MainShmKey, SHM_MINBLOCK, flags);
225 if (shm_id != -1)
226 break;
228 if (shm_id == -1) {
229 dprintf_shm(stddeb,"failed to create shared memory\n");
230 return 0;
232 dprintf_shm(stddeb,"shared memory created, attaching\n");
233 main_block=(struct shm_main_block*) shmat(shm_id, 0,0);
234 if (debugging_shm)
235 print_shm_info(shm_id);
236 main_shm_id= shm_id;
237 shm_setup_main_block();
238 dde_wnd_setup();
239 return 1;
243 /* link to the dde shared memory block */
244 /* RETURN: 0 on success, non zero on failure */
245 int shm_init(void)
247 if ( !shm_locate_MainBlock(WineKey)
248 && !shm_create_MainBlock(WineKey)) {
249 fflush(stdout);
250 fprintf(stderr,"shm_init: failed to init main shm block\n");
251 exit(1);
254 dde_proc_add(main_block->proc);
255 return 0;
258 static void shm_main_refresh()
260 int proc_idx;
262 for (proc_idx= 0 ; proc_idx < DDE_PROCS ; proc_idx++)
263 dde_proc_refresh( &main_block->proc[proc_idx] );