14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1992-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * Glenn Fowler <gsf@research.att.com> * 184887Schin * David Korn <dgk@research.att.com> * 194887Schin * * 204887Schin ***********************************************************************/ 214887Schin #pragma prototyped 224887Schin 234887Schin static const char usage[] = 24*8462SApril.Chin@Sun.COM "[-?\n@(#)$Id: fds (AT&T Research) 2008-08-26 $\n]" 254887Schin USAGE_LICENSE 264887Schin "[+NAME?fds - list open file descriptor status]" 274887Schin "[+DESCRIPTION?\bfds\b lists the status for each open file descriptor. " 284887Schin "When invoked as a shell builtin it accesses the file descriptors of the " 294887Schin "calling shell, otherwise it lists the file descriptors passed across " 304887Schin "\bexec\b(2).]" 314887Schin "[l:long?List file descriptor details.]" 32*8462SApril.Chin@Sun.COM "[+SEE ALSO?\blogname\b(1), \bwho\b(1), \bgetgroups\b(2), \bgetsockname\b(2), \bgetsockopts\b(2)]" 334887Schin ; 344887Schin 354887Schin #include <cmd.h> 364887Schin #include <ls.h> 374887Schin 384887Schin #include "FEATURE/sockets" 394887Schin 404887Schin #if defined(S_IFSOCK) && _sys_socket && _hdr_arpa_inet && _hdr_netinet_in && _lib_getsockname && _lib_getsockopt && _lib_inet_ntoa 414887Schin #include <sys/socket.h> 424887Schin #include <netinet/in.h> 434887Schin #include <arpa/inet.h> 444887Schin #else 454887Schin #undef S_IFSOCK 464887Schin #endif 474887Schin 484887Schin #ifndef minor 494887Schin #define minor(x) (int)((x)&0xff) 504887Schin #endif 514887Schin #ifndef major 524887Schin #define major(x) (int)(((unsigned int)(x)>>8)&0xff) 534887Schin #endif 544887Schin 55*8462SApril.Chin@Sun.COM #undef getconf 56*8462SApril.Chin@Sun.COM #define getconf(x) strtol(astconf(x,NiL,NiL),NiL,0) 57*8462SApril.Chin@Sun.COM 58*8462SApril.Chin@Sun.COM #ifdef S_IFSOCK 59*8462SApril.Chin@Sun.COM 60*8462SApril.Chin@Sun.COM typedef struct NV_s 61*8462SApril.Chin@Sun.COM { 62*8462SApril.Chin@Sun.COM const char* name; 63*8462SApril.Chin@Sun.COM int value; 64*8462SApril.Chin@Sun.COM } NV_t; 65*8462SApril.Chin@Sun.COM 66*8462SApril.Chin@Sun.COM static const NV_t family[] = 67*8462SApril.Chin@Sun.COM { 68*8462SApril.Chin@Sun.COM #ifdef AF_LOCAL 69*8462SApril.Chin@Sun.COM "pipe", AF_LOCAL, 70*8462SApril.Chin@Sun.COM #endif 71*8462SApril.Chin@Sun.COM #ifdef AF_UNIX 72*8462SApril.Chin@Sun.COM "pipe", AF_UNIX, 73*8462SApril.Chin@Sun.COM #endif 74*8462SApril.Chin@Sun.COM #ifdef AF_FILE 75*8462SApril.Chin@Sun.COM "FILE", AF_FILE, 76*8462SApril.Chin@Sun.COM #endif 77*8462SApril.Chin@Sun.COM #ifdef AF_INET 78*8462SApril.Chin@Sun.COM "INET", AF_INET, 79*8462SApril.Chin@Sun.COM #endif 80*8462SApril.Chin@Sun.COM #ifdef AF_AX25 81*8462SApril.Chin@Sun.COM "AX25", AF_AX25, 82*8462SApril.Chin@Sun.COM #endif 83*8462SApril.Chin@Sun.COM #ifdef AF_IPX 84*8462SApril.Chin@Sun.COM "IPX", AF_IPX, 85*8462SApril.Chin@Sun.COM #endif 86*8462SApril.Chin@Sun.COM #ifdef AF_APPLETALK 87*8462SApril.Chin@Sun.COM "APPLETALK", AF_APPLETALK, 88*8462SApril.Chin@Sun.COM #endif 89*8462SApril.Chin@Sun.COM #ifdef AF_NETROM 90*8462SApril.Chin@Sun.COM "NETROM", AF_NETROM, 91*8462SApril.Chin@Sun.COM #endif 92*8462SApril.Chin@Sun.COM #ifdef AF_BRIDGE 93*8462SApril.Chin@Sun.COM "BRIDGE", AF_BRIDGE, 94*8462SApril.Chin@Sun.COM #endif 95*8462SApril.Chin@Sun.COM #ifdef AF_ATMPVC 96*8462SApril.Chin@Sun.COM "ATMPVC", AF_ATMPVC, 97*8462SApril.Chin@Sun.COM #endif 98*8462SApril.Chin@Sun.COM #ifdef AF_X25 99*8462SApril.Chin@Sun.COM "X25", AF_X25, 100*8462SApril.Chin@Sun.COM #endif 101*8462SApril.Chin@Sun.COM #ifdef AF_INET6 102*8462SApril.Chin@Sun.COM "INET6", AF_INET6, 103*8462SApril.Chin@Sun.COM #endif 104*8462SApril.Chin@Sun.COM #ifdef AF_ROSE 105*8462SApril.Chin@Sun.COM "ROSE", AF_ROSE, 106*8462SApril.Chin@Sun.COM #endif 107*8462SApril.Chin@Sun.COM #ifdef AF_DECnet 108*8462SApril.Chin@Sun.COM "DECnet", AF_DECnet, 109*8462SApril.Chin@Sun.COM #endif 110*8462SApril.Chin@Sun.COM #ifdef AF_NETBEUI 111*8462SApril.Chin@Sun.COM "NETBEUI", AF_NETBEUI, 112*8462SApril.Chin@Sun.COM #endif 113*8462SApril.Chin@Sun.COM #ifdef AF_SECURITY 114*8462SApril.Chin@Sun.COM "SECURITY", AF_SECURITY, 115*8462SApril.Chin@Sun.COM #endif 116*8462SApril.Chin@Sun.COM #ifdef AF_KEY 117*8462SApril.Chin@Sun.COM "KEY", AF_KEY, 118*8462SApril.Chin@Sun.COM #endif 119*8462SApril.Chin@Sun.COM #ifdef AF_NETLINK 120*8462SApril.Chin@Sun.COM "NETLINK", AF_NETLINK, 121*8462SApril.Chin@Sun.COM #endif 122*8462SApril.Chin@Sun.COM #ifdef AF_ROUTE 123*8462SApril.Chin@Sun.COM "ROUTE", AF_ROUTE, 124*8462SApril.Chin@Sun.COM #endif 125*8462SApril.Chin@Sun.COM #ifdef AF_PACKET 126*8462SApril.Chin@Sun.COM "PACKET", AF_PACKET, 127*8462SApril.Chin@Sun.COM #endif 128*8462SApril.Chin@Sun.COM #ifdef AF_ASH 129*8462SApril.Chin@Sun.COM "ASH", AF_ASH, 130*8462SApril.Chin@Sun.COM #endif 131*8462SApril.Chin@Sun.COM #ifdef AF_ECONET 132*8462SApril.Chin@Sun.COM "ECONET", AF_ECONET, 133*8462SApril.Chin@Sun.COM #endif 134*8462SApril.Chin@Sun.COM #ifdef AF_ATMSVC 135*8462SApril.Chin@Sun.COM "ATMSVC", AF_ATMSVC, 136*8462SApril.Chin@Sun.COM #endif 137*8462SApril.Chin@Sun.COM #ifdef AF_SNA 138*8462SApril.Chin@Sun.COM "SNA", AF_SNA, 139*8462SApril.Chin@Sun.COM #endif 140*8462SApril.Chin@Sun.COM #ifdef AF_IRDA 141*8462SApril.Chin@Sun.COM "IRDA", AF_IRDA, 142*8462SApril.Chin@Sun.COM #endif 143*8462SApril.Chin@Sun.COM #ifdef AF_PPPOX 144*8462SApril.Chin@Sun.COM "PPPOX", AF_PPPOX, 145*8462SApril.Chin@Sun.COM #endif 146*8462SApril.Chin@Sun.COM #ifdef AF_WANPIPE 147*8462SApril.Chin@Sun.COM "WANPIPE", AF_WANPIPE, 148*8462SApril.Chin@Sun.COM #endif 149*8462SApril.Chin@Sun.COM #ifdef AF_BLUETOOTH 150*8462SApril.Chin@Sun.COM "BLUETOOTH", AF_BLUETOOTH, 151*8462SApril.Chin@Sun.COM #endif 152*8462SApril.Chin@Sun.COM 0 153*8462SApril.Chin@Sun.COM }; 154*8462SApril.Chin@Sun.COM 155*8462SApril.Chin@Sun.COM #endif 156*8462SApril.Chin@Sun.COM 1574887Schin int 1584887Schin b_fds(int argc, char** argv, void* context) 1594887Schin { 1604887Schin register char* s; 1614887Schin register int i; 1624887Schin register char* m; 1634887Schin register char* x; 1644887Schin int flags; 1654887Schin int details; 166*8462SApril.Chin@Sun.COM int open_max; 1674887Schin struct stat st; 1684887Schin #ifdef S_IFSOCK 1694887Schin struct sockaddr_in addr; 170*8462SApril.Chin@Sun.COM char* a; 171*8462SApril.Chin@Sun.COM unsigned char* b; 172*8462SApril.Chin@Sun.COM unsigned char* e; 173*8462SApril.Chin@Sun.COM socklen_t addrlen; 1744887Schin socklen_t len; 1754887Schin int type; 176*8462SApril.Chin@Sun.COM int port; 1774887Schin int prot; 178*8462SApril.Chin@Sun.COM char nam[256]; 179*8462SApril.Chin@Sun.COM char num[64]; 180*8462SApril.Chin@Sun.COM char fam[64]; 1814887Schin #endif 1824887Schin 1834887Schin cmdinit(argc, argv, context, ERROR_CATALOG, 0); 1844887Schin details = 0; 1854887Schin for (;;) 1864887Schin { 1874887Schin switch (optget(argv, usage)) 1884887Schin { 1894887Schin case 'l': 1904887Schin details = opt_info.num; 1914887Schin continue; 1924887Schin case '?': 1934887Schin error(ERROR_USAGE|4, "%s", opt_info.arg); 1944887Schin continue; 1954887Schin case ':': 1964887Schin error(2, "%s", opt_info.arg); 1974887Schin continue; 1984887Schin } 1994887Schin break; 2004887Schin } 2014887Schin argv += opt_info.index; 2024887Schin if (error_info.errors || *argv) 2034887Schin error(ERROR_USAGE|4, "%s", optusage(NiL)); 204*8462SApril.Chin@Sun.COM if ((open_max = getconf("OPEN_MAX")) <= 0) 205*8462SApril.Chin@Sun.COM open_max = OPEN_MAX; 206*8462SApril.Chin@Sun.COM for (i = 0; i <= open_max; i++) 207*8462SApril.Chin@Sun.COM { 2084887Schin if (fstat(i, &st)) 209*8462SApril.Chin@Sun.COM { 210*8462SApril.Chin@Sun.COM /* not open */ 211*8462SApril.Chin@Sun.COM continue; 212*8462SApril.Chin@Sun.COM } 213*8462SApril.Chin@Sun.COM if (!details) 2144887Schin { 215*8462SApril.Chin@Sun.COM sfprintf(sfstdout, "%d\n", i); 216*8462SApril.Chin@Sun.COM continue; 217*8462SApril.Chin@Sun.COM } 218*8462SApril.Chin@Sun.COM if ((flags = fcntl(i, F_GETFL, (char*)0)) == -1) 219*8462SApril.Chin@Sun.COM m = "--"; 220*8462SApril.Chin@Sun.COM else 221*8462SApril.Chin@Sun.COM switch (flags & (O_RDONLY|O_WRONLY|O_RDWR)) 222*8462SApril.Chin@Sun.COM { 223*8462SApril.Chin@Sun.COM case O_RDONLY: 224*8462SApril.Chin@Sun.COM m = "r-"; 225*8462SApril.Chin@Sun.COM break; 226*8462SApril.Chin@Sun.COM case O_WRONLY: 227*8462SApril.Chin@Sun.COM m = "-w"; 228*8462SApril.Chin@Sun.COM break; 229*8462SApril.Chin@Sun.COM case O_RDWR: 230*8462SApril.Chin@Sun.COM m = "rw"; 231*8462SApril.Chin@Sun.COM break; 232*8462SApril.Chin@Sun.COM default: 233*8462SApril.Chin@Sun.COM m = "??"; 234*8462SApril.Chin@Sun.COM break; 235*8462SApril.Chin@Sun.COM } 236*8462SApril.Chin@Sun.COM x = (fcntl(i, F_GETFD, (char*)0) > 0) ? "x" : "-"; 237*8462SApril.Chin@Sun.COM if (isatty(i) && (s = ttyname(i))) 238*8462SApril.Chin@Sun.COM { 239*8462SApril.Chin@Sun.COM sfprintf(sfstdout, "%02d %s%s %s %s\n", i, m, x, fmtmode(st.st_mode, 0), s); 240*8462SApril.Chin@Sun.COM continue; 241*8462SApril.Chin@Sun.COM } 242*8462SApril.Chin@Sun.COM #ifdef S_IFSOCK 243*8462SApril.Chin@Sun.COM addrlen = sizeof(addr); 244*8462SApril.Chin@Sun.COM memset(&addr, 0, addrlen); 245*8462SApril.Chin@Sun.COM if (!getsockname(i, (struct sockaddr*)&addr, (void*)&addrlen)) 246*8462SApril.Chin@Sun.COM { 247*8462SApril.Chin@Sun.COM type = 0; 248*8462SApril.Chin@Sun.COM prot = 0; 249*8462SApril.Chin@Sun.COM #ifdef SO_TYPE 250*8462SApril.Chin@Sun.COM len = sizeof(type); 251*8462SApril.Chin@Sun.COM if (getsockopt(i, SOL_SOCKET, SO_TYPE, (void*)&type, (void*)&len)) 252*8462SApril.Chin@Sun.COM type = -1; 253*8462SApril.Chin@Sun.COM #endif 254*8462SApril.Chin@Sun.COM #ifdef SO_PROTOTYPE 255*8462SApril.Chin@Sun.COM len = sizeof(prot); 256*8462SApril.Chin@Sun.COM if (getsockopt(i, SOL_SOCKET, SO_PROTOTYPE, (void*)&prot, (void*)&len)) 257*8462SApril.Chin@Sun.COM prot = -1; 258*8462SApril.Chin@Sun.COM #endif 259*8462SApril.Chin@Sun.COM if (!st.st_mode) 260*8462SApril.Chin@Sun.COM st.st_mode = S_IFSOCK|S_IRUSR|S_IWUSR; 261*8462SApril.Chin@Sun.COM s = 0; 262*8462SApril.Chin@Sun.COM switch (type) 263*8462SApril.Chin@Sun.COM { 264*8462SApril.Chin@Sun.COM case SOCK_DGRAM: 265*8462SApril.Chin@Sun.COM switch (addr.sin_family) 2664887Schin { 267*8462SApril.Chin@Sun.COM case AF_INET: 268*8462SApril.Chin@Sun.COM #ifdef AF_INET6 269*8462SApril.Chin@Sun.COM case AF_INET6: 270*8462SApril.Chin@Sun.COM #endif 271*8462SApril.Chin@Sun.COM s = "udp"; 2724887Schin break; 2734887Schin } 274*8462SApril.Chin@Sun.COM break; 275*8462SApril.Chin@Sun.COM case SOCK_STREAM: 276*8462SApril.Chin@Sun.COM switch (addr.sin_family) 277*8462SApril.Chin@Sun.COM { 278*8462SApril.Chin@Sun.COM case AF_INET: 279*8462SApril.Chin@Sun.COM #ifdef AF_INET6 280*8462SApril.Chin@Sun.COM case AF_INET6: 2814887Schin #endif 282*8462SApril.Chin@Sun.COM #ifdef IPPROTO_SCTP 283*8462SApril.Chin@Sun.COM if (prot == IPPROTO_SCTP) 284*8462SApril.Chin@Sun.COM s = "sctp"; 285*8462SApril.Chin@Sun.COM else 2864887Schin #endif 2874887Schin s = "tcp"; 2884887Schin break; 2894887Schin } 290*8462SApril.Chin@Sun.COM break; 291*8462SApril.Chin@Sun.COM #ifdef SOCK_RAW 292*8462SApril.Chin@Sun.COM case SOCK_RAW: 293*8462SApril.Chin@Sun.COM s = "raw"; 294*8462SApril.Chin@Sun.COM break; 295*8462SApril.Chin@Sun.COM #endif 296*8462SApril.Chin@Sun.COM #ifdef SOCK_RDM 297*8462SApril.Chin@Sun.COM case SOCK_RDM: 298*8462SApril.Chin@Sun.COM s = "rdm"; 299*8462SApril.Chin@Sun.COM break; 300*8462SApril.Chin@Sun.COM #endif 301*8462SApril.Chin@Sun.COM #ifdef SOCK_SEQPACKET 302*8462SApril.Chin@Sun.COM case SOCK_SEQPACKET: 303*8462SApril.Chin@Sun.COM s = "seqpacket"; 304*8462SApril.Chin@Sun.COM break; 3054887Schin #endif 306*8462SApril.Chin@Sun.COM } 307*8462SApril.Chin@Sun.COM if (!s) 308*8462SApril.Chin@Sun.COM { 309*8462SApril.Chin@Sun.COM for (type = 0; family[type].name && family[type].value != addr.sin_family; type++); 310*8462SApril.Chin@Sun.COM if (!(s = (char*)family[type].name)) 311*8462SApril.Chin@Sun.COM sfsprintf(s = num, sizeof(num), "family.%d", addr.sin_family); 312*8462SApril.Chin@Sun.COM } 313*8462SApril.Chin@Sun.COM port = 0; 314*8462SApril.Chin@Sun.COM #ifdef INET6_ADDRSTRLEN 315*8462SApril.Chin@Sun.COM if (a = (char*)inet_ntop(addr.sin_family, &addr.sin_addr, nam, sizeof(nam))) 316*8462SApril.Chin@Sun.COM port = ntohs(addr.sin_port); 3174887Schin else 318*8462SApril.Chin@Sun.COM #endif 319*8462SApril.Chin@Sun.COM if (addr.sin_family == AF_INET) 320*8462SApril.Chin@Sun.COM { 321*8462SApril.Chin@Sun.COM a = inet_ntoa(addr.sin_addr); 322*8462SApril.Chin@Sun.COM port = ntohs(addr.sin_port); 323*8462SApril.Chin@Sun.COM } 324*8462SApril.Chin@Sun.COM else 325*8462SApril.Chin@Sun.COM { 326*8462SApril.Chin@Sun.COM a = fam; 327*8462SApril.Chin@Sun.COM e = (b = (unsigned char*)&addr) + addrlen; 328*8462SApril.Chin@Sun.COM while (b < e && a < &fam[sizeof(fam)-1]) 329*8462SApril.Chin@Sun.COM a += sfsprintf(a, &fam[sizeof(fam)] - a - 1, ".%d", *b++); 330*8462SApril.Chin@Sun.COM a = a == fam ? "0" : fam + 1; 331*8462SApril.Chin@Sun.COM } 332*8462SApril.Chin@Sun.COM if (port) 333*8462SApril.Chin@Sun.COM sfprintf(sfstdout, "%02d %s%s %s /dev/%s/%s/%d\n", i, m, x, fmtmode(st.st_mode, 0), s, a, port); 334*8462SApril.Chin@Sun.COM else 335*8462SApril.Chin@Sun.COM sfprintf(sfstdout, "%02d %s%s %s /dev/%s/%s\n", i, m, x, fmtmode(st.st_mode, 0), s, a); 336*8462SApril.Chin@Sun.COM continue; 3374887Schin } 338*8462SApril.Chin@Sun.COM #endif 339*8462SApril.Chin@Sun.COM 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*8462SApril.Chin@Sun.COM } 3414887Schin return 0; 3424887Schin } 343