xref: /titanic_51/usr/src/lib/libcmd/common/fds.c (revision 7c2fbfb345896881c631598ee3852ce9ce33fb07)
1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*7c2fbfb3SApril Chin *          Copyright (c) 1992-2008 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6da2e3ebdSchin *                  Common Public License, Version 1.0                  *
7*7c2fbfb3SApril 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[] =
24*7c2fbfb3SApril Chin "[-?\n@(#)$Id: fds (AT&T Research) 2008-08-26 $\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.]"
32*7c2fbfb3SApril Chin "[+SEE ALSO?\blogname\b(1), \bwho\b(1), \bgetgroups\b(2), \bgetsockname\b(2), \bgetsockopts\b(2)]"
33da2e3ebdSchin ;
34da2e3ebdSchin 
35da2e3ebdSchin #include <cmd.h>
36da2e3ebdSchin #include <ls.h>
37da2e3ebdSchin 
38da2e3ebdSchin #include "FEATURE/sockets"
39da2e3ebdSchin 
40da2e3ebdSchin #if defined(S_IFSOCK) && _sys_socket && _hdr_arpa_inet && _hdr_netinet_in && _lib_getsockname && _lib_getsockopt && _lib_inet_ntoa
41da2e3ebdSchin #include <sys/socket.h>
42da2e3ebdSchin #include <netinet/in.h>
43da2e3ebdSchin #include <arpa/inet.h>
44da2e3ebdSchin #else
45da2e3ebdSchin #undef	S_IFSOCK
46da2e3ebdSchin #endif
47da2e3ebdSchin 
48da2e3ebdSchin #ifndef minor
49da2e3ebdSchin #define minor(x)	(int)((x)&0xff)
50da2e3ebdSchin #endif
51da2e3ebdSchin #ifndef major
52da2e3ebdSchin #define major(x)	(int)(((unsigned int)(x)>>8)&0xff)
53da2e3ebdSchin #endif
54da2e3ebdSchin 
55*7c2fbfb3SApril Chin #undef	getconf
56*7c2fbfb3SApril Chin #define getconf(x)	strtol(astconf(x,NiL,NiL),NiL,0)
57*7c2fbfb3SApril Chin 
58*7c2fbfb3SApril Chin #ifdef S_IFSOCK
59*7c2fbfb3SApril Chin 
60*7c2fbfb3SApril Chin typedef struct NV_s
61*7c2fbfb3SApril Chin {
62*7c2fbfb3SApril Chin 	const char*	name;
63*7c2fbfb3SApril Chin 	int		value;
64*7c2fbfb3SApril Chin } NV_t;
65*7c2fbfb3SApril Chin 
66*7c2fbfb3SApril Chin static const NV_t	family[] =
67*7c2fbfb3SApril Chin {
68*7c2fbfb3SApril Chin #ifdef AF_LOCAL
69*7c2fbfb3SApril Chin 	"pipe",		AF_LOCAL,
70*7c2fbfb3SApril Chin #endif
71*7c2fbfb3SApril Chin #ifdef AF_UNIX
72*7c2fbfb3SApril Chin 	"pipe",		AF_UNIX,
73*7c2fbfb3SApril Chin #endif
74*7c2fbfb3SApril Chin #ifdef AF_FILE
75*7c2fbfb3SApril Chin 	"FILE",		AF_FILE,
76*7c2fbfb3SApril Chin #endif
77*7c2fbfb3SApril Chin #ifdef AF_INET
78*7c2fbfb3SApril Chin 	"INET",		AF_INET,
79*7c2fbfb3SApril Chin #endif
80*7c2fbfb3SApril Chin #ifdef AF_AX25
81*7c2fbfb3SApril Chin 	"AX25",		AF_AX25,
82*7c2fbfb3SApril Chin #endif
83*7c2fbfb3SApril Chin #ifdef AF_IPX
84*7c2fbfb3SApril Chin 	"IPX",		AF_IPX,
85*7c2fbfb3SApril Chin #endif
86*7c2fbfb3SApril Chin #ifdef AF_APPLETALK
87*7c2fbfb3SApril Chin 	"APPLETALK",	AF_APPLETALK,
88*7c2fbfb3SApril Chin #endif
89*7c2fbfb3SApril Chin #ifdef AF_NETROM
90*7c2fbfb3SApril Chin 	"NETROM",	AF_NETROM,
91*7c2fbfb3SApril Chin #endif
92*7c2fbfb3SApril Chin #ifdef AF_BRIDGE
93*7c2fbfb3SApril Chin 	"BRIDGE",	AF_BRIDGE,
94*7c2fbfb3SApril Chin #endif
95*7c2fbfb3SApril Chin #ifdef AF_ATMPVC
96*7c2fbfb3SApril Chin 	"ATMPVC",	AF_ATMPVC,
97*7c2fbfb3SApril Chin #endif
98*7c2fbfb3SApril Chin #ifdef AF_X25
99*7c2fbfb3SApril Chin 	"X25",		AF_X25,
100*7c2fbfb3SApril Chin #endif
101*7c2fbfb3SApril Chin #ifdef AF_INET6
102*7c2fbfb3SApril Chin 	"INET6",	AF_INET6,
103*7c2fbfb3SApril Chin #endif
104*7c2fbfb3SApril Chin #ifdef AF_ROSE
105*7c2fbfb3SApril Chin 	"ROSE",		AF_ROSE,
106*7c2fbfb3SApril Chin #endif
107*7c2fbfb3SApril Chin #ifdef AF_DECnet
108*7c2fbfb3SApril Chin 	"DECnet",	AF_DECnet,
109*7c2fbfb3SApril Chin #endif
110*7c2fbfb3SApril Chin #ifdef AF_NETBEUI
111*7c2fbfb3SApril Chin 	"NETBEUI",	AF_NETBEUI,
112*7c2fbfb3SApril Chin #endif
113*7c2fbfb3SApril Chin #ifdef AF_SECURITY
114*7c2fbfb3SApril Chin 	"SECURITY",	AF_SECURITY,
115*7c2fbfb3SApril Chin #endif
116*7c2fbfb3SApril Chin #ifdef AF_KEY
117*7c2fbfb3SApril Chin 	"KEY",		AF_KEY,
118*7c2fbfb3SApril Chin #endif
119*7c2fbfb3SApril Chin #ifdef AF_NETLINK
120*7c2fbfb3SApril Chin 	"NETLINK",	AF_NETLINK,
121*7c2fbfb3SApril Chin #endif
122*7c2fbfb3SApril Chin #ifdef AF_ROUTE
123*7c2fbfb3SApril Chin 	"ROUTE",	AF_ROUTE,
124*7c2fbfb3SApril Chin #endif
125*7c2fbfb3SApril Chin #ifdef AF_PACKET
126*7c2fbfb3SApril Chin 	"PACKET",	AF_PACKET,
127*7c2fbfb3SApril Chin #endif
128*7c2fbfb3SApril Chin #ifdef AF_ASH
129*7c2fbfb3SApril Chin 	"ASH",		AF_ASH,
130*7c2fbfb3SApril Chin #endif
131*7c2fbfb3SApril Chin #ifdef AF_ECONET
132*7c2fbfb3SApril Chin 	"ECONET",	AF_ECONET,
133*7c2fbfb3SApril Chin #endif
134*7c2fbfb3SApril Chin #ifdef AF_ATMSVC
135*7c2fbfb3SApril Chin 	"ATMSVC",	AF_ATMSVC,
136*7c2fbfb3SApril Chin #endif
137*7c2fbfb3SApril Chin #ifdef AF_SNA
138*7c2fbfb3SApril Chin 	"SNA",		AF_SNA,
139*7c2fbfb3SApril Chin #endif
140*7c2fbfb3SApril Chin #ifdef AF_IRDA
141*7c2fbfb3SApril Chin 	"IRDA",		AF_IRDA,
142*7c2fbfb3SApril Chin #endif
143*7c2fbfb3SApril Chin #ifdef AF_PPPOX
144*7c2fbfb3SApril Chin 	"PPPOX",	AF_PPPOX,
145*7c2fbfb3SApril Chin #endif
146*7c2fbfb3SApril Chin #ifdef AF_WANPIPE
147*7c2fbfb3SApril Chin 	"WANPIPE",	AF_WANPIPE,
148*7c2fbfb3SApril Chin #endif
149*7c2fbfb3SApril Chin #ifdef AF_BLUETOOTH
150*7c2fbfb3SApril Chin 	"BLUETOOTH",	AF_BLUETOOTH,
151*7c2fbfb3SApril Chin #endif
152*7c2fbfb3SApril Chin 	0
153*7c2fbfb3SApril Chin };
154*7c2fbfb3SApril Chin 
155*7c2fbfb3SApril Chin #endif
156*7c2fbfb3SApril Chin 
157da2e3ebdSchin int
158da2e3ebdSchin b_fds(int argc, char** argv, void* context)
159da2e3ebdSchin {
160da2e3ebdSchin 	register char*		s;
161da2e3ebdSchin 	register int		i;
162da2e3ebdSchin 	register char*		m;
163da2e3ebdSchin 	register char*		x;
164da2e3ebdSchin 	int			flags;
165da2e3ebdSchin 	int			details;
166*7c2fbfb3SApril Chin 	int			open_max;
167da2e3ebdSchin 	struct stat		st;
168da2e3ebdSchin #ifdef S_IFSOCK
169da2e3ebdSchin 	struct sockaddr_in	addr;
170*7c2fbfb3SApril Chin 	char*			a;
171*7c2fbfb3SApril Chin 	unsigned char*		b;
172*7c2fbfb3SApril Chin 	unsigned char*		e;
173*7c2fbfb3SApril Chin 	socklen_t		addrlen;
174da2e3ebdSchin 	socklen_t		len;
175da2e3ebdSchin 	int			type;
176*7c2fbfb3SApril Chin 	int			port;
177da2e3ebdSchin 	int			prot;
178*7c2fbfb3SApril Chin 	char			nam[256];
179*7c2fbfb3SApril Chin 	char			num[64];
180*7c2fbfb3SApril Chin 	char			fam[64];
181da2e3ebdSchin #endif
182da2e3ebdSchin 
183da2e3ebdSchin 	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
184da2e3ebdSchin 	details = 0;
185da2e3ebdSchin 	for (;;)
186da2e3ebdSchin 	{
187da2e3ebdSchin 		switch (optget(argv, usage))
188da2e3ebdSchin 		{
189da2e3ebdSchin 		case 'l':
190da2e3ebdSchin 			details = opt_info.num;
191da2e3ebdSchin 			continue;
192da2e3ebdSchin 		case '?':
193da2e3ebdSchin 			error(ERROR_USAGE|4, "%s", opt_info.arg);
194da2e3ebdSchin 			continue;
195da2e3ebdSchin 		case ':':
196da2e3ebdSchin 			error(2, "%s", opt_info.arg);
197da2e3ebdSchin 			continue;
198da2e3ebdSchin 		}
199da2e3ebdSchin 		break;
200da2e3ebdSchin 	}
201da2e3ebdSchin 	argv += opt_info.index;
202da2e3ebdSchin 	if (error_info.errors || *argv)
203da2e3ebdSchin 		error(ERROR_USAGE|4, "%s", optusage(NiL));
204*7c2fbfb3SApril Chin 	if ((open_max = getconf("OPEN_MAX")) <= 0)
205*7c2fbfb3SApril Chin 		open_max = OPEN_MAX;
206*7c2fbfb3SApril Chin 	for (i = 0; i <= open_max; i++)
207da2e3ebdSchin 	{
208*7c2fbfb3SApril Chin 		if (fstat(i, &st))
209*7c2fbfb3SApril Chin 		{
210*7c2fbfb3SApril Chin 			/* not open */
211*7c2fbfb3SApril Chin 			continue;
212*7c2fbfb3SApril Chin 		}
213*7c2fbfb3SApril Chin 		if (!details)
214*7c2fbfb3SApril Chin 		{
215*7c2fbfb3SApril Chin 			sfprintf(sfstdout, "%d\n", i);
216*7c2fbfb3SApril Chin 			continue;
217*7c2fbfb3SApril Chin 		}
218da2e3ebdSchin 		if ((flags = fcntl(i, F_GETFL, (char*)0)) == -1)
219da2e3ebdSchin 			m = "--";
220da2e3ebdSchin 		else
221da2e3ebdSchin 			switch (flags & (O_RDONLY|O_WRONLY|O_RDWR))
222da2e3ebdSchin 			{
223da2e3ebdSchin 			case O_RDONLY:
224da2e3ebdSchin 				m = "r-";
225da2e3ebdSchin 				break;
226da2e3ebdSchin 			case O_WRONLY:
227da2e3ebdSchin 				m = "-w";
228da2e3ebdSchin 				break;
229da2e3ebdSchin 			case O_RDWR:
230da2e3ebdSchin 				m = "rw";
231da2e3ebdSchin 				break;
232da2e3ebdSchin 			default:
233da2e3ebdSchin 				m = "??";
234da2e3ebdSchin 				break;
235da2e3ebdSchin 			}
236da2e3ebdSchin 		x = (fcntl(i, F_GETFD, (char*)0) > 0) ? "x" : "-";
237da2e3ebdSchin 		if (isatty(i) && (s = ttyname(i)))
238*7c2fbfb3SApril Chin 		{
239da2e3ebdSchin 			sfprintf(sfstdout, "%02d %s%s %s %s\n", i, m, x, fmtmode(st.st_mode, 0), s);
240*7c2fbfb3SApril Chin 			continue;
241*7c2fbfb3SApril Chin 		}
242da2e3ebdSchin #ifdef S_IFSOCK
243*7c2fbfb3SApril Chin 		addrlen = sizeof(addr);
244*7c2fbfb3SApril Chin 		memset(&addr, 0, addrlen);
245*7c2fbfb3SApril Chin 		if (!getsockname(i, (struct sockaddr*)&addr, (void*)&addrlen))
246*7c2fbfb3SApril Chin 		{
247*7c2fbfb3SApril Chin 			type = 0;
248*7c2fbfb3SApril Chin 			prot = 0;
249da2e3ebdSchin #ifdef SO_TYPE
250*7c2fbfb3SApril Chin 			len = sizeof(type);
251*7c2fbfb3SApril Chin 			if (getsockopt(i, SOL_SOCKET, SO_TYPE, (void*)&type, (void*)&len))
252*7c2fbfb3SApril Chin 				type = -1;
253da2e3ebdSchin #endif
254da2e3ebdSchin #ifdef SO_PROTOTYPE
255*7c2fbfb3SApril Chin 			len = sizeof(prot);
256*7c2fbfb3SApril Chin 			if (getsockopt(i, SOL_SOCKET, SO_PROTOTYPE, (void*)&prot, (void*)&len))
257*7c2fbfb3SApril Chin 				prot = -1;
258da2e3ebdSchin #endif
259da2e3ebdSchin 			if (!st.st_mode)
260da2e3ebdSchin 				st.st_mode = S_IFSOCK|S_IRUSR|S_IWUSR;
261da2e3ebdSchin 			s = 0;
262da2e3ebdSchin 			switch (type)
263da2e3ebdSchin 			{
264da2e3ebdSchin 			case SOCK_DGRAM:
265*7c2fbfb3SApril Chin 				switch (addr.sin_family)
266*7c2fbfb3SApril Chin 				{
267*7c2fbfb3SApril Chin 				case AF_INET:
268*7c2fbfb3SApril Chin #ifdef AF_INET6
269*7c2fbfb3SApril Chin 				case AF_INET6:
270*7c2fbfb3SApril Chin #endif
271da2e3ebdSchin 					s = "udp";
272da2e3ebdSchin 					break;
273*7c2fbfb3SApril Chin 				}
274*7c2fbfb3SApril Chin 				break;
275da2e3ebdSchin 			case SOCK_STREAM:
276*7c2fbfb3SApril Chin 				switch (addr.sin_family)
277*7c2fbfb3SApril Chin 				{
278*7c2fbfb3SApril Chin 				case AF_INET:
279*7c2fbfb3SApril Chin #ifdef AF_INET6
280*7c2fbfb3SApril Chin 				case AF_INET6:
281da2e3ebdSchin #endif
282*7c2fbfb3SApril Chin #ifdef IPPROTO_SCTP
283*7c2fbfb3SApril Chin 					if (prot == IPPROTO_SCTP)
284*7c2fbfb3SApril Chin 						s = "sctp";
285*7c2fbfb3SApril Chin 					else
286*7c2fbfb3SApril Chin #endif
287*7c2fbfb3SApril Chin 						s = "tcp";
288da2e3ebdSchin 					break;
289da2e3ebdSchin 				}
290*7c2fbfb3SApril Chin 				break;
291*7c2fbfb3SApril Chin #ifdef SOCK_RAW
292*7c2fbfb3SApril Chin 			case SOCK_RAW:
293*7c2fbfb3SApril Chin 				s = "raw";
294*7c2fbfb3SApril Chin 				break;
295*7c2fbfb3SApril Chin #endif
296*7c2fbfb3SApril Chin #ifdef SOCK_RDM
297*7c2fbfb3SApril Chin 			case SOCK_RDM:
298*7c2fbfb3SApril Chin 				s = "rdm";
299*7c2fbfb3SApril Chin 				break;
300*7c2fbfb3SApril Chin #endif
301*7c2fbfb3SApril Chin #ifdef SOCK_SEQPACKET
302*7c2fbfb3SApril Chin 			case SOCK_SEQPACKET:
303*7c2fbfb3SApril Chin 				s = "seqpacket";
304*7c2fbfb3SApril Chin 				break;
305*7c2fbfb3SApril Chin #endif
306*7c2fbfb3SApril Chin 			}
307da2e3ebdSchin 			if (!s)
308*7c2fbfb3SApril Chin 			{
309*7c2fbfb3SApril Chin 				for (type = 0; family[type].name && family[type].value != addr.sin_family; type++);
310*7c2fbfb3SApril Chin 				if (!(s = (char*)family[type].name))
311*7c2fbfb3SApril Chin 					sfsprintf(s = num, sizeof(num), "family.%d", addr.sin_family);
312*7c2fbfb3SApril Chin 			}
313*7c2fbfb3SApril Chin 			port = 0;
314*7c2fbfb3SApril Chin #ifdef INET6_ADDRSTRLEN
315*7c2fbfb3SApril Chin 			if (a = (char*)inet_ntop(addr.sin_family, &addr.sin_addr, nam, sizeof(nam)))
316*7c2fbfb3SApril Chin 				port = ntohs(addr.sin_port);
317*7c2fbfb3SApril Chin 			else
318*7c2fbfb3SApril Chin #endif
319*7c2fbfb3SApril Chin 			if (addr.sin_family == AF_INET)
320*7c2fbfb3SApril Chin 			{
321*7c2fbfb3SApril Chin 				a = inet_ntoa(addr.sin_addr);
322*7c2fbfb3SApril Chin 				port = ntohs(addr.sin_port);
323*7c2fbfb3SApril Chin 			}
324*7c2fbfb3SApril Chin 			else
325*7c2fbfb3SApril Chin 			{
326*7c2fbfb3SApril Chin 				a = fam;
327*7c2fbfb3SApril Chin 				e = (b = (unsigned char*)&addr) + addrlen;
328*7c2fbfb3SApril Chin 				while (b < e && a < &fam[sizeof(fam)-1])
329*7c2fbfb3SApril Chin 					a += sfsprintf(a, &fam[sizeof(fam)] - a - 1, ".%d", *b++);
330*7c2fbfb3SApril Chin 				a = a == fam ? "0" : fam + 1;
331*7c2fbfb3SApril Chin 			}
332*7c2fbfb3SApril Chin 			if (port)
333*7c2fbfb3SApril Chin 				sfprintf(sfstdout, "%02d %s%s %s /dev/%s/%s/%d\n", i, m, x, fmtmode(st.st_mode, 0), s, a, port);
334*7c2fbfb3SApril Chin 			else
335*7c2fbfb3SApril Chin 				sfprintf(sfstdout, "%02d %s%s %s /dev/%s/%s\n", i, m, x, fmtmode(st.st_mode, 0), s, a);
336*7c2fbfb3SApril Chin 			continue;
337da2e3ebdSchin 		}
338da2e3ebdSchin #endif
339da2e3ebdSchin 		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);
340da2e3ebdSchin 	}
341da2e3ebdSchin 	return 0;
342da2e3ebdSchin }
343