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