1*4887Schin /*********************************************************************** 2*4887Schin * * 3*4887Schin * This software is part of the ast package * 4*4887Schin * Copyright (c) 1992-2007 AT&T Knowledge Ventures * 5*4887Schin * and is licensed under the * 6*4887Schin * Common Public License, Version 1.0 * 7*4887Schin * by AT&T Knowledge Ventures * 8*4887Schin * * 9*4887Schin * A copy of the License is available at * 10*4887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 11*4887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*4887Schin * * 13*4887Schin * Information and Software Systems Research * 14*4887Schin * AT&T Research * 15*4887Schin * Florham Park NJ * 16*4887Schin * * 17*4887Schin * Glenn Fowler <gsf@research.att.com> * 18*4887Schin * David Korn <dgk@research.att.com> * 19*4887Schin * * 20*4887Schin ***********************************************************************/ 21*4887Schin #pragma prototyped 22*4887Schin 23*4887Schin static const char usage[] = 24*4887Schin "[-?\n@(#)$Id: fds (AT&T Research) 2006-10-26 $\n]" 25*4887Schin USAGE_LICENSE 26*4887Schin "[+NAME?fds - list open file descriptor status]" 27*4887Schin "[+DESCRIPTION?\bfds\b lists the status for each open file descriptor. " 28*4887Schin "When invoked as a shell builtin it accesses the file descriptors of the " 29*4887Schin "calling shell, otherwise it lists the file descriptors passed across " 30*4887Schin "\bexec\b(2).]" 31*4887Schin "[l:long?List file descriptor details.]" 32*4887Schin "[+SEE ALSO?\blogname\b(1), \bwho\b(1), \bgetgroups\b(2)]" 33*4887Schin ; 34*4887Schin 35*4887Schin #include <cmd.h> 36*4887Schin #include <ls.h> 37*4887Schin 38*4887Schin #include "FEATURE/sockets" 39*4887Schin 40*4887Schin #if defined(S_IFSOCK) && _sys_socket && _hdr_arpa_inet && _hdr_netinet_in && _lib_getsockname && _lib_getsockopt && _lib_inet_ntoa 41*4887Schin #include <sys/socket.h> 42*4887Schin #include <netinet/in.h> 43*4887Schin #include <arpa/inet.h> 44*4887Schin #else 45*4887Schin #undef S_IFSOCK 46*4887Schin #endif 47*4887Schin 48*4887Schin #ifndef minor 49*4887Schin #define minor(x) (int)((x)&0xff) 50*4887Schin #endif 51*4887Schin #ifndef major 52*4887Schin #define major(x) (int)(((unsigned int)(x)>>8)&0xff) 53*4887Schin #endif 54*4887Schin 55*4887Schin int 56*4887Schin b_fds(int argc, char** argv, void* context) 57*4887Schin { 58*4887Schin register char* s; 59*4887Schin register int i; 60*4887Schin register char* m; 61*4887Schin register char* x; 62*4887Schin int flags; 63*4887Schin int details; 64*4887Schin struct stat st; 65*4887Schin #ifdef S_IFSOCK 66*4887Schin struct sockaddr_in addr; 67*4887Schin socklen_t len; 68*4887Schin int type; 69*4887Schin int prot; 70*4887Schin char num[32]; 71*4887Schin #endif 72*4887Schin 73*4887Schin cmdinit(argc, argv, context, ERROR_CATALOG, 0); 74*4887Schin details = 0; 75*4887Schin for (;;) 76*4887Schin { 77*4887Schin switch (optget(argv, usage)) 78*4887Schin { 79*4887Schin case 'l': 80*4887Schin details = opt_info.num; 81*4887Schin continue; 82*4887Schin case '?': 83*4887Schin error(ERROR_USAGE|4, "%s", opt_info.arg); 84*4887Schin continue; 85*4887Schin case ':': 86*4887Schin error(2, "%s", opt_info.arg); 87*4887Schin continue; 88*4887Schin } 89*4887Schin break; 90*4887Schin } 91*4887Schin argv += opt_info.index; 92*4887Schin if (error_info.errors || *argv) 93*4887Schin error(ERROR_USAGE|4, "%s", optusage(NiL)); 94*4887Schin for (i = 0; i <= OPEN_MAX; i++) 95*4887Schin if (fstat(i, &st)) 96*4887Schin /* not open */; 97*4887Schin else if (details) 98*4887Schin { 99*4887Schin if ((flags = fcntl(i, F_GETFL, (char*)0)) == -1) 100*4887Schin m = "--"; 101*4887Schin else 102*4887Schin switch (flags & (O_RDONLY|O_WRONLY|O_RDWR)) 103*4887Schin { 104*4887Schin case O_RDONLY: 105*4887Schin m = "r-"; 106*4887Schin break; 107*4887Schin case O_WRONLY: 108*4887Schin m = "-w"; 109*4887Schin break; 110*4887Schin case O_RDWR: 111*4887Schin m = "rw"; 112*4887Schin break; 113*4887Schin default: 114*4887Schin m = "??"; 115*4887Schin break; 116*4887Schin } 117*4887Schin x = (fcntl(i, F_GETFD, (char*)0) > 0) ? "x" : "-"; 118*4887Schin if (isatty(i) && (s = ttyname(i))) 119*4887Schin sfprintf(sfstdout, "%02d %s%s %s %s\n", i, m, x, fmtmode(st.st_mode, 0), s); 120*4887Schin #ifdef S_IFSOCK 121*4887Schin else if ((len = sizeof(addr)) 122*4887Schin && !getsockname(i, (struct sockaddr*)&addr, (void*)&len) 123*4887Schin && len == sizeof(addr) 124*4887Schin && addr.sin_family == AF_INET 125*4887Schin #ifdef SO_TYPE 126*4887Schin && (len = sizeof(type)) 127*4887Schin && !getsockopt(i, SOL_SOCKET, SO_TYPE, (void*)&type, (void*)&len) 128*4887Schin && len == sizeof(type) 129*4887Schin #else 130*4887Schin && !(type = 0) 131*4887Schin #endif 132*4887Schin #ifdef SO_PROTOTYPE 133*4887Schin && (len = sizeof(prot)) 134*4887Schin && (!getsockopt(i, SOL_SOCKET, SO_PROTOTYPE, (void*)&prot, (void*)&len) || !(prot = 0)) 135*4887Schin #else 136*4887Schin && !(prot = 0) 137*4887Schin #endif 138*4887Schin ) 139*4887Schin { 140*4887Schin if (!st.st_mode) 141*4887Schin st.st_mode = S_IFSOCK|S_IRUSR|S_IWUSR; 142*4887Schin s = 0; 143*4887Schin switch (type) 144*4887Schin { 145*4887Schin case SOCK_DGRAM: 146*4887Schin s = "udp"; 147*4887Schin break; 148*4887Schin case SOCK_STREAM: 149*4887Schin if (prot == 0) 150*4887Schin s = "tcp"; 151*4887Schin #ifdef IPPROTO_SCTP 152*4887Schin else if (prot == IPPROTO_SCTP) 153*4887Schin s = "sctp"; 154*4887Schin #endif 155*4887Schin break; 156*4887Schin } 157*4887Schin if (!s) 158*4887Schin sfprintf(sfstdout, s = num, "type.%d.prot.%d", type, prot); 159*4887Schin sfprintf(sfstdout, "%02d %s%s %s /dev/%s/%s/%d\n", i, m, x, fmtmode(st.st_mode, 0), s, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); 160*4887Schin } 161*4887Schin #endif 162*4887Schin else 163*4887Schin 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); 164*4887Schin } 165*4887Schin else 166*4887Schin sfprintf(sfstdout, "%d\n", i); 167*4887Schin return 0; 168*4887Schin } 169