desc.c revision 4dc8a2aec63e4fb5ee2688544c4de323ed5de3ef
1/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
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#include <fcntl.h>
36#include <sys/file.h>
37
38static struct xlat fcntlcmds[] = {
39	{ F_DUPFD,	"F_DUPFD"	},
40	{ F_GETFD,	"F_GETFD"	},
41	{ F_SETFD,	"F_SETFD"	},
42	{ F_GETFL,	"F_GETFL"	},
43	{ F_SETFL,	"F_SETFL"	},
44	{ F_GETLK,	"F_GETLK"	},
45	{ F_SETLK,	"F_SETLK"	},
46	{ F_SETLKW,	"F_SETLKW"	},
47	{ F_GETOWN,	"F_GETOWN"	},
48	{ F_SETOWN,	"F_SETOWN"	},
49#ifdef F_RSETLK
50	{ F_RSETLK,	"F_RSETLK"	},
51#endif
52#ifdef F_RSETLKW
53	{ F_RSETLKW,	"F_RSETLKW"	},
54#endif
55#ifdef F_RGETLK
56	{ F_RGETLK,	"F_RGETLK"	},
57#endif
58#ifdef F_CNVT
59	{ F_CNVT,	"F_CNVT"	},
60#endif
61	{ 0,		NULL		},
62};
63
64static struct xlat fdflags[] = {
65#ifdef FD_CLOEXEC
66	{ FD_CLOEXEC,	"FD_CLOEXEC"	},
67#endif
68	{ 0,		NULL		},
69};
70
71#ifdef LOCK_SH
72
73static struct xlat flockcmds[] = {
74	{ LOCK_SH,	"LOCK_SH"	},
75	{ LOCK_EX,	"LOCK_EX"	},
76	{ LOCK_NB,	"LOCK_NB"	},
77	{ LOCK_UN,	"LOCK_UN"	},
78	{ 0,		NULL		},
79};
80
81#endif /* LOCK_SH */
82
83static struct xlat lockfcmds[] = {
84	{ F_RDLCK,	"F_RDLCK"	},
85	{ F_WRLCK,	"F_WRLCK"	},
86	{ F_UNLCK,	"F_UNLCK"	},
87#ifdef F_EXLCK
88	{ F_EXLCK,	"F_EXLCK"	},
89#endif
90#ifdef F_SHLCK
91	{ F_SHLCK,	"F_SHLCK"	},
92#endif
93	{ 0,		NULL		},
94};
95
96static struct xlat whence[] = {
97	{ SEEK_SET,	"SEEK_SET"	},
98	{ SEEK_CUR,	"SEEK_CUR"	},
99	{ SEEK_END,	"SEEK_END"	},
100	{ 0,		NULL		},
101};
102
103/* fcntl/lockf */
104static void
105printflock(tcp, addr, getlk)
106struct tcb *tcp;
107int addr;
108int getlk;
109{
110	struct flock fl;
111
112	if (umove(tcp, addr, &fl) < 0) {
113		tprintf("{...}");
114		return;
115	}
116	tprintf("{type=");
117	printxval(lockfcmds, fl.l_type, "F_???");
118	tprintf(", whence=");
119	printxval(whence, fl.l_whence, "SEEK_???");
120	tprintf(", start=%ld, len=%ld", fl.l_start, fl.l_len);
121	if (getlk)
122		tprintf(", pid=%lu}", (unsigned long) fl.l_pid);
123	else
124		tprintf("}");
125}
126
127static char *
128sprintflags(xlat, flags)
129struct xlat *xlat;
130int flags;
131{
132	static char outstr[1024];
133	char *sep;
134
135	strcpy(outstr, "flags ");
136	sep = "";
137	for (; xlat->str; xlat++) {
138		if ((flags & xlat->val) == xlat->val) {
139			sprintf(outstr + strlen(outstr),
140				"%s%s", sep, xlat->str);
141			sep = "|";
142			flags &= ~xlat->val;
143		}
144	}
145	if (flags)
146		sprintf(outstr + strlen(outstr),
147			"%s%#x", sep, flags);
148	return outstr;
149}
150
151int
152sys_fcntl(tcp)
153struct tcb *tcp;
154{
155	extern struct xlat openmodes[];
156
157	if (entering(tcp)) {
158		tprintf("%ld, ", tcp->u_arg[0]);
159		printxval(fcntlcmds, tcp->u_arg[1], "F_???");
160		switch (tcp->u_arg[1]) {
161		case F_SETFD:
162			tprintf(", ");
163			if (printflags(fdflags, tcp->u_arg[2]) == 0)
164				tprintf("0");
165			break;
166		case F_SETOWN: case F_DUPFD:
167			tprintf(", %ld", tcp->u_arg[2]);
168			break;
169		case F_SETFL:
170			tprintf(", ");
171			if (printflags(openmodes, tcp->u_arg[2] + 1) == 0)
172				tprintf("0");
173			break;
174		case F_SETLK: case F_SETLKW:
175			tprintf(", ");
176			printflock(tcp, tcp->u_arg[2], 0);
177			break;
178		}
179	}
180	else {
181		switch (tcp->u_arg[1]) {
182		case F_DUPFD:
183		case F_SETFD: case F_SETFL:
184		case F_SETLK: case F_SETLKW:
185		case F_SETOWN: case F_GETOWN:
186			break;
187		case F_GETFD:
188			if (tcp->u_rval == 0)
189				return 0;
190			tcp->auxstr = sprintflags(fdflags, tcp->u_rval);
191			return RVAL_HEX|RVAL_STR;
192		case F_GETFL:
193			tcp->auxstr = sprintflags(openmodes, tcp->u_rval + 1);
194			return RVAL_HEX|RVAL_STR;
195		case F_GETLK:
196			tprintf(", ");
197			printflock(tcp, tcp->u_arg[2], 1);
198			break;
199		default:
200			tprintf(", %#lx", tcp->u_arg[2]);
201			break;
202		}
203	}
204	return 0;
205}
206
207#ifdef LOCK_SH
208
209int
210sys_flock(tcp)
211struct tcb *tcp;
212{
213	if (entering(tcp)) {
214		tprintf("%ld, ", tcp->u_arg[0]);
215		if (!printflags(flockcmds, tcp->u_arg[1]))
216			tprintf("LOCK_???");
217	}
218	return 0;
219}
220#endif /* LOCK_SH */
221
222int
223sys_close(tcp)
224struct tcb *tcp;
225{
226	if (entering(tcp)) {
227		tprintf("%ld", tcp->u_arg[0]);
228	}
229	return 0;
230}
231
232int
233sys_dup(tcp)
234struct tcb *tcp;
235{
236	if (entering(tcp)) {
237		tprintf("%ld", tcp->u_arg[0]);
238	}
239	return 0;
240}
241
242int
243sys_dup2(tcp)
244struct tcb *tcp;
245{
246	if (entering(tcp)) {
247		tprintf("%ld, %ld", tcp->u_arg[0], tcp->u_arg[1]);
248	}
249	return 0;
250}
251
252int
253sys_getdtablesize(tcp)
254struct tcb *tcp;
255{
256	return 0;
257}
258
259static int
260decode_select(tcp, args, bitness)
261struct tcb *tcp;
262long *args;
263int bitness;
264{
265	int i, j, nfds;
266	fd_set fds;
267	struct timeval tv;
268#ifdef ALPHA
269	struct timeval32 {
270		unsigned tv_sec;
271		unsigned tv_usec;
272	} *tv32;
273#endif
274	static char outstr[1024];
275	char *sep;
276	long arg;
277
278	if (entering(tcp)) {
279		nfds = args[0];
280		tprintf("%d", nfds);
281		for (i = 0; i < 3; i++) {
282			arg = args[i+1];
283			if (arg == 0) {
284				tprintf(", NULL");
285				continue;
286			}
287			if (!verbose(tcp)) {
288				tprintf(", %#lx", arg);
289				continue;
290			}
291			if (umove(tcp, arg, &fds) < 0) {
292				tprintf(", [?]");
293				continue;
294			}
295			tprintf(", [");
296			for (j = 0, sep = ""; j < nfds; j++) {
297				if (FD_ISSET(j, &fds)) {
298					tprintf("%s%u", sep, j);
299					sep = " ";
300				}
301			}
302			tprintf("]");
303		}
304		if (!args[4])
305			tprintf(", NULL");
306		else if (!verbose(tcp))
307			tprintf(", %#lx", args[4]);
308		else if (umove(tcp, args[4], &tv) < 0)
309			tprintf(", {...}");
310		else {
311#ifdef ALPHA
312			if (bitness) {
313				tv32=(struct timeval32*)&tv;
314				tprintf(", {%u, %u}", tv32->tv_sec, tv32->tv_usec);
315			} else
316#endif
317				tprintf(", {%lu, %lu}",
318					(long) tv.tv_sec, (long) tv.tv_usec);
319		}
320	}
321	else
322	{
323		unsigned int cumlen = 0;
324		char *sep = "";
325
326		if (syserror(tcp))
327			return 0;
328
329		if ((nfds = tcp->u_rval) == 0) {
330			tcp->auxstr = "Timeout";
331			return RVAL_STR;
332		}
333		outstr[0] = '\0';
334		for (i = 0; i < 3; i++) {
335			int first = 1;
336			char str[20];
337
338			tcp->auxstr = outstr;
339			arg = args[i+1];
340			if (!arg || umove(tcp, arg, &fds) < 0)
341				continue;
342			for (j = 0; j < args[0]; j++) {
343				if (FD_ISSET(j, &fds)) {
344					if (first) {
345						sprintf(str, "%s%s [%u", sep,
346							i == 0 ? "in" :
347							i == 1 ? "out" :
348							"except", j);
349						first = 0;
350						sep = ", ";
351					}
352					else
353						sprintf(str, " %u", j);
354					cumlen += strlen(str);
355					if (cumlen < sizeof(outstr))
356						strcat(outstr, str);
357					nfds--;
358				}
359			}
360			if (cumlen)
361				strcat(outstr, "]");
362			if (nfds == 0)
363				break;
364		}
365#ifdef LINUX
366		/* This contains no useful information on SunOS.  */
367		if (args[4]) {
368			char str[20];
369
370			if (umove(tcp, args[4], &tv) >= 0) {
371#ifdef ALPHA
372				if (bitness) {
373					tv32=(struct timeval32*)&tv;
374					sprintf(str, "%sleft {%u, %u}", sep,
375						tv32->tv_sec, tv32->tv_usec);
376				} else
377#endif
378					sprintf(str, "%sleft {%lu, %lu}", sep,
379						(long) tv.tv_sec, (long) tv.tv_usec);
380
381				if ((cumlen += strlen(str)) < sizeof(outstr))
382					strcat(outstr, str);
383			}
384		}
385#endif /* LINUX */
386		return RVAL_STR;
387	}
388	return 0;
389}
390
391#ifdef LINUX
392
393int
394sys_oldselect(tcp)
395struct tcb *tcp;
396{
397	long args[5];
398
399	if (umoven(tcp, tcp->u_arg[0], sizeof args, (char *) args) < 0) {
400		tprintf("[...]");
401		return 0;
402	}
403	return decode_select(tcp, args, 0);
404}
405
406#ifdef ALPHA
407sys_osf_select(tcp)
408struct tcb *tcp;
409{
410	long *args = tcp->u_arg;
411	return decode_select(tcp, args, 1);
412}
413#endif
414
415#endif /* LINUX */
416
417int
418sys_select(tcp)
419struct tcb *tcp;
420{
421	long *args = tcp->u_arg;
422	return decode_select(tcp, args, 0);
423}
424