summaryrefslogtreecommitdiff
path: root/src/lib/libcmd/fds.c
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2012-06-24 22:28:35 +0000
committerIgor Pashev <pashev.igor@gmail.com>2012-06-24 22:28:35 +0000
commit3950ffe2a485479f6561c27364d3d7df5a21d124 (patch)
tree468c6e14449d1b1e279222ec32f676b0311917d2 /src/lib/libcmd/fds.c
downloadksh-upstream.tar.gz
Imported Upstream version 93u+upstream
Diffstat (limited to 'src/lib/libcmd/fds.c')
-rw-r--r--src/lib/libcmd/fds.c360
1 files changed, 360 insertions, 0 deletions
diff --git a/src/lib/libcmd/fds.c b/src/lib/libcmd/fds.c
new file mode 100644
index 0000000..4dc934f
--- /dev/null
+++ b/src/lib/libcmd/fds.c
@@ -0,0 +1,360 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+static const char usage[] =
+"[-?\n@(#)$Id: fds (AT&T Research) 2009-09-09 $\n]"
+USAGE_LICENSE
+"[+NAME?fds - list open file descriptor status]"
+"[+DESCRIPTION?\bfds\b lists the status for each open file descriptor. "
+ "When invoked as a shell builtin it accesses the file descriptors of the "
+ "calling shell, otherwise it lists the file descriptors passed across "
+ "\bexec\b(2).]"
+"[l:long?List file descriptor details.]"
+"[u:unit?Write output to \afd\a.]#[fd]"
+"[+SEE ALSO?\blogname\b(1), \bwho\b(1), \bgetgroups\b(2), \bgetsockname\b(2), \bgetsockopts\b(2)]"
+;
+
+#include <cmd.h>
+#include <ls.h>
+
+#include "FEATURE/sockets"
+
+#if defined(S_IFSOCK) && _sys_socket && _hdr_arpa_inet && _hdr_netinet_in && _lib_getsockname && _lib_getsockopt && _lib_inet_ntoa
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#else
+#undef S_IFSOCK
+#endif
+
+#ifndef minor
+#define minor(x) (int)((x)&0xff)
+#endif
+#ifndef major
+#define major(x) (int)(((unsigned int)(x)>>8)&0xff)
+#endif
+
+#undef getconf
+#define getconf(x) strtol(astconf(x,NiL,NiL),NiL,0)
+
+#ifdef S_IFSOCK
+
+typedef struct NV_s
+{
+ const char* name;
+ int value;
+} NV_t;
+
+static const NV_t family[] =
+{
+#ifdef AF_LOCAL
+ "pipe", AF_LOCAL,
+#endif
+#ifdef AF_UNIX
+ "pipe", AF_UNIX,
+#endif
+#ifdef AF_FILE
+ "FILE", AF_FILE,
+#endif
+#ifdef AF_INET
+ "INET", AF_INET,
+#endif
+#ifdef AF_AX25
+ "AX25", AF_AX25,
+#endif
+#ifdef AF_IPX
+ "IPX", AF_IPX,
+#endif
+#ifdef AF_APPLETALK
+ "APPLETALK", AF_APPLETALK,
+#endif
+#ifdef AF_NETROM
+ "NETROM", AF_NETROM,
+#endif
+#ifdef AF_BRIDGE
+ "BRIDGE", AF_BRIDGE,
+#endif
+#ifdef AF_ATMPVC
+ "ATMPVC", AF_ATMPVC,
+#endif
+#ifdef AF_X25
+ "X25", AF_X25,
+#endif
+#ifdef AF_INET6
+ "INET6", AF_INET6,
+#endif
+#ifdef AF_ROSE
+ "ROSE", AF_ROSE,
+#endif
+#ifdef AF_DECnet
+ "DECnet", AF_DECnet,
+#endif
+#ifdef AF_NETBEUI
+ "NETBEUI", AF_NETBEUI,
+#endif
+#ifdef AF_SECURITY
+ "SECURITY", AF_SECURITY,
+#endif
+#ifdef AF_KEY
+ "KEY", AF_KEY,
+#endif
+#ifdef AF_NETLINK
+ "NETLINK", AF_NETLINK,
+#endif
+#ifdef AF_ROUTE
+ "ROUTE", AF_ROUTE,
+#endif
+#ifdef AF_PACKET
+ "PACKET", AF_PACKET,
+#endif
+#ifdef AF_ASH
+ "ASH", AF_ASH,
+#endif
+#ifdef AF_ECONET
+ "ECONET", AF_ECONET,
+#endif
+#ifdef AF_ATMSVC
+ "ATMSVC", AF_ATMSVC,
+#endif
+#ifdef AF_SNA
+ "SNA", AF_SNA,
+#endif
+#ifdef AF_IRDA
+ "IRDA", AF_IRDA,
+#endif
+#ifdef AF_PPPOX
+ "PPPOX", AF_PPPOX,
+#endif
+#ifdef AF_WANPIPE
+ "WANPIPE", AF_WANPIPE,
+#endif
+#ifdef AF_BLUETOOTH
+ "BLUETOOTH", AF_BLUETOOTH,
+#endif
+ 0
+};
+
+#endif
+
+int
+b_fds(int argc, char** argv, Shbltin_t* context)
+{
+ register char* s;
+ register int i;
+ register char* m;
+ register char* x;
+ int flags;
+ int details;
+ int open_max;
+ int unit;
+ Sfio_t* sp;
+ struct stat st;
+#ifdef S_IFSOCK
+ struct sockaddr_in addr;
+ char* a;
+ unsigned char* b;
+ unsigned char* e;
+ socklen_t addrlen;
+ socklen_t len;
+ int type;
+ int port;
+ int prot;
+ char num[64];
+ char fam[64];
+#ifdef INET6_ADDRSTRLEN
+ char nam[256];
+#endif
+#endif
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ details = 0;
+ unit = 1;
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'l':
+ details = opt_info.num;
+ continue;
+ case 'u':
+ unit = opt_info.num;
+ continue;
+ case '?':
+ error(ERROR_USAGE|4, "%s", opt_info.arg);
+ break;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors || *argv)
+ error(ERROR_USAGE|4, "%s", optusage(NiL));
+ if ((open_max = getconf("OPEN_MAX")) <= 0)
+ open_max = OPEN_MAX;
+ if (unit == 1)
+ sp = sfstdout;
+ else if (fstat(unit, &st) || !(sp = sfnew(NiL, NiL, SF_UNBOUND, unit, SF_WRITE)))
+ error(ERROR_SYSTEM|3, "%d: cannot write to file descriptor");
+ for (i = 0; i <= open_max; i++)
+ {
+ if (fstat(i, &st))
+ {
+ /* not open */
+ continue;
+ }
+ if (!details)
+ {
+ sfprintf(sp, "%d\n", i);
+ continue;
+ }
+ if ((flags = fcntl(i, F_GETFL, (char*)0)) == -1)
+ m = "--";
+ else
+ switch (flags & (O_RDONLY|O_WRONLY|O_RDWR))
+ {
+ case O_RDONLY:
+ m = "r-";
+ break;
+ case O_WRONLY:
+ m = "-w";
+ break;
+ case O_RDWR:
+ m = "rw";
+ break;
+ default:
+ m = "??";
+ break;
+ }
+ x = (fcntl(i, F_GETFD, (char*)0) > 0) ? "x" : "-";
+ if (isatty(i) && (s = ttyname(i)))
+ {
+ sfprintf(sp, "%02d %s%s %s %s\n", i, m, x, fmtmode(st.st_mode, 0), s);
+ continue;
+ }
+#ifdef S_IFSOCK
+ addrlen = sizeof(addr);
+ memset(&addr, 0, addrlen);
+ if (!getsockname(i, (struct sockaddr*)&addr, (void*)&addrlen))
+ {
+ type = 0;
+ prot = 0;
+#ifdef SO_TYPE
+ len = sizeof(type);
+ if (getsockopt(i, SOL_SOCKET, SO_TYPE, (void*)&type, (void*)&len))
+ type = -1;
+#endif
+#ifdef SO_PROTOTYPE
+ len = sizeof(prot);
+ if (getsockopt(i, SOL_SOCKET, SO_PROTOTYPE, (void*)&prot, (void*)&len))
+ prot = -1;
+#endif
+ if (!st.st_mode)
+ st.st_mode = S_IFSOCK|S_IRUSR|S_IWUSR;
+ s = 0;
+ switch (type)
+ {
+ case SOCK_DGRAM:
+ switch (addr.sin_family)
+ {
+ case AF_INET:
+#ifdef AF_INET6
+ case AF_INET6:
+#endif
+ s = "udp";
+ break;
+ }
+ break;
+ case SOCK_STREAM:
+ switch (addr.sin_family)
+ {
+ case AF_INET:
+#ifdef AF_INET6
+ case AF_INET6:
+#endif
+#ifdef IPPROTO_SCTP
+ if (prot == IPPROTO_SCTP)
+ s = "sctp";
+ else
+#endif
+ s = "tcp";
+ break;
+ }
+ break;
+#ifdef SOCK_RAW
+ case SOCK_RAW:
+ s = "raw";
+ break;
+#endif
+#ifdef SOCK_RDM
+ case SOCK_RDM:
+ s = "rdm";
+ break;
+#endif
+#ifdef SOCK_SEQPACKET
+ case SOCK_SEQPACKET:
+ s = "seqpacket";
+ break;
+#endif
+ }
+ if (!s)
+ {
+ for (type = 0; family[type].name && family[type].value != addr.sin_family; type++);
+ if (!(s = (char*)family[type].name))
+ sfsprintf(s = num, sizeof(num), "family.%d", addr.sin_family);
+ }
+ port = 0;
+#ifdef INET6_ADDRSTRLEN
+ if (a = (char*)inet_ntop(addr.sin_family, &addr.sin_addr, nam, sizeof(nam)))
+ port = ntohs(addr.sin_port);
+ else
+#endif
+ if (addr.sin_family == AF_INET)
+ {
+ a = inet_ntoa(addr.sin_addr);
+ port = ntohs(addr.sin_port);
+ }
+ else
+ {
+ a = fam;
+ e = (b = (unsigned char*)&addr) + addrlen;
+ while (b < e && a < &fam[sizeof(fam)-1])
+ a += sfsprintf(a, &fam[sizeof(fam)] - a - 1, ".%d", *b++);
+ a = a == fam ? "0" : fam + 1;
+ }
+ if (port)
+ sfprintf(sp, "%02d %s%s %s /dev/%s/%s/%d\n", i, m, x, fmtmode(st.st_mode, 0), s, a, port);
+ else
+ sfprintf(sp, "%02d %s%s %s /dev/%s/%s\n", i, m, x, fmtmode(st.st_mode, 0), s, a);
+ continue;
+ }
+#endif
+ sfprintf(sp, "%02d %s%s %s /dev/inode/%u/%u\n", i, m, x, fmtmode(st.st_mode, 0), st.st_dev, st.st_ino);
+ }
+ if (sp != sfstdout)
+ {
+ sfsetfd(sp, -1);
+ sfclose(sp);
+ }
+ return 0;
+}