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