1 /***************************************************************************
2 * Copyright 1995, Technion, Israel Institute of Technology
3 * Electrical Eng, Software Lab.
4 * Author: Michael Veksler.
5 ***************************************************************************
7 * Purpose: Main Wine's shared memory block
8 ***************************************************************************
12 #define inline __inline__
13 #include <sys/types.h>
21 #include "shm_fragment.h"
22 #include "shm_block.h"
23 #include "shm_main_blk.h"
24 #include "shm_semaph.h"
26 DEFAULT_DEBUG_CHANNEL(shm
)
28 #define WineKey ( 'W'+((int)'i'<<8)+((int)'n'<<16)+((int)'e'<<24) )
29 #define SHM_KEY_RANGE 8
31 /* main block (set during initialization) */
32 struct shm_main_block
*main_block
=NULL
;
33 static char *shm_header
="Wine - Windows emulator DDE mechanism";
34 static int main_shm_id
;
36 static void shm_main_refresh();
38 /* for debugging only */
39 static void print_perm(struct ipc_perm
*perm
)
41 printf("Permission:\n");
42 /* FIXME: not portable
43 printf("\tKey=%d, mode=%03o, sequence #=%d\n",
44 (int)perm->key,perm->mode, perm->seq);
46 printf("\towner: uid=%d, gid=%d ;" ,perm
->uid
, perm
->gid
);
47 printf(" creator: uid=%d, gid=%d\n",perm
->cuid
,perm
->cgid
);
50 /* for debugging only */
51 /* print_shm_info: print shared memory descriptor info */
52 static void print_shm_info(int shm_id
)
55 shmctl(shm_id
, IPC_STAT
, &ds
);
57 printf("shm_id=%d, Size=0x%08x , Number of attaches=%d\n",
58 shm_id
, ds
.shm_segsz
, (int)ds
.shm_nattch
);
60 printf("Last attach=%s",ctime(&ds
.shm_atime
));
62 printf("Last detach=%s",ctime(&ds
.shm_dtime
));
63 printf("Last change=%s",ctime(&ds
.shm_ctime
));
64 printf("pid: creator=%d, last operator=%d\n",
65 (int)ds
.shm_cpid
,(int)ds
.shm_lpid
);
66 print_perm( &ds
.shm_perm
);
70 int proc_exist(pid_t pid
)
72 if ( kill(pid
,0) == 0) /* dummy signal to test existence */
74 else if (errno
==ESRCH
) /* "no such process" */
80 /* setup a new main shm block (only construct a shm block object). */
81 static void shm_setup_main_block()
83 TRACE(shm
,"creating data structure\n");
84 main_block
->build_lock
=1;
85 strcpy(main_block
->magic
, shm_header
);
87 shm_setup_block(&main_block
->block
,sizeof(*main_block
),SHM_MINBLOCK
);
89 dde_proc_init(main_block
->proc
);
91 shm_sem_init(&main_block
->sem
);
93 /* main block set and data structure is stable now */
94 main_block
->build_lock
=0;
97 /* Delete everything related to main_block */
98 void shm_delete_all(int shmid
)
105 shmctl( shmid
, IPC_RMID
, NULL
);
107 for (proc_idx
= 0 ; proc_idx
< DDE_PROCS
; proc_idx
++)
108 dde_proc_done( &main_block
->proc
[proc_idx
] );
110 shm_sem_done(&main_block
->sem
);
111 shmdt( (void *) main_block
);
115 int DDE_no_of_attached()
117 struct shmid_ds shm_info
;
119 if (shmctl(main_shm_id
, IPC_STAT
, &shm_info
) == -1)
122 return shm_info
.shm_nattch
;
125 ** Test if shm_id is MainBlock and attach it (if it is),
126 ** Return 1 if ok, 0 otherwise.
128 static int attach_MainBlock(int shm_id
)
130 struct shmid_ds shm_info
;
132 if (shmctl(shm_id
, IPC_STAT
, &shm_info
) == -1)
135 /* Make sure we don't work on somebody else's block */
136 if (shm_info
.shm_perm
.cuid
!= getuid()) { /* creator is not me */
137 WARN(shm
, "Creator is not me!\n");
141 TRACE(shm
,"shared memory exist, attaching anywhere\n");
142 main_block
=(struct shm_main_block
*)shmat(shm_id
, 0, 0);
143 if ( (int)main_block
==-1) {
144 WARN(shm
, "Attach failed\n");
148 if (strcmp(main_block
->magic
, shm_header
) != 0) {
149 TRACE(shm
,"Detaching, wrong magic\n");
150 shmdt((void *)main_block
);
155 print_shm_info(shm_id
);
157 /* Is it an old unused block ? */
158 if (shm_info
.shm_nattch
== 0) {
159 TRACE(shm
,"No attaches, deleting old data\n");
160 shm_delete_all(shm_id
);
164 /* Wait for data structure to stabilize */
165 while (main_block
->build_lock
)
174 /* (Function used by the constructor)
175 * Try to get existing shared memory with key="Wine", size=SHM_MINBLOCK
176 * complete user permission.
177 * If such block is found - return true (1), else return false (0)
179 static int shm_locate_MainBlock(key_t shm_key
)
181 int shm_id
; /* Descriptor to this shared memory */
184 TRACE(shm
,"trying to attach, key=0x%x\n",
186 for (i
=0 ; i
< SHM_KEY_RANGE
; i
++) {
187 TRACE(shm
,"iteration=%d\n", i
);
189 shm_id
= shmget ( shm_key
+i
, SHM_MINBLOCK
,0700);
192 if ( attach_MainBlock(shm_id
) ) {
193 return 1; /* success! */
198 case EIDRM
: /* segment destroyed */
200 case EACCES
: /* no user permision */
203 case ENOMEM
: /* no free memory */
204 case ENOENT
: /* this key does not exist */
206 WARN(shm
,"shmget failed, errno=%d, %s\n",
207 errno
, strerror(errno
) );
208 return 0; /* Failed */
215 /* (Function used by the constructor)
216 * Try to allocate new shared memory with key="Wine", size=SHM_MINBLOCK
217 * with complete user permission.
218 * If allocation succeeds - return true (1), else return false (0)
220 static int shm_create_MainBlock(key_t MainShmKey
)
223 int flags
= 0700 | IPC_CREAT
| IPC_EXCL
;
226 TRACE(shm
,"creating shared memory\n");
228 /* try to allocate shared memory with key="Wine", size=SHM_MINBLOCK, */
229 /* complete user permission */
230 for (i
=0 ; i
< SHM_KEY_RANGE
; i
++) {
231 shm_id
= shmget ( (key_t
) MainShmKey
, SHM_MINBLOCK
, flags
);
236 WARN(shm
, "failed to create shared memory\n");
239 TRACE(shm
,"shared memory created, attaching\n");
240 main_block
=(struct shm_main_block
*) shmat(shm_id
, 0,0);
242 print_shm_info(shm_id
);
244 shm_setup_main_block();
250 /* link to the dde shared memory block */
251 /* RETURN: 0 on success, non zero on failure */
254 if ( !shm_locate_MainBlock(WineKey
)
255 && !shm_create_MainBlock(WineKey
)) {
256 ERR(shm
, "Failed to init main shm block\n");
260 dde_proc_add(main_block
->proc
);
264 static void shm_main_refresh()
268 for (proc_idx
= 0 ; proc_idx
< DDE_PROCS
; proc_idx
++)
269 dde_proc_refresh( &main_block
->proc
[proc_idx
] );
272 #endif /* CONFIG_IPC */