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