ipc.c revision b2dee13345a62c80a677f3342cd525d611fbc632
1/*
2 * Copyright (c) 1993 Ulrich Pegelow <pegelow@moorea.uni-muenster.de>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 *    derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 *	$Id$
31 */
32
33#include "defs.h"
34
35#if defined(LINUX) || defined(SUNOS4) || defined(FREEBSD)
36
37# ifdef HAVE_MQUEUE_H
38#  include <mqueue.h>
39# endif
40
41#include <fcntl.h>
42#include <sys/ipc.h>
43#include <sys/sem.h>
44#include <sys/msg.h>
45#include <sys/shm.h>
46
47#ifndef MSG_STAT
48#define MSG_STAT 11
49#endif
50#ifndef MSG_INFO
51#define MSG_INFO 12
52#endif
53#ifndef SHM_STAT
54#define SHM_STAT 13
55#endif
56#ifndef SHM_INFO
57#define SHM_INFO 14
58#endif
59#ifndef SEM_STAT
60#define SEM_STAT 18
61#endif
62#ifndef SEM_INFO
63#define SEM_INFO 19
64#endif
65
66#if defined LINUX && !defined IPC_64
67# define IPC_64 0x100
68#endif
69
70extern const struct xlat openmodes[];
71extern void printsigevent(struct tcb *tcp, long arg);
72
73static const struct xlat msgctl_flags[] = {
74	{ IPC_RMID,	"IPC_RMID"	},
75	{ IPC_SET,	"IPC_SET"	},
76	{ IPC_STAT,	"IPC_STAT"	},
77#ifdef LINUX
78	{ IPC_INFO,	"IPC_INFO"	},
79	{ MSG_STAT,	"MSG_STAT"	},
80	{ MSG_INFO,	"MSG_INFO"	},
81#endif /* LINUX */
82	{ 0,		NULL		},
83};
84
85static const struct xlat semctl_flags[] = {
86	{ IPC_RMID,	"IPC_RMID"	},
87	{ IPC_SET,	"IPC_SET"	},
88	{ IPC_STAT,	"IPC_STAT"	},
89#ifdef LINUX
90	{ IPC_INFO,	"IPC_INFO"	},
91	{ SEM_STAT,	"SEM_STAT"	},
92	{ SEM_INFO,	"SEM_INFO"	},
93#endif /* LINUX */
94	{ GETPID,	"GETPID"	},
95	{ GETVAL,	"GETVAL"	},
96	{ GETALL,	"GETALL"	},
97	{ GETNCNT,	"GETNCNT"	},
98	{ GETZCNT,	"GETZCNT"	},
99	{ SETVAL,	"SETVAL"	},
100	{ SETALL,	"SETALL"	},
101	{ 0,		NULL		},
102};
103
104static const struct xlat shmctl_flags[] = {
105	{ IPC_RMID,	"IPC_RMID"	},
106	{ IPC_SET,	"IPC_SET"	},
107	{ IPC_STAT,	"IPC_STAT"	},
108#ifdef LINUX
109	{ IPC_INFO,	"IPC_INFO"	},
110	{ SHM_STAT,	"SHM_STAT"	},
111	{ SHM_INFO,	"SHM_INFO"	},
112#endif /* LINUX */
113#ifdef SHM_LOCK
114	{ SHM_LOCK,	"SHM_LOCK"	},
115#endif
116#ifdef SHM_UNLOCK
117	{ SHM_UNLOCK,	"SHM_UNLOCK"	},
118#endif
119	{ 0,		NULL		},
120};
121
122static const struct xlat resource_flags[] = {
123	{ IPC_CREAT,	"IPC_CREAT"	},
124	{ IPC_EXCL,	"IPC_EXCL"	},
125	{ IPC_NOWAIT,	"IPC_NOWAIT"	},
126	{ 0,		NULL		},
127};
128
129static const struct xlat shm_resource_flags[] = {
130	{ IPC_CREAT,	"IPC_CREAT"	},
131	{ IPC_EXCL,	"IPC_EXCL"	},
132#ifdef SHM_HUGETLB
133	{ SHM_HUGETLB,	"SHM_HUGETLB"	},
134#endif
135	{ 0,		NULL		},
136};
137
138static const struct xlat shm_flags[] = {
139#ifdef LINUX
140	{ SHM_REMAP,	"SHM_REMAP"	},
141#endif /* LINUX */
142	{ SHM_RDONLY,	"SHM_RDONLY"	},
143	{ SHM_RND,	"SHM_RND"	},
144	{ 0,		NULL		},
145};
146
147static const struct xlat msg_flags[] = {
148	{ MSG_NOERROR,	"MSG_NOERROR"	},
149#ifdef LINUX
150	{ MSG_EXCEPT,	"MSG_EXCEPT"	},
151#endif /* LINUX */
152	{ IPC_NOWAIT,	"IPC_NOWAIT"	},
153	{ 0,		NULL		},
154};
155
156int sys_msgget(tcp)
157struct tcb *tcp;
158{
159	if (entering(tcp)) {
160		if (tcp->u_arg[0])
161			tprintf("%lu", tcp->u_arg[0]);
162		else
163			tprintf("IPC_PRIVATE");
164		tprintf(", ");
165		if (printflags(resource_flags, tcp->u_arg[1] & ~0777, NULL) != 0)
166			tprintf("|");
167		tprintf("%#lo", tcp->u_arg[1] & 0777);
168	}
169	return 0;
170}
171
172#ifdef IPC_64
173# define PRINTCTL(flagset, arg, dflt) \
174	if ((arg) & IPC_64) tprintf("IPC_64|"); \
175	printxval((flagset), (arg) &~ IPC_64, dflt)
176#else
177# define PRINTCTL printxval
178#endif
179
180int sys_msgctl(tcp)
181struct tcb *tcp;
182{
183	if (entering(tcp)) {
184		tprintf("%lu, ", tcp->u_arg[0]);
185		PRINTCTL(msgctl_flags, tcp->u_arg[1], "MSG_???");
186#ifdef LINUX
187		tprintf(", %#lx", tcp->u_arg[3]);
188#else /* !LINUX */
189		tprintf(", %#lx", tcp->u_arg[2]);
190#endif /* !LINUX */
191	}
192	return 0;
193}
194
195int sys_msgsnd(tcp)
196struct tcb *tcp;
197{
198	long mtype;
199
200	if (entering(tcp)) {
201		tprintf("%lu", tcp->u_arg[0]);
202#ifdef LINUX
203		umove(tcp, tcp->u_arg[3], &mtype);
204		tprintf(", {%lu, ", mtype);
205		printstr(tcp, tcp->u_arg[3] + sizeof(long),
206			tcp->u_arg[1]);
207		tprintf("}, %lu", tcp->u_arg[1]);
208		tprintf(", ");
209		printflags(msg_flags, tcp->u_arg[2], "MSG_???");
210#else /* !LINUX */
211		umove(tcp, tcp->u_arg[1], &mtype);
212		tprintf(", {%lu, ", mtype);
213		printstr(tcp, tcp->u_arg[1] + sizeof(long),
214			tcp->u_arg[2]);
215		tprintf("}, %lu", tcp->u_arg[2]);
216		tprintf(", ");
217		printflags(msg_flags, tcp->u_arg[3], "MSG_???");
218#endif /* !LINUX */
219	}
220	return 0;
221}
222
223int sys_msgrcv(tcp)
224struct tcb *tcp;
225{
226	long mtype;
227#ifdef LINUX
228	struct ipc_wrapper {
229		struct msgbuf *msgp;
230		long msgtyp;
231	} tmp;
232#endif
233
234
235	if (exiting(tcp)) {
236		tprintf("%lu", tcp->u_arg[0]);
237#ifdef LINUX
238		umove(tcp, tcp->u_arg[3], &tmp);
239		umove(tcp, (long) tmp.msgp, &mtype);
240		tprintf(", {%lu, ", mtype);
241		printstr(tcp, (long) (tmp.msgp) + sizeof(long),
242			tcp->u_arg[1]);
243		tprintf("}, %lu", tcp->u_arg[1]);
244		tprintf(", %ld", tmp.msgtyp);
245		tprintf(", ");
246		printflags(msg_flags, tcp->u_arg[2], "MSG_???");
247#else /* !LINUX */
248		umove(tcp, tcp->u_arg[1], &mtype);
249		tprintf(", {%lu, ", mtype);
250		printstr(tcp, tcp->u_arg[1] + sizeof(long),
251			tcp->u_arg[2]);
252		tprintf("}, %lu", tcp->u_arg[2]);
253		tprintf(", %ld", tcp->u_arg[3]);
254		tprintf(", ");
255		printflags(msg_flags, tcp->u_arg[4], "MSG_???");
256#endif /* !LINUX */
257	}
258	return 0;
259}
260
261int sys_semop(tcp)
262struct tcb *tcp;
263{
264	if (entering(tcp)) {
265		tprintf("%lu", tcp->u_arg[0]);
266#ifdef LINUX
267		tprintf(", %#lx", tcp->u_arg[3]);
268		tprintf(", %lu", tcp->u_arg[1]);
269#else /* !LINUX */
270		tprintf(", %#lx", tcp->u_arg[1]);
271		tprintf(", %lu", tcp->u_arg[2]);
272#endif /* !LINUX */
273	}
274	return 0;
275}
276
277#ifdef LINUX
278int sys_semtimedop(tcp)
279struct tcb *tcp;
280{
281	if (entering(tcp)) {
282		tprintf("%lu", tcp->u_arg[0]);
283		tprintf(", %#lx", tcp->u_arg[3]);
284		tprintf(", %lu, ", tcp->u_arg[1]);
285		printtv(tcp, tcp->u_arg[5]);
286	}
287	return 0;
288}
289#endif
290
291int sys_semget(tcp)
292struct tcb *tcp;
293{
294	if (entering(tcp)) {
295		if (tcp->u_arg[0])
296			tprintf("%lu", tcp->u_arg[0]);
297		else
298			tprintf("IPC_PRIVATE");
299		tprintf(", %lu", tcp->u_arg[1]);
300		tprintf(", ");
301		if (printflags(resource_flags, tcp->u_arg[2] & ~0777, NULL) != 0)
302			tprintf("|");
303		tprintf("%#lo", tcp->u_arg[2] & 0777);
304	}
305	return 0;
306}
307
308int sys_semctl(tcp)
309struct tcb *tcp;
310{
311	if (entering(tcp)) {
312		tprintf("%lu", tcp->u_arg[0]);
313		tprintf(", %lu, ", tcp->u_arg[1]);
314		PRINTCTL(semctl_flags, tcp->u_arg[2], "SEM_???");
315		tprintf(", %#lx", tcp->u_arg[3]);
316	}
317	return 0;
318}
319
320int sys_shmget(tcp)
321struct tcb *tcp;
322{
323	if (entering(tcp)) {
324		if (tcp->u_arg[0])
325			tprintf("%lu", tcp->u_arg[0]);
326		else
327			tprintf("IPC_PRIVATE");
328		tprintf(", %lu", tcp->u_arg[1]);
329		tprintf(", ");
330		if (printflags(shm_resource_flags, tcp->u_arg[2] & ~0777, NULL) != 0)
331			tprintf("|");
332		tprintf("%#lo", tcp->u_arg[2] & 0777);
333	}
334	return 0;
335}
336
337int sys_shmctl(tcp)
338struct tcb *tcp;
339{
340	if (entering(tcp)) {
341		tprintf("%lu, ", tcp->u_arg[0]);
342		PRINTCTL(shmctl_flags, tcp->u_arg[1], "SHM_???");
343#ifdef LINUX
344		tprintf(", %#lx", tcp->u_arg[3]);
345#else /* !LINUX */
346		tprintf(", %#lx", tcp->u_arg[2]);
347#endif /* !LINUX */
348	}
349	return 0;
350}
351
352int sys_shmat(tcp)
353struct tcb *tcp;
354{
355#ifdef LINUX
356	unsigned long raddr;
357#endif /* LINUX */
358
359	if (exiting(tcp)) {
360		tprintf("%lu", tcp->u_arg[0]);
361#ifdef LINUX
362		tprintf(", %#lx", tcp->u_arg[3]);
363		tprintf(", ");
364		printflags(shm_flags, tcp->u_arg[1], "SHM_???");
365#else /* !LINUX */
366		tprintf(", %#lx", tcp->u_arg[1]);
367		tprintf(", ");
368		printflags(shm_flags, tcp->u_arg[2], "SHM_???");
369#endif /* !LINUX */
370		if (syserror(tcp))
371			return 0;
372#ifdef LINUX
373		if (umove(tcp, tcp->u_arg[2], &raddr) < 0)
374			return RVAL_NONE;
375		tcp->u_rval = raddr;
376#endif /* LINUX */
377		return RVAL_HEX;
378	}
379	return 0;
380}
381
382int sys_shmdt(tcp)
383struct tcb *tcp;
384{
385	if (entering(tcp))
386#ifdef LINUX
387		tprintf("%#lx", tcp->u_arg[3]);
388#else /* !LINUX */
389		tprintf("%#lx", tcp->u_arg[0]);
390#endif /* !LINUX */
391	return 0;
392}
393
394#endif /* defined(LINUX) || defined(SUNOS4) || defined(FREEBSD) */
395
396#ifdef LINUX
397int sys_mq_open(tcp)
398struct tcb *tcp;
399{
400	if (entering(tcp)) {
401		printpath(tcp, tcp->u_arg[0]);
402		tprintf(", ");
403		/* flags */
404		printflags(openmodes, tcp->u_arg[1] + 1, "O_???");
405		if (tcp->u_arg[1] & O_CREAT) {
406# ifndef HAVE_MQUEUE_H
407			tprintf(", %lx", tcp->u_arg[2]);
408# else
409			struct mq_attr attr;
410			/* mode */
411			tprintf(", %#lo, ", tcp->u_arg[2]);
412			if (umove(tcp, tcp->u_arg[3], &attr) < 0)
413				tprintf("{ ??? }");
414			else
415				tprintf("{mq_maxmsg=%ld, mq_msgsize=%ld}",
416					attr.mq_maxmsg, attr.mq_msgsize);
417# endif
418		}
419	}
420	return 0;
421}
422
423int sys_mq_timedsend(tcp)
424struct tcb *tcp;
425{
426	if (entering(tcp)) {
427		tprintf("%ld, ", tcp->u_arg[0]);
428		printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
429		tprintf(", %lu, %ld, ", tcp->u_arg[2], tcp->u_arg[3]);
430		printtv(tcp, tcp->u_arg[4]);
431	}
432	return 0;
433}
434
435int sys_mq_timedreceive(tcp)
436struct tcb *tcp;
437{
438	if (entering(tcp))
439		tprintf("%ld, ", tcp->u_arg[0]);
440	else {
441		printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
442		tprintf(", %lu, %ld, ", tcp->u_arg[2], tcp->u_arg[3]);
443		printtv(tcp, tcp->u_arg[4]);
444	}
445	return 0;
446}
447
448int sys_mq_notify(tcp)
449struct tcb *tcp;
450{
451	if (entering(tcp)) {
452		tprintf("%ld, ", tcp->u_arg[0]);
453		printsigevent(tcp, tcp->u_arg[1]);
454	}
455	return 0;
456}
457
458static void printmqattr(tcp, addr)
459struct tcb *tcp;
460long addr;
461{
462	if (addr == 0)
463		tprintf("NULL");
464	else {
465# ifndef HAVE_MQUEUE_H
466		tprintf("%#lx", addr);
467# else
468		struct mq_attr attr;
469		if (umove(tcp, addr, &attr) < 0) {
470			tprintf("{...}");
471			return;
472		}
473		tprintf("{mq_flags=");
474		printflags(openmodes, attr.mq_flags + 1, "O_???");
475		tprintf(", mq_maxmsg=%ld, mq_msgsize=%ld, mq_curmsg=%ld}",
476			attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs);
477# endif
478	}
479}
480
481int sys_mq_getsetattr(tcp)
482struct tcb *tcp;
483{
484	if (entering(tcp)) {
485		tprintf("%ld, ", tcp->u_arg[0]);
486		printmqattr(tcp, tcp->u_arg[1]);
487		tprintf(", ");
488	} else
489		printmqattr(tcp, tcp->u_arg[2]);
490	return 0;
491}
492#endif
493