14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1992-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * Glenn Fowler <gsf@research.att.com> *
184887Schin * David Korn <dgk@research.att.com> *
194887Schin * *
204887Schin ***********************************************************************/
214887Schin #pragma prototyped
224887Schin
234887Schin static const char usage[] =
2410898Sroland.mainz@nrubsig.org "[-?\n@(#)$Id: fds (AT&T Research) 2009-09-09 $\n]"
254887Schin USAGE_LICENSE
264887Schin "[+NAME?fds - list open file descriptor status]"
274887Schin "[+DESCRIPTION?\bfds\b lists the status for each open file descriptor. "
284887Schin "When invoked as a shell builtin it accesses the file descriptors of the "
294887Schin "calling shell, otherwise it lists the file descriptors passed across "
304887Schin "\bexec\b(2).]"
314887Schin "[l:long?List file descriptor details.]"
3210898Sroland.mainz@nrubsig.org "[u:unit?Write output to \afd\a.]#[fd]"
338462SApril.Chin@Sun.COM "[+SEE ALSO?\blogname\b(1), \bwho\b(1), \bgetgroups\b(2), \bgetsockname\b(2), \bgetsockopts\b(2)]"
344887Schin ;
354887Schin
364887Schin #include <cmd.h>
374887Schin #include <ls.h>
384887Schin
394887Schin #include "FEATURE/sockets"
404887Schin
414887Schin #if defined(S_IFSOCK) && _sys_socket && _hdr_arpa_inet && _hdr_netinet_in && _lib_getsockname && _lib_getsockopt && _lib_inet_ntoa
424887Schin #include <sys/socket.h>
434887Schin #include <netinet/in.h>
444887Schin #include <arpa/inet.h>
454887Schin #else
464887Schin #undef S_IFSOCK
474887Schin #endif
484887Schin
494887Schin #ifndef minor
504887Schin #define minor(x) (int)((x)&0xff)
514887Schin #endif
524887Schin #ifndef major
534887Schin #define major(x) (int)(((unsigned int)(x)>>8)&0xff)
544887Schin #endif
554887Schin
568462SApril.Chin@Sun.COM #undef getconf
578462SApril.Chin@Sun.COM #define getconf(x) strtol(astconf(x,NiL,NiL),NiL,0)
588462SApril.Chin@Sun.COM
598462SApril.Chin@Sun.COM #ifdef S_IFSOCK
608462SApril.Chin@Sun.COM
618462SApril.Chin@Sun.COM typedef struct NV_s
628462SApril.Chin@Sun.COM {
638462SApril.Chin@Sun.COM const char* name;
648462SApril.Chin@Sun.COM int value;
658462SApril.Chin@Sun.COM } NV_t;
668462SApril.Chin@Sun.COM
678462SApril.Chin@Sun.COM static const NV_t family[] =
688462SApril.Chin@Sun.COM {
698462SApril.Chin@Sun.COM #ifdef AF_LOCAL
708462SApril.Chin@Sun.COM "pipe", AF_LOCAL,
718462SApril.Chin@Sun.COM #endif
728462SApril.Chin@Sun.COM #ifdef AF_UNIX
738462SApril.Chin@Sun.COM "pipe", AF_UNIX,
748462SApril.Chin@Sun.COM #endif
758462SApril.Chin@Sun.COM #ifdef AF_FILE
768462SApril.Chin@Sun.COM "FILE", AF_FILE,
778462SApril.Chin@Sun.COM #endif
788462SApril.Chin@Sun.COM #ifdef AF_INET
798462SApril.Chin@Sun.COM "INET", AF_INET,
808462SApril.Chin@Sun.COM #endif
818462SApril.Chin@Sun.COM #ifdef AF_AX25
828462SApril.Chin@Sun.COM "AX25", AF_AX25,
838462SApril.Chin@Sun.COM #endif
848462SApril.Chin@Sun.COM #ifdef AF_IPX
858462SApril.Chin@Sun.COM "IPX", AF_IPX,
868462SApril.Chin@Sun.COM #endif
878462SApril.Chin@Sun.COM #ifdef AF_APPLETALK
888462SApril.Chin@Sun.COM "APPLETALK", AF_APPLETALK,
898462SApril.Chin@Sun.COM #endif
908462SApril.Chin@Sun.COM #ifdef AF_NETROM
918462SApril.Chin@Sun.COM "NETROM", AF_NETROM,
928462SApril.Chin@Sun.COM #endif
938462SApril.Chin@Sun.COM #ifdef AF_BRIDGE
948462SApril.Chin@Sun.COM "BRIDGE", AF_BRIDGE,
958462SApril.Chin@Sun.COM #endif
968462SApril.Chin@Sun.COM #ifdef AF_ATMPVC
978462SApril.Chin@Sun.COM "ATMPVC", AF_ATMPVC,
988462SApril.Chin@Sun.COM #endif
998462SApril.Chin@Sun.COM #ifdef AF_X25
1008462SApril.Chin@Sun.COM "X25", AF_X25,
1018462SApril.Chin@Sun.COM #endif
1028462SApril.Chin@Sun.COM #ifdef AF_INET6
1038462SApril.Chin@Sun.COM "INET6", AF_INET6,
1048462SApril.Chin@Sun.COM #endif
1058462SApril.Chin@Sun.COM #ifdef AF_ROSE
1068462SApril.Chin@Sun.COM "ROSE", AF_ROSE,
1078462SApril.Chin@Sun.COM #endif
1088462SApril.Chin@Sun.COM #ifdef AF_DECnet
1098462SApril.Chin@Sun.COM "DECnet", AF_DECnet,
1108462SApril.Chin@Sun.COM #endif
1118462SApril.Chin@Sun.COM #ifdef AF_NETBEUI
1128462SApril.Chin@Sun.COM "NETBEUI", AF_NETBEUI,
1138462SApril.Chin@Sun.COM #endif
1148462SApril.Chin@Sun.COM #ifdef AF_SECURITY
1158462SApril.Chin@Sun.COM "SECURITY", AF_SECURITY,
1168462SApril.Chin@Sun.COM #endif
1178462SApril.Chin@Sun.COM #ifdef AF_KEY
1188462SApril.Chin@Sun.COM "KEY", AF_KEY,
1198462SApril.Chin@Sun.COM #endif
1208462SApril.Chin@Sun.COM #ifdef AF_NETLINK
1218462SApril.Chin@Sun.COM "NETLINK", AF_NETLINK,
1228462SApril.Chin@Sun.COM #endif
1238462SApril.Chin@Sun.COM #ifdef AF_ROUTE
1248462SApril.Chin@Sun.COM "ROUTE", AF_ROUTE,
1258462SApril.Chin@Sun.COM #endif
1268462SApril.Chin@Sun.COM #ifdef AF_PACKET
1278462SApril.Chin@Sun.COM "PACKET", AF_PACKET,
1288462SApril.Chin@Sun.COM #endif
1298462SApril.Chin@Sun.COM #ifdef AF_ASH
1308462SApril.Chin@Sun.COM "ASH", AF_ASH,
1318462SApril.Chin@Sun.COM #endif
1328462SApril.Chin@Sun.COM #ifdef AF_ECONET
1338462SApril.Chin@Sun.COM "ECONET", AF_ECONET,
1348462SApril.Chin@Sun.COM #endif
1358462SApril.Chin@Sun.COM #ifdef AF_ATMSVC
1368462SApril.Chin@Sun.COM "ATMSVC", AF_ATMSVC,
1378462SApril.Chin@Sun.COM #endif
1388462SApril.Chin@Sun.COM #ifdef AF_SNA
1398462SApril.Chin@Sun.COM "SNA", AF_SNA,
1408462SApril.Chin@Sun.COM #endif
1418462SApril.Chin@Sun.COM #ifdef AF_IRDA
1428462SApril.Chin@Sun.COM "IRDA", AF_IRDA,
1438462SApril.Chin@Sun.COM #endif
1448462SApril.Chin@Sun.COM #ifdef AF_PPPOX
1458462SApril.Chin@Sun.COM "PPPOX", AF_PPPOX,
1468462SApril.Chin@Sun.COM #endif
1478462SApril.Chin@Sun.COM #ifdef AF_WANPIPE
1488462SApril.Chin@Sun.COM "WANPIPE", AF_WANPIPE,
1498462SApril.Chin@Sun.COM #endif
1508462SApril.Chin@Sun.COM #ifdef AF_BLUETOOTH
1518462SApril.Chin@Sun.COM "BLUETOOTH", AF_BLUETOOTH,
1528462SApril.Chin@Sun.COM #endif
1538462SApril.Chin@Sun.COM 0
1548462SApril.Chin@Sun.COM };
1558462SApril.Chin@Sun.COM
1568462SApril.Chin@Sun.COM #endif
1578462SApril.Chin@Sun.COM
1584887Schin int
b_fds(int argc,char ** argv,void * context)1594887Schin b_fds(int argc, char** argv, void* context)
1604887Schin {
1614887Schin register char* s;
1624887Schin register int i;
1634887Schin register char* m;
1644887Schin register char* x;
1654887Schin int flags;
1664887Schin int details;
1678462SApril.Chin@Sun.COM int open_max;
16810898Sroland.mainz@nrubsig.org int unit;
16910898Sroland.mainz@nrubsig.org Sfio_t* sp;
1704887Schin struct stat st;
1714887Schin #ifdef S_IFSOCK
1724887Schin struct sockaddr_in addr;
1738462SApril.Chin@Sun.COM char* a;
1748462SApril.Chin@Sun.COM unsigned char* b;
1758462SApril.Chin@Sun.COM unsigned char* e;
1768462SApril.Chin@Sun.COM socklen_t addrlen;
1774887Schin socklen_t len;
1784887Schin int type;
1798462SApril.Chin@Sun.COM int port;
1804887Schin int prot;
1818462SApril.Chin@Sun.COM char num[64];
1828462SApril.Chin@Sun.COM char fam[64];
18310898Sroland.mainz@nrubsig.org #ifdef INET6_ADDRSTRLEN
18410898Sroland.mainz@nrubsig.org char nam[256];
18510898Sroland.mainz@nrubsig.org #endif
1864887Schin #endif
1874887Schin
1884887Schin cmdinit(argc, argv, context, ERROR_CATALOG, 0);
1894887Schin details = 0;
19010898Sroland.mainz@nrubsig.org unit = 1;
1914887Schin for (;;)
1924887Schin {
1934887Schin switch (optget(argv, usage))
1944887Schin {
1954887Schin case 'l':
1964887Schin details = opt_info.num;
1974887Schin continue;
19810898Sroland.mainz@nrubsig.org case 'u':
19910898Sroland.mainz@nrubsig.org unit = opt_info.num;
20010898Sroland.mainz@nrubsig.org continue;
2014887Schin case '?':
2024887Schin error(ERROR_USAGE|4, "%s", opt_info.arg);
2034887Schin continue;
2044887Schin case ':':
2054887Schin error(2, "%s", opt_info.arg);
2064887Schin continue;
2074887Schin }
2084887Schin break;
2094887Schin }
2104887Schin argv += opt_info.index;
2114887Schin if (error_info.errors || *argv)
2124887Schin error(ERROR_USAGE|4, "%s", optusage(NiL));
2138462SApril.Chin@Sun.COM if ((open_max = getconf("OPEN_MAX")) <= 0)
2148462SApril.Chin@Sun.COM open_max = OPEN_MAX;
21510898Sroland.mainz@nrubsig.org if (unit == 1)
21610898Sroland.mainz@nrubsig.org sp = sfstdout;
21710898Sroland.mainz@nrubsig.org else if (fstat(unit, &st) || !(sp = sfnew(NiL, NiL, SF_UNBOUND, unit, SF_WRITE)))
21810898Sroland.mainz@nrubsig.org error(ERROR_SYSTEM|3, "%d: cannot write to file descriptor");
2198462SApril.Chin@Sun.COM for (i = 0; i <= open_max; i++)
2208462SApril.Chin@Sun.COM {
2214887Schin if (fstat(i, &st))
2228462SApril.Chin@Sun.COM {
2238462SApril.Chin@Sun.COM /* not open */
2248462SApril.Chin@Sun.COM continue;
2258462SApril.Chin@Sun.COM }
2268462SApril.Chin@Sun.COM if (!details)
2274887Schin {
22810898Sroland.mainz@nrubsig.org sfprintf(sp, "%d\n", i);
2298462SApril.Chin@Sun.COM continue;
2308462SApril.Chin@Sun.COM }
2318462SApril.Chin@Sun.COM if ((flags = fcntl(i, F_GETFL, (char*)0)) == -1)
2328462SApril.Chin@Sun.COM m = "--";
2338462SApril.Chin@Sun.COM else
2348462SApril.Chin@Sun.COM switch (flags & (O_RDONLY|O_WRONLY|O_RDWR))
2358462SApril.Chin@Sun.COM {
2368462SApril.Chin@Sun.COM case O_RDONLY:
2378462SApril.Chin@Sun.COM m = "r-";
2388462SApril.Chin@Sun.COM break;
2398462SApril.Chin@Sun.COM case O_WRONLY:
2408462SApril.Chin@Sun.COM m = "-w";
2418462SApril.Chin@Sun.COM break;
2428462SApril.Chin@Sun.COM case O_RDWR:
2438462SApril.Chin@Sun.COM m = "rw";
2448462SApril.Chin@Sun.COM break;
2458462SApril.Chin@Sun.COM default:
2468462SApril.Chin@Sun.COM m = "??";
2478462SApril.Chin@Sun.COM break;
2488462SApril.Chin@Sun.COM }
2498462SApril.Chin@Sun.COM x = (fcntl(i, F_GETFD, (char*)0) > 0) ? "x" : "-";
2508462SApril.Chin@Sun.COM if (isatty(i) && (s = ttyname(i)))
2518462SApril.Chin@Sun.COM {
25210898Sroland.mainz@nrubsig.org sfprintf(sp, "%02d %s%s %s %s\n", i, m, x, fmtmode(st.st_mode, 0), s);
2538462SApril.Chin@Sun.COM continue;
2548462SApril.Chin@Sun.COM }
2558462SApril.Chin@Sun.COM #ifdef S_IFSOCK
2568462SApril.Chin@Sun.COM addrlen = sizeof(addr);
2578462SApril.Chin@Sun.COM memset(&addr, 0, addrlen);
2588462SApril.Chin@Sun.COM if (!getsockname(i, (struct sockaddr*)&addr, (void*)&addrlen))
2598462SApril.Chin@Sun.COM {
2608462SApril.Chin@Sun.COM type = 0;
2618462SApril.Chin@Sun.COM prot = 0;
2628462SApril.Chin@Sun.COM #ifdef SO_TYPE
2638462SApril.Chin@Sun.COM len = sizeof(type);
2648462SApril.Chin@Sun.COM if (getsockopt(i, SOL_SOCKET, SO_TYPE, (void*)&type, (void*)&len))
2658462SApril.Chin@Sun.COM type = -1;
2668462SApril.Chin@Sun.COM #endif
2678462SApril.Chin@Sun.COM #ifdef SO_PROTOTYPE
2688462SApril.Chin@Sun.COM len = sizeof(prot);
2698462SApril.Chin@Sun.COM if (getsockopt(i, SOL_SOCKET, SO_PROTOTYPE, (void*)&prot, (void*)&len))
2708462SApril.Chin@Sun.COM prot = -1;
2718462SApril.Chin@Sun.COM #endif
2728462SApril.Chin@Sun.COM if (!st.st_mode)
2738462SApril.Chin@Sun.COM st.st_mode = S_IFSOCK|S_IRUSR|S_IWUSR;
2748462SApril.Chin@Sun.COM s = 0;
2758462SApril.Chin@Sun.COM switch (type)
2768462SApril.Chin@Sun.COM {
2778462SApril.Chin@Sun.COM case SOCK_DGRAM:
2788462SApril.Chin@Sun.COM switch (addr.sin_family)
2794887Schin {
2808462SApril.Chin@Sun.COM case AF_INET:
2818462SApril.Chin@Sun.COM #ifdef AF_INET6
2828462SApril.Chin@Sun.COM case AF_INET6:
2838462SApril.Chin@Sun.COM #endif
2848462SApril.Chin@Sun.COM s = "udp";
2854887Schin break;
2864887Schin }
2878462SApril.Chin@Sun.COM break;
2888462SApril.Chin@Sun.COM case SOCK_STREAM:
2898462SApril.Chin@Sun.COM switch (addr.sin_family)
2908462SApril.Chin@Sun.COM {
2918462SApril.Chin@Sun.COM case AF_INET:
2928462SApril.Chin@Sun.COM #ifdef AF_INET6
2938462SApril.Chin@Sun.COM case AF_INET6:
2944887Schin #endif
2958462SApril.Chin@Sun.COM #ifdef IPPROTO_SCTP
2968462SApril.Chin@Sun.COM if (prot == IPPROTO_SCTP)
2978462SApril.Chin@Sun.COM s = "sctp";
2988462SApril.Chin@Sun.COM else
2994887Schin #endif
3004887Schin s = "tcp";
3014887Schin break;
3024887Schin }
3038462SApril.Chin@Sun.COM break;
3048462SApril.Chin@Sun.COM #ifdef SOCK_RAW
3058462SApril.Chin@Sun.COM case SOCK_RAW:
3068462SApril.Chin@Sun.COM s = "raw";
3078462SApril.Chin@Sun.COM break;
3088462SApril.Chin@Sun.COM #endif
3098462SApril.Chin@Sun.COM #ifdef SOCK_RDM
3108462SApril.Chin@Sun.COM case SOCK_RDM:
3118462SApril.Chin@Sun.COM s = "rdm";
3128462SApril.Chin@Sun.COM break;
3138462SApril.Chin@Sun.COM #endif
3148462SApril.Chin@Sun.COM #ifdef SOCK_SEQPACKET
3158462SApril.Chin@Sun.COM case SOCK_SEQPACKET:
3168462SApril.Chin@Sun.COM s = "seqpacket";
3178462SApril.Chin@Sun.COM break;
3184887Schin #endif
3198462SApril.Chin@Sun.COM }
3208462SApril.Chin@Sun.COM if (!s)
3218462SApril.Chin@Sun.COM {
3228462SApril.Chin@Sun.COM for (type = 0; family[type].name && family[type].value != addr.sin_family; type++);
3238462SApril.Chin@Sun.COM if (!(s = (char*)family[type].name))
3248462SApril.Chin@Sun.COM sfsprintf(s = num, sizeof(num), "family.%d", addr.sin_family);
3258462SApril.Chin@Sun.COM }
3268462SApril.Chin@Sun.COM port = 0;
3278462SApril.Chin@Sun.COM #ifdef INET6_ADDRSTRLEN
3288462SApril.Chin@Sun.COM if (a = (char*)inet_ntop(addr.sin_family, &addr.sin_addr, nam, sizeof(nam)))
3298462SApril.Chin@Sun.COM port = ntohs(addr.sin_port);
3304887Schin else
3318462SApril.Chin@Sun.COM #endif
3328462SApril.Chin@Sun.COM if (addr.sin_family == AF_INET)
3338462SApril.Chin@Sun.COM {
3348462SApril.Chin@Sun.COM a = inet_ntoa(addr.sin_addr);
3358462SApril.Chin@Sun.COM port = ntohs(addr.sin_port);
3368462SApril.Chin@Sun.COM }
3378462SApril.Chin@Sun.COM else
3388462SApril.Chin@Sun.COM {
3398462SApril.Chin@Sun.COM a = fam;
3408462SApril.Chin@Sun.COM e = (b = (unsigned char*)&addr) + addrlen;
3418462SApril.Chin@Sun.COM while (b < e && a < &fam[sizeof(fam)-1])
3428462SApril.Chin@Sun.COM a += sfsprintf(a, &fam[sizeof(fam)] - a - 1, ".%d", *b++);
3438462SApril.Chin@Sun.COM a = a == fam ? "0" : fam + 1;
3448462SApril.Chin@Sun.COM }
3458462SApril.Chin@Sun.COM if (port)
34610898Sroland.mainz@nrubsig.org sfprintf(sp, "%02d %s%s %s /dev/%s/%s/%d\n", i, m, x, fmtmode(st.st_mode, 0), s, a, port);
3478462SApril.Chin@Sun.COM else
34810898Sroland.mainz@nrubsig.org sfprintf(sp, "%02d %s%s %s /dev/%s/%s\n", i, m, x, fmtmode(st.st_mode, 0), s, a);
3498462SApril.Chin@Sun.COM continue;
3504887Schin }
3518462SApril.Chin@Sun.COM #endif
35210898Sroland.mainz@nrubsig.org 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);
35310898Sroland.mainz@nrubsig.org }
35410898Sroland.mainz@nrubsig.org if (sp != sfstdout)
35510898Sroland.mainz@nrubsig.org {
35610898Sroland.mainz@nrubsig.org sfsetfd(sp, -1);
35710898Sroland.mainz@nrubsig.org sfclose(sp);
3588462SApril.Chin@Sun.COM }
3594887Schin return 0;
3604887Schin }
361