summaryrefslogtreecommitdiff
path: root/desc.c
diff options
context:
space:
mode:
Diffstat (limited to 'desc.c')
-rw-r--r--desc.c390
1 files changed, 390 insertions, 0 deletions
diff --git a/desc.c b/desc.c
new file mode 100644
index 0000000..f1e0334
--- /dev/null
+++ b/desc.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
+ * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
+ * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id$
+ */
+
+#include "defs.h"
+
+#include <fcntl.h>
+#include <sys/file.h>
+
+static struct xlat fcntlcmds[] = {
+ { F_DUPFD, "F_DUPFD" },
+ { F_GETFD, "F_GETFD" },
+ { F_SETFD, "F_SETFD" },
+ { F_GETFL, "F_GETFL" },
+ { F_SETFL, "F_SETFL" },
+ { F_GETLK, "F_GETLK" },
+ { F_SETLK, "F_SETLK" },
+ { F_SETLKW, "F_SETLKW" },
+ { F_GETOWN, "F_GETOWN" },
+ { F_SETOWN, "F_SETOWN" },
+#ifdef F_RSETLK
+ { F_RSETLK, "F_RSETLK" },
+#endif
+#ifdef F_RSETLKW
+ { F_RSETLKW, "F_RSETLKW" },
+#endif
+#ifdef F_RGETLK
+ { F_RGETLK, "F_RGETLK" },
+#endif
+#ifdef F_CNVT
+ { F_CNVT, "F_CNVT" },
+#endif
+ { 0, NULL },
+};
+
+static struct xlat fdflags[] = {
+#ifdef FD_CLOEXEC
+ { FD_CLOEXEC, "FD_CLOEXEC" },
+#endif
+ { 0, NULL },
+};
+
+#ifdef LOCK_SH
+
+static struct xlat flockcmds[] = {
+ { LOCK_SH, "LOCK_SH" },
+ { LOCK_EX, "LOCK_EX" },
+ { LOCK_NB, "LOCK_NB" },
+ { LOCK_UN, "LOCK_UN" },
+ { 0, NULL },
+};
+
+#endif /* LOCK_SH */
+
+static struct xlat lockfcmds[] = {
+ { F_RDLCK, "F_RDLCK" },
+ { F_WRLCK, "F_WRLCK" },
+ { F_UNLCK, "F_UNLCK" },
+#ifdef F_EXLCK
+ { F_EXLCK, "F_EXLCK" },
+#endif
+#ifdef F_SHLCK
+ { F_SHLCK, "F_SHLCK" },
+#endif
+ { 0, NULL },
+};
+
+static struct xlat whence[] = {
+ { SEEK_SET, "SEEK_SET" },
+ { SEEK_CUR, "SEEK_CUR" },
+ { SEEK_END, "SEEK_END" },
+ { 0, NULL },
+};
+
+/* fcntl/lockf */
+static void
+printflock(tcp, addr, getlk)
+struct tcb *tcp;
+int addr;
+int getlk;
+{
+ struct flock fl;
+
+ if (umove(tcp, addr, &fl) < 0) {
+ tprintf("{...}");
+ return;
+ }
+ tprintf("{type=");
+ printxval(lockfcmds, fl.l_type, "F_???");
+ tprintf(", whence=");
+ printxval(whence, fl.l_whence, "SEEK_???");
+ tprintf(", start=%ld, len=%ld", fl.l_start, fl.l_len);
+ if (getlk)
+ tprintf(", pid=%lu}", (unsigned long) fl.l_pid);
+ else
+ tprintf("}");
+}
+
+static char *
+sprintflags(xlat, flags)
+struct xlat *xlat;
+int flags;
+{
+ static char outstr[1024];
+ char *sep;
+
+ strcpy(outstr, "flags ");
+ sep = "";
+ for (; xlat->str; xlat++) {
+ if ((flags & xlat->val) == xlat->val) {
+ sprintf(outstr + strlen(outstr),
+ "%s%s", sep, xlat->str);
+ sep = "|";
+ flags &= ~xlat->val;
+ }
+ }
+ if (flags)
+ sprintf(outstr + strlen(outstr),
+ "%s%#x", sep, flags);
+ return outstr;
+}
+
+int
+sys_fcntl(tcp)
+struct tcb *tcp;
+{
+ extern struct xlat openmodes[];
+
+ if (entering(tcp)) {
+ tprintf("%ld, ", tcp->u_arg[0]);
+ printxval(fcntlcmds, tcp->u_arg[1], "F_???");
+ switch (tcp->u_arg[1]) {
+ case F_SETFD:
+ tprintf(", ");
+ if (printflags(fdflags, tcp->u_arg[2]) == 0)
+ tprintf("0");
+ break;
+ case F_SETOWN: case F_DUPFD:
+ tprintf(", %ld", tcp->u_arg[2]);
+ break;
+ case F_SETFL:
+ tprintf(", ");
+ if (printflags(openmodes, tcp->u_arg[2] + 1) == 0)
+ tprintf("0");
+ break;
+ case F_SETLK: case F_SETLKW:
+ tprintf(", ");
+ printflock(tcp, tcp->u_arg[2], 0);
+ break;
+ }
+ }
+ else {
+ switch (tcp->u_arg[1]) {
+ case F_DUPFD:
+ case F_SETFD: case F_SETFL:
+ case F_SETLK: case F_SETLKW:
+ case F_SETOWN: case F_GETOWN:
+ break;
+ case F_GETFD:
+ if (tcp->u_rval == 0)
+ return 0;
+ tcp->auxstr = sprintflags(fdflags, tcp->u_rval);
+ return RVAL_HEX|RVAL_STR;
+ case F_GETFL:
+ tcp->auxstr = sprintflags(openmodes, tcp->u_rval + 1);
+ return RVAL_HEX|RVAL_STR;
+ case F_GETLK:
+ tprintf(", ");
+ printflock(tcp, tcp->u_arg[2], 1);
+ break;
+ default:
+ tprintf(", %#lx", tcp->u_arg[2]);
+ break;
+ }
+ }
+ return 0;
+}
+
+#ifdef LOCK_SH
+
+int
+sys_flock(tcp)
+struct tcb *tcp;
+{
+ if (entering(tcp)) {
+ tprintf("%ld, ", tcp->u_arg[0]);
+ if (!printflags(flockcmds, tcp->u_arg[1]))
+ tprintf("LOCK_???");
+ }
+ return 0;
+}
+#endif /* LOCK_SH */
+
+int
+sys_close(tcp)
+struct tcb *tcp;
+{
+ if (entering(tcp)) {
+ tprintf("%ld", tcp->u_arg[0]);
+ }
+ return 0;
+}
+
+int
+sys_dup(tcp)
+struct tcb *tcp;
+{
+ if (entering(tcp)) {
+ tprintf("%ld", tcp->u_arg[0]);
+ }
+ return 0;
+}
+
+int
+sys_dup2(tcp)
+struct tcb *tcp;
+{
+ if (entering(tcp)) {
+ tprintf("%ld, %ld", tcp->u_arg[0], tcp->u_arg[1]);
+ }
+ return 0;
+}
+
+int
+sys_getdtablesize(tcp)
+struct tcb *tcp;
+{
+ return 0;
+}
+
+static int
+decode_select(tcp, args)
+struct tcb *tcp;
+long *args;
+{
+ int i, j, nfds;
+ fd_set fds;
+ struct timeval tv;
+ static char outstr[1024];
+ char *sep;
+ long arg;
+
+ if (entering(tcp)) {
+ nfds = args[0];
+ tprintf("%d", nfds);
+ for (i = 0; i < 3; i++) {
+ arg = args[i+1];
+ if (arg == 0) {
+ tprintf(", NULL");
+ continue;
+ }
+ if (!verbose(tcp)) {
+ tprintf(", %#lx", arg);
+ continue;
+ }
+ if (umove(tcp, arg, &fds) < 0) {
+ tprintf(", [?]");
+ continue;
+ }
+ tprintf(", [");
+ for (j = 0, sep = ""; j < nfds; j++) {
+ if (FD_ISSET(j, &fds)) {
+ tprintf("%s%u", sep, j);
+ sep = " ";
+ }
+ }
+ tprintf("]");
+ }
+ if (!args[4])
+ tprintf(", NULL");
+ else if (!verbose(tcp))
+ tprintf(", %#lx", args[4]);
+ else if (umove(tcp, args[4], &tv) < 0)
+ tprintf(", {...}");
+ else {
+ tprintf(", {%lu, %lu}",
+ (long) tv.tv_sec, (long) tv.tv_usec);
+ }
+ }
+ else {
+ unsigned int cumlen = 0;
+ char *sep = "";
+
+ if (syserror(tcp))
+ return 0;
+
+ if ((nfds = tcp->u_rval) == 0) {
+ tcp->auxstr = "Timeout";
+ return RVAL_STR;
+ }
+ outstr[0] = '\0';
+ for (i = 0; i < 3; i++) {
+ int first = 1;
+ char str[20];
+
+ tcp->auxstr = outstr;
+ arg = args[i+1];
+ if (!arg || umove(tcp, arg, &fds) < 0)
+ continue;
+ for (j = 0; j < args[0]; j++) {
+ if (FD_ISSET(j, &fds)) {
+ if (first) {
+ sprintf(str, "%s%s [%u", sep,
+ i == 0 ? "in" :
+ i == 1 ? "out" :
+ "except", j);
+ first = 0;
+ sep = ", ";
+ }
+ else
+ sprintf(str, " %u", j);
+ cumlen += strlen(str);
+ if (cumlen < sizeof(outstr))
+ strcat(outstr, str);
+ nfds--;
+ }
+ }
+ if (cumlen)
+ strcat(outstr, "]");
+ if (nfds == 0)
+ break;
+ }
+#ifdef LINUX
+ /* This contains no useful information on SunOS. */
+ if (args[4]) {
+ char str[20];
+
+ if (umove(tcp, args[4], &tv) >= 0)
+ sprintf(str, "%sleft {%lu, %lu}", sep,
+ (long) tv.tv_sec, (long) tv.tv_usec);
+ if ((cumlen += strlen(str)) < sizeof(outstr))
+ strcat(outstr, str);
+ }
+#endif /* LINUX */
+ return RVAL_STR;
+ }
+ return 0;
+}
+
+#ifdef LINUX
+
+int
+sys_oldselect(tcp)
+struct tcb *tcp;
+{
+ long args[5];
+
+ if (umoven(tcp, tcp->u_arg[0], sizeof args, (char *) args) < 0) {
+ tprintf("[...]");
+ return 0;
+ }
+ return decode_select(tcp, args);
+}
+
+#endif /* LINUX */
+
+int
+sys_select(tcp)
+struct tcb *tcp;
+{
+ long *args = tcp->u_arg;
+ return decode_select(tcp, args);
+}