xref: /onnv-gate/usr/src/lib/libcmd/common/fds.c (revision 8462)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*8462SApril.Chin@Sun.COM *          Copyright (c) 1992-2008 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
7*8462SApril.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[] =
24*8462SApril.Chin@Sun.COM "[-?\n@(#)$Id: fds (AT&T Research) 2008-08-26 $\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.]"
32*8462SApril.Chin@Sun.COM "[+SEE ALSO?\blogname\b(1), \bwho\b(1), \bgetgroups\b(2), \bgetsockname\b(2), \bgetsockopts\b(2)]"
334887Schin ;
344887Schin 
354887Schin #include <cmd.h>
364887Schin #include <ls.h>
374887Schin 
384887Schin #include "FEATURE/sockets"
394887Schin 
404887Schin #if defined(S_IFSOCK) && _sys_socket && _hdr_arpa_inet && _hdr_netinet_in && _lib_getsockname && _lib_getsockopt && _lib_inet_ntoa
414887Schin #include <sys/socket.h>
424887Schin #include <netinet/in.h>
434887Schin #include <arpa/inet.h>
444887Schin #else
454887Schin #undef	S_IFSOCK
464887Schin #endif
474887Schin 
484887Schin #ifndef minor
494887Schin #define minor(x)	(int)((x)&0xff)
504887Schin #endif
514887Schin #ifndef major
524887Schin #define major(x)	(int)(((unsigned int)(x)>>8)&0xff)
534887Schin #endif
544887Schin 
55*8462SApril.Chin@Sun.COM #undef	getconf
56*8462SApril.Chin@Sun.COM #define getconf(x)	strtol(astconf(x,NiL,NiL),NiL,0)
57*8462SApril.Chin@Sun.COM 
58*8462SApril.Chin@Sun.COM #ifdef S_IFSOCK
59*8462SApril.Chin@Sun.COM 
60*8462SApril.Chin@Sun.COM typedef struct NV_s
61*8462SApril.Chin@Sun.COM {
62*8462SApril.Chin@Sun.COM 	const char*	name;
63*8462SApril.Chin@Sun.COM 	int		value;
64*8462SApril.Chin@Sun.COM } NV_t;
65*8462SApril.Chin@Sun.COM 
66*8462SApril.Chin@Sun.COM static const NV_t	family[] =
67*8462SApril.Chin@Sun.COM {
68*8462SApril.Chin@Sun.COM #ifdef AF_LOCAL
69*8462SApril.Chin@Sun.COM 	"pipe",		AF_LOCAL,
70*8462SApril.Chin@Sun.COM #endif
71*8462SApril.Chin@Sun.COM #ifdef AF_UNIX
72*8462SApril.Chin@Sun.COM 	"pipe",		AF_UNIX,
73*8462SApril.Chin@Sun.COM #endif
74*8462SApril.Chin@Sun.COM #ifdef AF_FILE
75*8462SApril.Chin@Sun.COM 	"FILE",		AF_FILE,
76*8462SApril.Chin@Sun.COM #endif
77*8462SApril.Chin@Sun.COM #ifdef AF_INET
78*8462SApril.Chin@Sun.COM 	"INET",		AF_INET,
79*8462SApril.Chin@Sun.COM #endif
80*8462SApril.Chin@Sun.COM #ifdef AF_AX25
81*8462SApril.Chin@Sun.COM 	"AX25",		AF_AX25,
82*8462SApril.Chin@Sun.COM #endif
83*8462SApril.Chin@Sun.COM #ifdef AF_IPX
84*8462SApril.Chin@Sun.COM 	"IPX",		AF_IPX,
85*8462SApril.Chin@Sun.COM #endif
86*8462SApril.Chin@Sun.COM #ifdef AF_APPLETALK
87*8462SApril.Chin@Sun.COM 	"APPLETALK",	AF_APPLETALK,
88*8462SApril.Chin@Sun.COM #endif
89*8462SApril.Chin@Sun.COM #ifdef AF_NETROM
90*8462SApril.Chin@Sun.COM 	"NETROM",	AF_NETROM,
91*8462SApril.Chin@Sun.COM #endif
92*8462SApril.Chin@Sun.COM #ifdef AF_BRIDGE
93*8462SApril.Chin@Sun.COM 	"BRIDGE",	AF_BRIDGE,
94*8462SApril.Chin@Sun.COM #endif
95*8462SApril.Chin@Sun.COM #ifdef AF_ATMPVC
96*8462SApril.Chin@Sun.COM 	"ATMPVC",	AF_ATMPVC,
97*8462SApril.Chin@Sun.COM #endif
98*8462SApril.Chin@Sun.COM #ifdef AF_X25
99*8462SApril.Chin@Sun.COM 	"X25",		AF_X25,
100*8462SApril.Chin@Sun.COM #endif
101*8462SApril.Chin@Sun.COM #ifdef AF_INET6
102*8462SApril.Chin@Sun.COM 	"INET6",	AF_INET6,
103*8462SApril.Chin@Sun.COM #endif
104*8462SApril.Chin@Sun.COM #ifdef AF_ROSE
105*8462SApril.Chin@Sun.COM 	"ROSE",		AF_ROSE,
106*8462SApril.Chin@Sun.COM #endif
107*8462SApril.Chin@Sun.COM #ifdef AF_DECnet
108*8462SApril.Chin@Sun.COM 	"DECnet",	AF_DECnet,
109*8462SApril.Chin@Sun.COM #endif
110*8462SApril.Chin@Sun.COM #ifdef AF_NETBEUI
111*8462SApril.Chin@Sun.COM 	"NETBEUI",	AF_NETBEUI,
112*8462SApril.Chin@Sun.COM #endif
113*8462SApril.Chin@Sun.COM #ifdef AF_SECURITY
114*8462SApril.Chin@Sun.COM 	"SECURITY",	AF_SECURITY,
115*8462SApril.Chin@Sun.COM #endif
116*8462SApril.Chin@Sun.COM #ifdef AF_KEY
117*8462SApril.Chin@Sun.COM 	"KEY",		AF_KEY,
118*8462SApril.Chin@Sun.COM #endif
119*8462SApril.Chin@Sun.COM #ifdef AF_NETLINK
120*8462SApril.Chin@Sun.COM 	"NETLINK",	AF_NETLINK,
121*8462SApril.Chin@Sun.COM #endif
122*8462SApril.Chin@Sun.COM #ifdef AF_ROUTE
123*8462SApril.Chin@Sun.COM 	"ROUTE",	AF_ROUTE,
124*8462SApril.Chin@Sun.COM #endif
125*8462SApril.Chin@Sun.COM #ifdef AF_PACKET
126*8462SApril.Chin@Sun.COM 	"PACKET",	AF_PACKET,
127*8462SApril.Chin@Sun.COM #endif
128*8462SApril.Chin@Sun.COM #ifdef AF_ASH
129*8462SApril.Chin@Sun.COM 	"ASH",		AF_ASH,
130*8462SApril.Chin@Sun.COM #endif
131*8462SApril.Chin@Sun.COM #ifdef AF_ECONET
132*8462SApril.Chin@Sun.COM 	"ECONET",	AF_ECONET,
133*8462SApril.Chin@Sun.COM #endif
134*8462SApril.Chin@Sun.COM #ifdef AF_ATMSVC
135*8462SApril.Chin@Sun.COM 	"ATMSVC",	AF_ATMSVC,
136*8462SApril.Chin@Sun.COM #endif
137*8462SApril.Chin@Sun.COM #ifdef AF_SNA
138*8462SApril.Chin@Sun.COM 	"SNA",		AF_SNA,
139*8462SApril.Chin@Sun.COM #endif
140*8462SApril.Chin@Sun.COM #ifdef AF_IRDA
141*8462SApril.Chin@Sun.COM 	"IRDA",		AF_IRDA,
142*8462SApril.Chin@Sun.COM #endif
143*8462SApril.Chin@Sun.COM #ifdef AF_PPPOX
144*8462SApril.Chin@Sun.COM 	"PPPOX",	AF_PPPOX,
145*8462SApril.Chin@Sun.COM #endif
146*8462SApril.Chin@Sun.COM #ifdef AF_WANPIPE
147*8462SApril.Chin@Sun.COM 	"WANPIPE",	AF_WANPIPE,
148*8462SApril.Chin@Sun.COM #endif
149*8462SApril.Chin@Sun.COM #ifdef AF_BLUETOOTH
150*8462SApril.Chin@Sun.COM 	"BLUETOOTH",	AF_BLUETOOTH,
151*8462SApril.Chin@Sun.COM #endif
152*8462SApril.Chin@Sun.COM 	0
153*8462SApril.Chin@Sun.COM };
154*8462SApril.Chin@Sun.COM 
155*8462SApril.Chin@Sun.COM #endif
156*8462SApril.Chin@Sun.COM 
1574887Schin int
1584887Schin b_fds(int argc, char** argv, void* context)
1594887Schin {
1604887Schin 	register char*		s;
1614887Schin 	register int		i;
1624887Schin 	register char*		m;
1634887Schin 	register char*		x;
1644887Schin 	int			flags;
1654887Schin 	int			details;
166*8462SApril.Chin@Sun.COM 	int			open_max;
1674887Schin 	struct stat		st;
1684887Schin #ifdef S_IFSOCK
1694887Schin 	struct sockaddr_in	addr;
170*8462SApril.Chin@Sun.COM 	char*			a;
171*8462SApril.Chin@Sun.COM 	unsigned char*		b;
172*8462SApril.Chin@Sun.COM 	unsigned char*		e;
173*8462SApril.Chin@Sun.COM 	socklen_t		addrlen;
1744887Schin 	socklen_t		len;
1754887Schin 	int			type;
176*8462SApril.Chin@Sun.COM 	int			port;
1774887Schin 	int			prot;
178*8462SApril.Chin@Sun.COM 	char			nam[256];
179*8462SApril.Chin@Sun.COM 	char			num[64];
180*8462SApril.Chin@Sun.COM 	char			fam[64];
1814887Schin #endif
1824887Schin 
1834887Schin 	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
1844887Schin 	details = 0;
1854887Schin 	for (;;)
1864887Schin 	{
1874887Schin 		switch (optget(argv, usage))
1884887Schin 		{
1894887Schin 		case 'l':
1904887Schin 			details = opt_info.num;
1914887Schin 			continue;
1924887Schin 		case '?':
1934887Schin 			error(ERROR_USAGE|4, "%s", opt_info.arg);
1944887Schin 			continue;
1954887Schin 		case ':':
1964887Schin 			error(2, "%s", opt_info.arg);
1974887Schin 			continue;
1984887Schin 		}
1994887Schin 		break;
2004887Schin 	}
2014887Schin 	argv += opt_info.index;
2024887Schin 	if (error_info.errors || *argv)
2034887Schin 		error(ERROR_USAGE|4, "%s", optusage(NiL));
204*8462SApril.Chin@Sun.COM 	if ((open_max = getconf("OPEN_MAX")) <= 0)
205*8462SApril.Chin@Sun.COM 		open_max = OPEN_MAX;
206*8462SApril.Chin@Sun.COM 	for (i = 0; i <= open_max; i++)
207*8462SApril.Chin@Sun.COM 	{
2084887Schin 		if (fstat(i, &st))
209*8462SApril.Chin@Sun.COM 		{
210*8462SApril.Chin@Sun.COM 			/* not open */
211*8462SApril.Chin@Sun.COM 			continue;
212*8462SApril.Chin@Sun.COM 		}
213*8462SApril.Chin@Sun.COM 		if (!details)
2144887Schin 		{
215*8462SApril.Chin@Sun.COM 			sfprintf(sfstdout, "%d\n", i);
216*8462SApril.Chin@Sun.COM 			continue;
217*8462SApril.Chin@Sun.COM 		}
218*8462SApril.Chin@Sun.COM 		if ((flags = fcntl(i, F_GETFL, (char*)0)) == -1)
219*8462SApril.Chin@Sun.COM 			m = "--";
220*8462SApril.Chin@Sun.COM 		else
221*8462SApril.Chin@Sun.COM 			switch (flags & (O_RDONLY|O_WRONLY|O_RDWR))
222*8462SApril.Chin@Sun.COM 			{
223*8462SApril.Chin@Sun.COM 			case O_RDONLY:
224*8462SApril.Chin@Sun.COM 				m = "r-";
225*8462SApril.Chin@Sun.COM 				break;
226*8462SApril.Chin@Sun.COM 			case O_WRONLY:
227*8462SApril.Chin@Sun.COM 				m = "-w";
228*8462SApril.Chin@Sun.COM 				break;
229*8462SApril.Chin@Sun.COM 			case O_RDWR:
230*8462SApril.Chin@Sun.COM 				m = "rw";
231*8462SApril.Chin@Sun.COM 				break;
232*8462SApril.Chin@Sun.COM 			default:
233*8462SApril.Chin@Sun.COM 				m = "??";
234*8462SApril.Chin@Sun.COM 				break;
235*8462SApril.Chin@Sun.COM 			}
236*8462SApril.Chin@Sun.COM 		x = (fcntl(i, F_GETFD, (char*)0) > 0) ? "x" : "-";
237*8462SApril.Chin@Sun.COM 		if (isatty(i) && (s = ttyname(i)))
238*8462SApril.Chin@Sun.COM 		{
239*8462SApril.Chin@Sun.COM 			sfprintf(sfstdout, "%02d %s%s %s %s\n", i, m, x, fmtmode(st.st_mode, 0), s);
240*8462SApril.Chin@Sun.COM 			continue;
241*8462SApril.Chin@Sun.COM 		}
242*8462SApril.Chin@Sun.COM #ifdef S_IFSOCK
243*8462SApril.Chin@Sun.COM 		addrlen = sizeof(addr);
244*8462SApril.Chin@Sun.COM 		memset(&addr, 0, addrlen);
245*8462SApril.Chin@Sun.COM 		if (!getsockname(i, (struct sockaddr*)&addr, (void*)&addrlen))
246*8462SApril.Chin@Sun.COM 		{
247*8462SApril.Chin@Sun.COM 			type = 0;
248*8462SApril.Chin@Sun.COM 			prot = 0;
249*8462SApril.Chin@Sun.COM #ifdef SO_TYPE
250*8462SApril.Chin@Sun.COM 			len = sizeof(type);
251*8462SApril.Chin@Sun.COM 			if (getsockopt(i, SOL_SOCKET, SO_TYPE, (void*)&type, (void*)&len))
252*8462SApril.Chin@Sun.COM 				type = -1;
253*8462SApril.Chin@Sun.COM #endif
254*8462SApril.Chin@Sun.COM #ifdef SO_PROTOTYPE
255*8462SApril.Chin@Sun.COM 			len = sizeof(prot);
256*8462SApril.Chin@Sun.COM 			if (getsockopt(i, SOL_SOCKET, SO_PROTOTYPE, (void*)&prot, (void*)&len))
257*8462SApril.Chin@Sun.COM 				prot = -1;
258*8462SApril.Chin@Sun.COM #endif
259*8462SApril.Chin@Sun.COM 			if (!st.st_mode)
260*8462SApril.Chin@Sun.COM 				st.st_mode = S_IFSOCK|S_IRUSR|S_IWUSR;
261*8462SApril.Chin@Sun.COM 			s = 0;
262*8462SApril.Chin@Sun.COM 			switch (type)
263*8462SApril.Chin@Sun.COM 			{
264*8462SApril.Chin@Sun.COM 			case SOCK_DGRAM:
265*8462SApril.Chin@Sun.COM 				switch (addr.sin_family)
2664887Schin 				{
267*8462SApril.Chin@Sun.COM 				case AF_INET:
268*8462SApril.Chin@Sun.COM #ifdef AF_INET6
269*8462SApril.Chin@Sun.COM 				case AF_INET6:
270*8462SApril.Chin@Sun.COM #endif
271*8462SApril.Chin@Sun.COM 					s = "udp";
2724887Schin 					break;
2734887Schin 				}
274*8462SApril.Chin@Sun.COM 				break;
275*8462SApril.Chin@Sun.COM 			case SOCK_STREAM:
276*8462SApril.Chin@Sun.COM 				switch (addr.sin_family)
277*8462SApril.Chin@Sun.COM 				{
278*8462SApril.Chin@Sun.COM 				case AF_INET:
279*8462SApril.Chin@Sun.COM #ifdef AF_INET6
280*8462SApril.Chin@Sun.COM 				case AF_INET6:
2814887Schin #endif
282*8462SApril.Chin@Sun.COM #ifdef IPPROTO_SCTP
283*8462SApril.Chin@Sun.COM 					if (prot == IPPROTO_SCTP)
284*8462SApril.Chin@Sun.COM 						s = "sctp";
285*8462SApril.Chin@Sun.COM 					else
2864887Schin #endif
2874887Schin 						s = "tcp";
2884887Schin 					break;
2894887Schin 				}
290*8462SApril.Chin@Sun.COM 				break;
291*8462SApril.Chin@Sun.COM #ifdef SOCK_RAW
292*8462SApril.Chin@Sun.COM 			case SOCK_RAW:
293*8462SApril.Chin@Sun.COM 				s = "raw";
294*8462SApril.Chin@Sun.COM 				break;
295*8462SApril.Chin@Sun.COM #endif
296*8462SApril.Chin@Sun.COM #ifdef SOCK_RDM
297*8462SApril.Chin@Sun.COM 			case SOCK_RDM:
298*8462SApril.Chin@Sun.COM 				s = "rdm";
299*8462SApril.Chin@Sun.COM 				break;
300*8462SApril.Chin@Sun.COM #endif
301*8462SApril.Chin@Sun.COM #ifdef SOCK_SEQPACKET
302*8462SApril.Chin@Sun.COM 			case SOCK_SEQPACKET:
303*8462SApril.Chin@Sun.COM 				s = "seqpacket";
304*8462SApril.Chin@Sun.COM 				break;
3054887Schin #endif
306*8462SApril.Chin@Sun.COM 			}
307*8462SApril.Chin@Sun.COM 			if (!s)
308*8462SApril.Chin@Sun.COM 			{
309*8462SApril.Chin@Sun.COM 				for (type = 0; family[type].name && family[type].value != addr.sin_family; type++);
310*8462SApril.Chin@Sun.COM 				if (!(s = (char*)family[type].name))
311*8462SApril.Chin@Sun.COM 					sfsprintf(s = num, sizeof(num), "family.%d", addr.sin_family);
312*8462SApril.Chin@Sun.COM 			}
313*8462SApril.Chin@Sun.COM 			port = 0;
314*8462SApril.Chin@Sun.COM #ifdef INET6_ADDRSTRLEN
315*8462SApril.Chin@Sun.COM 			if (a = (char*)inet_ntop(addr.sin_family, &addr.sin_addr, nam, sizeof(nam)))
316*8462SApril.Chin@Sun.COM 				port = ntohs(addr.sin_port);
3174887Schin 			else
318*8462SApril.Chin@Sun.COM #endif
319*8462SApril.Chin@Sun.COM 			if (addr.sin_family == AF_INET)
320*8462SApril.Chin@Sun.COM 			{
321*8462SApril.Chin@Sun.COM 				a = inet_ntoa(addr.sin_addr);
322*8462SApril.Chin@Sun.COM 				port = ntohs(addr.sin_port);
323*8462SApril.Chin@Sun.COM 			}
324*8462SApril.Chin@Sun.COM 			else
325*8462SApril.Chin@Sun.COM 			{
326*8462SApril.Chin@Sun.COM 				a = fam;
327*8462SApril.Chin@Sun.COM 				e = (b = (unsigned char*)&addr) + addrlen;
328*8462SApril.Chin@Sun.COM 				while (b < e && a < &fam[sizeof(fam)-1])
329*8462SApril.Chin@Sun.COM 					a += sfsprintf(a, &fam[sizeof(fam)] - a - 1, ".%d", *b++);
330*8462SApril.Chin@Sun.COM 				a = a == fam ? "0" : fam + 1;
331*8462SApril.Chin@Sun.COM 			}
332*8462SApril.Chin@Sun.COM 			if (port)
333*8462SApril.Chin@Sun.COM 				sfprintf(sfstdout, "%02d %s%s %s /dev/%s/%s/%d\n", i, m, x, fmtmode(st.st_mode, 0), s, a, port);
334*8462SApril.Chin@Sun.COM 			else
335*8462SApril.Chin@Sun.COM 				sfprintf(sfstdout, "%02d %s%s %s /dev/%s/%s\n", i, m, x, fmtmode(st.st_mode, 0), s, a);
336*8462SApril.Chin@Sun.COM 			continue;
3374887Schin 		}
338*8462SApril.Chin@Sun.COM #endif
339*8462SApril.Chin@Sun.COM 		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);
340*8462SApril.Chin@Sun.COM 	}
3414887Schin 	return 0;
3424887Schin }
343