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