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