fds.c revision da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968
/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1992-2007 AT&T Knowledge Ventures *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Knowledge Ventures *
* *
* A copy of the License is available at *
* http://www.opensource.org/licenses/cpl1.0.txt *
* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
* *
* 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) 2006-10-26 $\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.]"
"[+SEE ALSO?\blogname\b(1), \bwho\b(1), \bgetgroups\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
int
b_fds(int argc, char** argv, void* context)
{
register char* s;
register int i;
register char* m;
register char* x;
int flags;
int details;
struct stat st;
#ifdef S_IFSOCK
struct sockaddr_in addr;
socklen_t len;
int type;
int prot;
char num[32];
#endif
cmdinit(argc, argv, context, ERROR_CATALOG, 0);
details = 0;
for (;;)
{
switch (optget(argv, usage))
{
case 'l':
details = opt_info.num;
continue;
case '?':
error(ERROR_USAGE|4, "%s", opt_info.arg);
continue;
case ':':
error(2, "%s", opt_info.arg);
continue;
}
break;
}
argv += opt_info.index;
if (error_info.errors || *argv)
error(ERROR_USAGE|4, "%s", optusage(NiL));
for (i = 0; i <= OPEN_MAX; i++)
if (fstat(i, &st))
/* not open */;
else if (details)
{
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(sfstdout, "%02d %s%s %s %s\n", i, m, x, fmtmode(st.st_mode, 0), s);
#ifdef S_IFSOCK
else if ((len = sizeof(addr))
&& !getsockname(i, (struct sockaddr*)&addr, (void*)&len)
&& len == sizeof(addr)
&& addr.sin_family == AF_INET
#ifdef SO_TYPE
&& (len = sizeof(type))
&& !getsockopt(i, SOL_SOCKET, SO_TYPE, (void*)&type, (void*)&len)
&& len == sizeof(type)
#else
&& !(type = 0)
#endif
#ifdef SO_PROTOTYPE
&& (len = sizeof(prot))
&& (!getsockopt(i, SOL_SOCKET, SO_PROTOTYPE, (void*)&prot, (void*)&len) || !(prot = 0))
#else
&& !(prot = 0)
#endif
)
{
if (!st.st_mode)
st.st_mode = S_IFSOCK|S_IRUSR|S_IWUSR;
s = 0;
switch (type)
{
case SOCK_DGRAM:
s = "udp";
break;
case SOCK_STREAM:
if (prot == 0)
s = "tcp";
#ifdef IPPROTO_SCTP
else if (prot == IPPROTO_SCTP)
s = "sctp";
#endif
break;
}
if (!s)
sfprintf(sfstdout, s = num, "type.%d.prot.%d", type, prot);
sfprintf(sfstdout, "%02d %s%s %s /dev/%s/%s/%d\n", i, m, x, fmtmode(st.st_mode, 0), s, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
}
#endif
else
sfprintf(sfstdout, "%02d %s%s %s /dev/inode/%u/%u\n", i, m, x, fmtmode(st.st_mode, 0), st.st_dev, st.st_ino);
}
else
sfprintf(sfstdout, "%d\n", i);
return 0;
}