1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1992-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * Glenn Fowler <gsf@research.att.com> *
18da2e3ebdSchin * David Korn <dgk@research.att.com> *
19da2e3ebdSchin * *
20da2e3ebdSchin ***********************************************************************/
21da2e3ebdSchin #pragma prototyped
22da2e3ebdSchin
23da2e3ebdSchin static const char usage[] =
2434f9b3eeSRoland Mainz "[-?\n@(#)$Id: fds (AT&T Research) 2009-09-09 $\n]"
25da2e3ebdSchin USAGE_LICENSE
26da2e3ebdSchin "[+NAME?fds - list open file descriptor status]"
27da2e3ebdSchin "[+DESCRIPTION?\bfds\b lists the status for each open file descriptor. "
28da2e3ebdSchin "When invoked as a shell builtin it accesses the file descriptors of the "
29da2e3ebdSchin "calling shell, otherwise it lists the file descriptors passed across "
30da2e3ebdSchin "\bexec\b(2).]"
31da2e3ebdSchin "[l:long?List file descriptor details.]"
3234f9b3eeSRoland Mainz "[u:unit?Write output to \afd\a.]#[fd]"
337c2fbfb3SApril Chin "[+SEE ALSO?\blogname\b(1), \bwho\b(1), \bgetgroups\b(2), \bgetsockname\b(2), \bgetsockopts\b(2)]"
34da2e3ebdSchin ;
35da2e3ebdSchin
36da2e3ebdSchin #include <cmd.h>
37da2e3ebdSchin #include <ls.h>
38da2e3ebdSchin
39da2e3ebdSchin #include "FEATURE/sockets"
40da2e3ebdSchin
41da2e3ebdSchin #if defined(S_IFSOCK) && _sys_socket && _hdr_arpa_inet && _hdr_netinet_in && _lib_getsockname && _lib_getsockopt && _lib_inet_ntoa
42da2e3ebdSchin #include <sys/socket.h>
43da2e3ebdSchin #include <netinet/in.h>
44da2e3ebdSchin #include <arpa/inet.h>
45da2e3ebdSchin #else
46da2e3ebdSchin #undef S_IFSOCK
47da2e3ebdSchin #endif
48da2e3ebdSchin
49da2e3ebdSchin #ifndef minor
50da2e3ebdSchin #define minor(x) (int)((x)&0xff)
51da2e3ebdSchin #endif
52da2e3ebdSchin #ifndef major
53da2e3ebdSchin #define major(x) (int)(((unsigned int)(x)>>8)&0xff)
54da2e3ebdSchin #endif
55da2e3ebdSchin
567c2fbfb3SApril Chin #undef getconf
577c2fbfb3SApril Chin #define getconf(x) strtol(astconf(x,NiL,NiL),NiL,0)
587c2fbfb3SApril Chin
597c2fbfb3SApril Chin #ifdef S_IFSOCK
607c2fbfb3SApril Chin
617c2fbfb3SApril Chin typedef struct NV_s
627c2fbfb3SApril Chin {
637c2fbfb3SApril Chin const char* name;
647c2fbfb3SApril Chin int value;
657c2fbfb3SApril Chin } NV_t;
667c2fbfb3SApril Chin
677c2fbfb3SApril Chin static const NV_t family[] =
687c2fbfb3SApril Chin {
697c2fbfb3SApril Chin #ifdef AF_LOCAL
707c2fbfb3SApril Chin "pipe", AF_LOCAL,
717c2fbfb3SApril Chin #endif
727c2fbfb3SApril Chin #ifdef AF_UNIX
737c2fbfb3SApril Chin "pipe", AF_UNIX,
747c2fbfb3SApril Chin #endif
757c2fbfb3SApril Chin #ifdef AF_FILE
767c2fbfb3SApril Chin "FILE", AF_FILE,
777c2fbfb3SApril Chin #endif
787c2fbfb3SApril Chin #ifdef AF_INET
797c2fbfb3SApril Chin "INET", AF_INET,
807c2fbfb3SApril Chin #endif
817c2fbfb3SApril Chin #ifdef AF_AX25
827c2fbfb3SApril Chin "AX25", AF_AX25,
837c2fbfb3SApril Chin #endif
847c2fbfb3SApril Chin #ifdef AF_IPX
857c2fbfb3SApril Chin "IPX", AF_IPX,
867c2fbfb3SApril Chin #endif
877c2fbfb3SApril Chin #ifdef AF_APPLETALK
887c2fbfb3SApril Chin "APPLETALK", AF_APPLETALK,
897c2fbfb3SApril Chin #endif
907c2fbfb3SApril Chin #ifdef AF_NETROM
917c2fbfb3SApril Chin "NETROM", AF_NETROM,
927c2fbfb3SApril Chin #endif
937c2fbfb3SApril Chin #ifdef AF_BRIDGE
947c2fbfb3SApril Chin "BRIDGE", AF_BRIDGE,
957c2fbfb3SApril Chin #endif
967c2fbfb3SApril Chin #ifdef AF_ATMPVC
977c2fbfb3SApril Chin "ATMPVC", AF_ATMPVC,
987c2fbfb3SApril Chin #endif
997c2fbfb3SApril Chin #ifdef AF_X25
1007c2fbfb3SApril Chin "X25", AF_X25,
1017c2fbfb3SApril Chin #endif
1027c2fbfb3SApril Chin #ifdef AF_INET6
1037c2fbfb3SApril Chin "INET6", AF_INET6,
1047c2fbfb3SApril Chin #endif
1057c2fbfb3SApril Chin #ifdef AF_ROSE
1067c2fbfb3SApril Chin "ROSE", AF_ROSE,
1077c2fbfb3SApril Chin #endif
1087c2fbfb3SApril Chin #ifdef AF_DECnet
1097c2fbfb3SApril Chin "DECnet", AF_DECnet,
1107c2fbfb3SApril Chin #endif
1117c2fbfb3SApril Chin #ifdef AF_NETBEUI
1127c2fbfb3SApril Chin "NETBEUI", AF_NETBEUI,
1137c2fbfb3SApril Chin #endif
1147c2fbfb3SApril Chin #ifdef AF_SECURITY
1157c2fbfb3SApril Chin "SECURITY", AF_SECURITY,
1167c2fbfb3SApril Chin #endif
1177c2fbfb3SApril Chin #ifdef AF_KEY
1187c2fbfb3SApril Chin "KEY", AF_KEY,
1197c2fbfb3SApril Chin #endif
1207c2fbfb3SApril Chin #ifdef AF_NETLINK
1217c2fbfb3SApril Chin "NETLINK", AF_NETLINK,
1227c2fbfb3SApril Chin #endif
1237c2fbfb3SApril Chin #ifdef AF_ROUTE
1247c2fbfb3SApril Chin "ROUTE", AF_ROUTE,
1257c2fbfb3SApril Chin #endif
1267c2fbfb3SApril Chin #ifdef AF_PACKET
1277c2fbfb3SApril Chin "PACKET", AF_PACKET,
1287c2fbfb3SApril Chin #endif
1297c2fbfb3SApril Chin #ifdef AF_ASH
1307c2fbfb3SApril Chin "ASH", AF_ASH,
1317c2fbfb3SApril Chin #endif
1327c2fbfb3SApril Chin #ifdef AF_ECONET
1337c2fbfb3SApril Chin "ECONET", AF_ECONET,
1347c2fbfb3SApril Chin #endif
1357c2fbfb3SApril Chin #ifdef AF_ATMSVC
1367c2fbfb3SApril Chin "ATMSVC", AF_ATMSVC,
1377c2fbfb3SApril Chin #endif
1387c2fbfb3SApril Chin #ifdef AF_SNA
1397c2fbfb3SApril Chin "SNA", AF_SNA,
1407c2fbfb3SApril Chin #endif
1417c2fbfb3SApril Chin #ifdef AF_IRDA
1427c2fbfb3SApril Chin "IRDA", AF_IRDA,
1437c2fbfb3SApril Chin #endif
1447c2fbfb3SApril Chin #ifdef AF_PPPOX
1457c2fbfb3SApril Chin "PPPOX", AF_PPPOX,
1467c2fbfb3SApril Chin #endif
1477c2fbfb3SApril Chin #ifdef AF_WANPIPE
1487c2fbfb3SApril Chin "WANPIPE", AF_WANPIPE,
1497c2fbfb3SApril Chin #endif
1507c2fbfb3SApril Chin #ifdef AF_BLUETOOTH
1517c2fbfb3SApril Chin "BLUETOOTH", AF_BLUETOOTH,
1527c2fbfb3SApril Chin #endif
1537c2fbfb3SApril Chin 0
1547c2fbfb3SApril Chin };
1557c2fbfb3SApril Chin
1567c2fbfb3SApril Chin #endif
1577c2fbfb3SApril Chin
158da2e3ebdSchin int
b_fds(int argc,char ** argv,void * context)159da2e3ebdSchin b_fds(int argc, char** argv, void* context)
160da2e3ebdSchin {
161da2e3ebdSchin register char* s;
162da2e3ebdSchin register int i;
163da2e3ebdSchin register char* m;
164da2e3ebdSchin register char* x;
165da2e3ebdSchin int flags;
166da2e3ebdSchin int details;
1677c2fbfb3SApril Chin int open_max;
16834f9b3eeSRoland Mainz int unit;
16934f9b3eeSRoland Mainz Sfio_t* sp;
170da2e3ebdSchin struct stat st;
171da2e3ebdSchin #ifdef S_IFSOCK
172da2e3ebdSchin struct sockaddr_in addr;
1737c2fbfb3SApril Chin char* a;
1747c2fbfb3SApril Chin unsigned char* b;
1757c2fbfb3SApril Chin unsigned char* e;
1767c2fbfb3SApril Chin socklen_t addrlen;
177da2e3ebdSchin socklen_t len;
178da2e3ebdSchin int type;
1797c2fbfb3SApril Chin int port;
180da2e3ebdSchin int prot;
1817c2fbfb3SApril Chin char num[64];
1827c2fbfb3SApril Chin char fam[64];
18334f9b3eeSRoland Mainz #ifdef INET6_ADDRSTRLEN
18434f9b3eeSRoland Mainz char nam[256];
18534f9b3eeSRoland Mainz #endif
186da2e3ebdSchin #endif
187da2e3ebdSchin
188da2e3ebdSchin cmdinit(argc, argv, context, ERROR_CATALOG, 0);
189da2e3ebdSchin details = 0;
19034f9b3eeSRoland Mainz unit = 1;
191da2e3ebdSchin for (;;)
192da2e3ebdSchin {
193da2e3ebdSchin switch (optget(argv, usage))
194da2e3ebdSchin {
195da2e3ebdSchin case 'l':
196da2e3ebdSchin details = opt_info.num;
197da2e3ebdSchin continue;
19834f9b3eeSRoland Mainz case 'u':
19934f9b3eeSRoland Mainz unit = opt_info.num;
20034f9b3eeSRoland Mainz continue;
201da2e3ebdSchin case '?':
202da2e3ebdSchin error(ERROR_USAGE|4, "%s", opt_info.arg);
203da2e3ebdSchin continue;
204da2e3ebdSchin case ':':
205da2e3ebdSchin error(2, "%s", opt_info.arg);
206da2e3ebdSchin continue;
207da2e3ebdSchin }
208da2e3ebdSchin break;
209da2e3ebdSchin }
210da2e3ebdSchin argv += opt_info.index;
211da2e3ebdSchin if (error_info.errors || *argv)
212da2e3ebdSchin error(ERROR_USAGE|4, "%s", optusage(NiL));
2137c2fbfb3SApril Chin if ((open_max = getconf("OPEN_MAX")) <= 0)
2147c2fbfb3SApril Chin open_max = OPEN_MAX;
21534f9b3eeSRoland Mainz if (unit == 1)
21634f9b3eeSRoland Mainz sp = sfstdout;
21734f9b3eeSRoland Mainz else if (fstat(unit, &st) || !(sp = sfnew(NiL, NiL, SF_UNBOUND, unit, SF_WRITE)))
21834f9b3eeSRoland Mainz error(ERROR_SYSTEM|3, "%d: cannot write to file descriptor");
2197c2fbfb3SApril Chin for (i = 0; i <= open_max; i++)
220da2e3ebdSchin {
2217c2fbfb3SApril Chin if (fstat(i, &st))
2227c2fbfb3SApril Chin {
2237c2fbfb3SApril Chin /* not open */
2247c2fbfb3SApril Chin continue;
2257c2fbfb3SApril Chin }
2267c2fbfb3SApril Chin if (!details)
2277c2fbfb3SApril Chin {
22834f9b3eeSRoland Mainz sfprintf(sp, "%d\n", i);
2297c2fbfb3SApril Chin continue;
2307c2fbfb3SApril Chin }
231da2e3ebdSchin if ((flags = fcntl(i, F_GETFL, (char*)0)) == -1)
232da2e3ebdSchin m = "--";
233da2e3ebdSchin else
234da2e3ebdSchin switch (flags & (O_RDONLY|O_WRONLY|O_RDWR))
235da2e3ebdSchin {
236da2e3ebdSchin case O_RDONLY:
237da2e3ebdSchin m = "r-";
238da2e3ebdSchin break;
239da2e3ebdSchin case O_WRONLY:
240da2e3ebdSchin m = "-w";
241da2e3ebdSchin break;
242da2e3ebdSchin case O_RDWR:
243da2e3ebdSchin m = "rw";
244da2e3ebdSchin break;
245da2e3ebdSchin default:
246da2e3ebdSchin m = "??";
247da2e3ebdSchin break;
248da2e3ebdSchin }
249da2e3ebdSchin x = (fcntl(i, F_GETFD, (char*)0) > 0) ? "x" : "-";
250da2e3ebdSchin if (isatty(i) && (s = ttyname(i)))
2517c2fbfb3SApril Chin {
25234f9b3eeSRoland Mainz sfprintf(sp, "%02d %s%s %s %s\n", i, m, x, fmtmode(st.st_mode, 0), s);
2537c2fbfb3SApril Chin continue;
2547c2fbfb3SApril Chin }
255da2e3ebdSchin #ifdef S_IFSOCK
2567c2fbfb3SApril Chin addrlen = sizeof(addr);
2577c2fbfb3SApril Chin memset(&addr, 0, addrlen);
2587c2fbfb3SApril Chin if (!getsockname(i, (struct sockaddr*)&addr, (void*)&addrlen))
2597c2fbfb3SApril Chin {
2607c2fbfb3SApril Chin type = 0;
2617c2fbfb3SApril Chin prot = 0;
262da2e3ebdSchin #ifdef SO_TYPE
2637c2fbfb3SApril Chin len = sizeof(type);
2647c2fbfb3SApril Chin if (getsockopt(i, SOL_SOCKET, SO_TYPE, (void*)&type, (void*)&len))
2657c2fbfb3SApril Chin type = -1;
266da2e3ebdSchin #endif
267da2e3ebdSchin #ifdef SO_PROTOTYPE
2687c2fbfb3SApril Chin len = sizeof(prot);
2697c2fbfb3SApril Chin if (getsockopt(i, SOL_SOCKET, SO_PROTOTYPE, (void*)&prot, (void*)&len))
2707c2fbfb3SApril Chin prot = -1;
271da2e3ebdSchin #endif
272da2e3ebdSchin if (!st.st_mode)
273da2e3ebdSchin st.st_mode = S_IFSOCK|S_IRUSR|S_IWUSR;
274da2e3ebdSchin s = 0;
275da2e3ebdSchin switch (type)
276da2e3ebdSchin {
277da2e3ebdSchin case SOCK_DGRAM:
2787c2fbfb3SApril Chin switch (addr.sin_family)
2797c2fbfb3SApril Chin {
2807c2fbfb3SApril Chin case AF_INET:
2817c2fbfb3SApril Chin #ifdef AF_INET6
2827c2fbfb3SApril Chin case AF_INET6:
2837c2fbfb3SApril Chin #endif
284da2e3ebdSchin s = "udp";
285da2e3ebdSchin break;
2867c2fbfb3SApril Chin }
2877c2fbfb3SApril Chin break;
288da2e3ebdSchin case SOCK_STREAM:
2897c2fbfb3SApril Chin switch (addr.sin_family)
2907c2fbfb3SApril Chin {
2917c2fbfb3SApril Chin case AF_INET:
2927c2fbfb3SApril Chin #ifdef AF_INET6
2937c2fbfb3SApril Chin case AF_INET6:
294da2e3ebdSchin #endif
2957c2fbfb3SApril Chin #ifdef IPPROTO_SCTP
2967c2fbfb3SApril Chin if (prot == IPPROTO_SCTP)
2977c2fbfb3SApril Chin s = "sctp";
2987c2fbfb3SApril Chin else
2997c2fbfb3SApril Chin #endif
3007c2fbfb3SApril Chin s = "tcp";
301da2e3ebdSchin break;
302da2e3ebdSchin }
3037c2fbfb3SApril Chin break;
3047c2fbfb3SApril Chin #ifdef SOCK_RAW
3057c2fbfb3SApril Chin case SOCK_RAW:
3067c2fbfb3SApril Chin s = "raw";
3077c2fbfb3SApril Chin break;
3087c2fbfb3SApril Chin #endif
3097c2fbfb3SApril Chin #ifdef SOCK_RDM
3107c2fbfb3SApril Chin case SOCK_RDM:
3117c2fbfb3SApril Chin s = "rdm";
3127c2fbfb3SApril Chin break;
3137c2fbfb3SApril Chin #endif
3147c2fbfb3SApril Chin #ifdef SOCK_SEQPACKET
3157c2fbfb3SApril Chin case SOCK_SEQPACKET:
3167c2fbfb3SApril Chin s = "seqpacket";
3177c2fbfb3SApril Chin break;
3187c2fbfb3SApril Chin #endif
3197c2fbfb3SApril Chin }
320da2e3ebdSchin if (!s)
3217c2fbfb3SApril Chin {
3227c2fbfb3SApril Chin for (type = 0; family[type].name && family[type].value != addr.sin_family; type++);
3237c2fbfb3SApril Chin if (!(s = (char*)family[type].name))
3247c2fbfb3SApril Chin sfsprintf(s = num, sizeof(num), "family.%d", addr.sin_family);
3257c2fbfb3SApril Chin }
3267c2fbfb3SApril Chin port = 0;
3277c2fbfb3SApril Chin #ifdef INET6_ADDRSTRLEN
3287c2fbfb3SApril Chin if (a = (char*)inet_ntop(addr.sin_family, &addr.sin_addr, nam, sizeof(nam)))
3297c2fbfb3SApril Chin port = ntohs(addr.sin_port);
3307c2fbfb3SApril Chin else
3317c2fbfb3SApril Chin #endif
3327c2fbfb3SApril Chin if (addr.sin_family == AF_INET)
3337c2fbfb3SApril Chin {
3347c2fbfb3SApril Chin a = inet_ntoa(addr.sin_addr);
3357c2fbfb3SApril Chin port = ntohs(addr.sin_port);
3367c2fbfb3SApril Chin }
3377c2fbfb3SApril Chin else
3387c2fbfb3SApril Chin {
3397c2fbfb3SApril Chin a = fam;
3407c2fbfb3SApril Chin e = (b = (unsigned char*)&addr) + addrlen;
3417c2fbfb3SApril Chin while (b < e && a < &fam[sizeof(fam)-1])
3427c2fbfb3SApril Chin a += sfsprintf(a, &fam[sizeof(fam)] - a - 1, ".%d", *b++);
3437c2fbfb3SApril Chin a = a == fam ? "0" : fam + 1;
3447c2fbfb3SApril Chin }
3457c2fbfb3SApril Chin if (port)
34634f9b3eeSRoland Mainz sfprintf(sp, "%02d %s%s %s /dev/%s/%s/%d\n", i, m, x, fmtmode(st.st_mode, 0), s, a, port);
3477c2fbfb3SApril Chin else
34834f9b3eeSRoland Mainz sfprintf(sp, "%02d %s%s %s /dev/%s/%s\n", i, m, x, fmtmode(st.st_mode, 0), s, a);
3497c2fbfb3SApril Chin continue;
350da2e3ebdSchin }
351da2e3ebdSchin #endif
35234f9b3eeSRoland Mainz 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);
35334f9b3eeSRoland Mainz }
35434f9b3eeSRoland Mainz if (sp != sfstdout)
35534f9b3eeSRoland Mainz {
35634f9b3eeSRoland Mainz sfsetfd(sp, -1);
35734f9b3eeSRoland Mainz sfclose(sp);
358da2e3ebdSchin }
359da2e3ebdSchin return 0;
360da2e3ebdSchin }
361