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