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 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