1da2e3ebdSchin /*********************************************************************** 2da2e3ebdSchin * * 3da2e3ebdSchin * This software is part of the ast package * 4*34f9b3eeSRoland Mainz * Copyright (c) 1992-2009 AT&T Intellectual Property * 5da2e3ebdSchin * and is licensed under the * 6da2e3ebdSchin * Common Public License, Version 1.0 * 77c2fbfb3SApril 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*34f9b3eeSRoland Mainz "[-?\n@(#)$Id: fds (AT&T Research) 2009-09-09 $\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*34f9b3eeSRoland Mainz "[u:unit?Write output to \afd\a.]#[fd]" 337c2fbfb3SApril Chin "[+SEE ALSO?\blogname\b(1), \bwho\b(1), \bgetgroups\b(2), \bgetsockname\b(2), \bgetsockopts\b(2)]" 34da2e3ebdSchin ; 35da2e3ebdSchin 36da2e3ebdSchin #include <cmd.h> 37da2e3ebdSchin #include <ls.h> 38da2e3ebdSchin 39da2e3ebdSchin #include "FEATURE/sockets" 40da2e3ebdSchin 41da2e3ebdSchin #if defined(S_IFSOCK) && _sys_socket && _hdr_arpa_inet && _hdr_netinet_in && _lib_getsockname && _lib_getsockopt && _lib_inet_ntoa 42da2e3ebdSchin #include <sys/socket.h> 43da2e3ebdSchin #include <netinet/in.h> 44da2e3ebdSchin #include <arpa/inet.h> 45da2e3ebdSchin #else 46da2e3ebdSchin #undef S_IFSOCK 47da2e3ebdSchin #endif 48da2e3ebdSchin 49da2e3ebdSchin #ifndef minor 50da2e3ebdSchin #define minor(x) (int)((x)&0xff) 51da2e3ebdSchin #endif 52da2e3ebdSchin #ifndef major 53da2e3ebdSchin #define major(x) (int)(((unsigned int)(x)>>8)&0xff) 54da2e3ebdSchin #endif 55da2e3ebdSchin 567c2fbfb3SApril Chin #undef getconf 577c2fbfb3SApril Chin #define getconf(x) strtol(astconf(x,NiL,NiL),NiL,0) 587c2fbfb3SApril Chin 597c2fbfb3SApril Chin #ifdef S_IFSOCK 607c2fbfb3SApril Chin 617c2fbfb3SApril Chin typedef struct NV_s 627c2fbfb3SApril Chin { 637c2fbfb3SApril Chin const char* name; 647c2fbfb3SApril Chin int value; 657c2fbfb3SApril Chin } NV_t; 667c2fbfb3SApril Chin 677c2fbfb3SApril Chin static const NV_t family[] = 687c2fbfb3SApril Chin { 697c2fbfb3SApril Chin #ifdef AF_LOCAL 707c2fbfb3SApril Chin "pipe", AF_LOCAL, 717c2fbfb3SApril Chin #endif 727c2fbfb3SApril Chin #ifdef AF_UNIX 737c2fbfb3SApril Chin "pipe", AF_UNIX, 747c2fbfb3SApril Chin #endif 757c2fbfb3SApril Chin #ifdef AF_FILE 767c2fbfb3SApril Chin "FILE", AF_FILE, 777c2fbfb3SApril Chin #endif 787c2fbfb3SApril Chin #ifdef AF_INET 797c2fbfb3SApril Chin "INET", AF_INET, 807c2fbfb3SApril Chin #endif 817c2fbfb3SApril Chin #ifdef AF_AX25 827c2fbfb3SApril Chin "AX25", AF_AX25, 837c2fbfb3SApril Chin #endif 847c2fbfb3SApril Chin #ifdef AF_IPX 857c2fbfb3SApril Chin "IPX", AF_IPX, 867c2fbfb3SApril Chin #endif 877c2fbfb3SApril Chin #ifdef AF_APPLETALK 887c2fbfb3SApril Chin "APPLETALK", AF_APPLETALK, 897c2fbfb3SApril Chin #endif 907c2fbfb3SApril Chin #ifdef AF_NETROM 917c2fbfb3SApril Chin "NETROM", AF_NETROM, 927c2fbfb3SApril Chin #endif 937c2fbfb3SApril Chin #ifdef AF_BRIDGE 947c2fbfb3SApril Chin "BRIDGE", AF_BRIDGE, 957c2fbfb3SApril Chin #endif 967c2fbfb3SApril Chin #ifdef AF_ATMPVC 977c2fbfb3SApril Chin "ATMPVC", AF_ATMPVC, 987c2fbfb3SApril Chin #endif 997c2fbfb3SApril Chin #ifdef AF_X25 1007c2fbfb3SApril Chin "X25", AF_X25, 1017c2fbfb3SApril Chin #endif 1027c2fbfb3SApril Chin #ifdef AF_INET6 1037c2fbfb3SApril Chin "INET6", AF_INET6, 1047c2fbfb3SApril Chin #endif 1057c2fbfb3SApril Chin #ifdef AF_ROSE 1067c2fbfb3SApril Chin "ROSE", AF_ROSE, 1077c2fbfb3SApril Chin #endif 1087c2fbfb3SApril Chin #ifdef AF_DECnet 1097c2fbfb3SApril Chin "DECnet", AF_DECnet, 1107c2fbfb3SApril Chin #endif 1117c2fbfb3SApril Chin #ifdef AF_NETBEUI 1127c2fbfb3SApril Chin "NETBEUI", AF_NETBEUI, 1137c2fbfb3SApril Chin #endif 1147c2fbfb3SApril Chin #ifdef AF_SECURITY 1157c2fbfb3SApril Chin "SECURITY", AF_SECURITY, 1167c2fbfb3SApril Chin #endif 1177c2fbfb3SApril Chin #ifdef AF_KEY 1187c2fbfb3SApril Chin "KEY", AF_KEY, 1197c2fbfb3SApril Chin #endif 1207c2fbfb3SApril Chin #ifdef AF_NETLINK 1217c2fbfb3SApril Chin "NETLINK", AF_NETLINK, 1227c2fbfb3SApril Chin #endif 1237c2fbfb3SApril Chin #ifdef AF_ROUTE 1247c2fbfb3SApril Chin "ROUTE", AF_ROUTE, 1257c2fbfb3SApril Chin #endif 1267c2fbfb3SApril Chin #ifdef AF_PACKET 1277c2fbfb3SApril Chin "PACKET", AF_PACKET, 1287c2fbfb3SApril Chin #endif 1297c2fbfb3SApril Chin #ifdef AF_ASH 1307c2fbfb3SApril Chin "ASH", AF_ASH, 1317c2fbfb3SApril Chin #endif 1327c2fbfb3SApril Chin #ifdef AF_ECONET 1337c2fbfb3SApril Chin "ECONET", AF_ECONET, 1347c2fbfb3SApril Chin #endif 1357c2fbfb3SApril Chin #ifdef AF_ATMSVC 1367c2fbfb3SApril Chin "ATMSVC", AF_ATMSVC, 1377c2fbfb3SApril Chin #endif 1387c2fbfb3SApril Chin #ifdef AF_SNA 1397c2fbfb3SApril Chin "SNA", AF_SNA, 1407c2fbfb3SApril Chin #endif 1417c2fbfb3SApril Chin #ifdef AF_IRDA 1427c2fbfb3SApril Chin "IRDA", AF_IRDA, 1437c2fbfb3SApril Chin #endif 1447c2fbfb3SApril Chin #ifdef AF_PPPOX 1457c2fbfb3SApril Chin "PPPOX", AF_PPPOX, 1467c2fbfb3SApril Chin #endif 1477c2fbfb3SApril Chin #ifdef AF_WANPIPE 1487c2fbfb3SApril Chin "WANPIPE", AF_WANPIPE, 1497c2fbfb3SApril Chin #endif 1507c2fbfb3SApril Chin #ifdef AF_BLUETOOTH 1517c2fbfb3SApril Chin "BLUETOOTH", AF_BLUETOOTH, 1527c2fbfb3SApril Chin #endif 1537c2fbfb3SApril Chin 0 1547c2fbfb3SApril Chin }; 1557c2fbfb3SApril Chin 1567c2fbfb3SApril Chin #endif 1577c2fbfb3SApril Chin 158da2e3ebdSchin int 159da2e3ebdSchin b_fds(int argc, char** argv, void* context) 160da2e3ebdSchin { 161da2e3ebdSchin register char* s; 162da2e3ebdSchin register int i; 163da2e3ebdSchin register char* m; 164da2e3ebdSchin register char* x; 165da2e3ebdSchin int flags; 166da2e3ebdSchin int details; 1677c2fbfb3SApril Chin int open_max; 168*34f9b3eeSRoland Mainz int unit; 169*34f9b3eeSRoland Mainz Sfio_t* sp; 170da2e3ebdSchin struct stat st; 171da2e3ebdSchin #ifdef S_IFSOCK 172da2e3ebdSchin struct sockaddr_in addr; 1737c2fbfb3SApril Chin char* a; 1747c2fbfb3SApril Chin unsigned char* b; 1757c2fbfb3SApril Chin unsigned char* e; 1767c2fbfb3SApril Chin socklen_t addrlen; 177da2e3ebdSchin socklen_t len; 178da2e3ebdSchin int type; 1797c2fbfb3SApril Chin int port; 180da2e3ebdSchin int prot; 1817c2fbfb3SApril Chin char num[64]; 1827c2fbfb3SApril Chin char fam[64]; 183*34f9b3eeSRoland Mainz #ifdef INET6_ADDRSTRLEN 184*34f9b3eeSRoland Mainz char nam[256]; 185*34f9b3eeSRoland Mainz #endif 186da2e3ebdSchin #endif 187da2e3ebdSchin 188da2e3ebdSchin cmdinit(argc, argv, context, ERROR_CATALOG, 0); 189da2e3ebdSchin details = 0; 190*34f9b3eeSRoland Mainz unit = 1; 191da2e3ebdSchin for (;;) 192da2e3ebdSchin { 193da2e3ebdSchin switch (optget(argv, usage)) 194da2e3ebdSchin { 195da2e3ebdSchin case 'l': 196da2e3ebdSchin details = opt_info.num; 197da2e3ebdSchin continue; 198*34f9b3eeSRoland Mainz case 'u': 199*34f9b3eeSRoland Mainz unit = opt_info.num; 200*34f9b3eeSRoland Mainz continue; 201da2e3ebdSchin case '?': 202da2e3ebdSchin error(ERROR_USAGE|4, "%s", opt_info.arg); 203da2e3ebdSchin continue; 204da2e3ebdSchin case ':': 205da2e3ebdSchin error(2, "%s", opt_info.arg); 206da2e3ebdSchin continue; 207da2e3ebdSchin } 208da2e3ebdSchin break; 209da2e3ebdSchin } 210da2e3ebdSchin argv += opt_info.index; 211da2e3ebdSchin if (error_info.errors || *argv) 212da2e3ebdSchin error(ERROR_USAGE|4, "%s", optusage(NiL)); 2137c2fbfb3SApril Chin if ((open_max = getconf("OPEN_MAX")) <= 0) 2147c2fbfb3SApril Chin open_max = OPEN_MAX; 215*34f9b3eeSRoland Mainz if (unit == 1) 216*34f9b3eeSRoland Mainz sp = sfstdout; 217*34f9b3eeSRoland Mainz else if (fstat(unit, &st) || !(sp = sfnew(NiL, NiL, SF_UNBOUND, unit, SF_WRITE))) 218*34f9b3eeSRoland Mainz error(ERROR_SYSTEM|3, "%d: cannot write to file descriptor"); 2197c2fbfb3SApril Chin for (i = 0; i <= open_max; i++) 220da2e3ebdSchin { 2217c2fbfb3SApril Chin if (fstat(i, &st)) 2227c2fbfb3SApril Chin { 2237c2fbfb3SApril Chin /* not open */ 2247c2fbfb3SApril Chin continue; 2257c2fbfb3SApril Chin } 2267c2fbfb3SApril Chin if (!details) 2277c2fbfb3SApril Chin { 228*34f9b3eeSRoland Mainz sfprintf(sp, "%d\n", i); 2297c2fbfb3SApril Chin continue; 2307c2fbfb3SApril Chin } 231da2e3ebdSchin if ((flags = fcntl(i, F_GETFL, (char*)0)) == -1) 232da2e3ebdSchin m = "--"; 233da2e3ebdSchin else 234da2e3ebdSchin switch (flags & (O_RDONLY|O_WRONLY|O_RDWR)) 235da2e3ebdSchin { 236da2e3ebdSchin case O_RDONLY: 237da2e3ebdSchin m = "r-"; 238da2e3ebdSchin break; 239da2e3ebdSchin case O_WRONLY: 240da2e3ebdSchin m = "-w"; 241da2e3ebdSchin break; 242da2e3ebdSchin case O_RDWR: 243da2e3ebdSchin m = "rw"; 244da2e3ebdSchin break; 245da2e3ebdSchin default: 246da2e3ebdSchin m = "??"; 247da2e3ebdSchin break; 248da2e3ebdSchin } 249da2e3ebdSchin x = (fcntl(i, F_GETFD, (char*)0) > 0) ? "x" : "-"; 250da2e3ebdSchin if (isatty(i) && (s = ttyname(i))) 2517c2fbfb3SApril Chin { 252*34f9b3eeSRoland Mainz sfprintf(sp, "%02d %s%s %s %s\n", i, m, x, fmtmode(st.st_mode, 0), s); 2537c2fbfb3SApril Chin continue; 2547c2fbfb3SApril Chin } 255da2e3ebdSchin #ifdef S_IFSOCK 2567c2fbfb3SApril Chin addrlen = sizeof(addr); 2577c2fbfb3SApril Chin memset(&addr, 0, addrlen); 2587c2fbfb3SApril Chin if (!getsockname(i, (struct sockaddr*)&addr, (void*)&addrlen)) 2597c2fbfb3SApril Chin { 2607c2fbfb3SApril Chin type = 0; 2617c2fbfb3SApril Chin prot = 0; 262da2e3ebdSchin #ifdef SO_TYPE 2637c2fbfb3SApril Chin len = sizeof(type); 2647c2fbfb3SApril Chin if (getsockopt(i, SOL_SOCKET, SO_TYPE, (void*)&type, (void*)&len)) 2657c2fbfb3SApril Chin type = -1; 266da2e3ebdSchin #endif 267da2e3ebdSchin #ifdef SO_PROTOTYPE 2687c2fbfb3SApril Chin len = sizeof(prot); 2697c2fbfb3SApril Chin if (getsockopt(i, SOL_SOCKET, SO_PROTOTYPE, (void*)&prot, (void*)&len)) 2707c2fbfb3SApril Chin prot = -1; 271da2e3ebdSchin #endif 272da2e3ebdSchin if (!st.st_mode) 273da2e3ebdSchin st.st_mode = S_IFSOCK|S_IRUSR|S_IWUSR; 274da2e3ebdSchin s = 0; 275da2e3ebdSchin switch (type) 276da2e3ebdSchin { 277da2e3ebdSchin case SOCK_DGRAM: 2787c2fbfb3SApril Chin switch (addr.sin_family) 2797c2fbfb3SApril Chin { 2807c2fbfb3SApril Chin case AF_INET: 2817c2fbfb3SApril Chin #ifdef AF_INET6 2827c2fbfb3SApril Chin case AF_INET6: 2837c2fbfb3SApril Chin #endif 284da2e3ebdSchin s = "udp"; 285da2e3ebdSchin break; 2867c2fbfb3SApril Chin } 2877c2fbfb3SApril Chin break; 288da2e3ebdSchin case SOCK_STREAM: 2897c2fbfb3SApril Chin switch (addr.sin_family) 2907c2fbfb3SApril Chin { 2917c2fbfb3SApril Chin case AF_INET: 2927c2fbfb3SApril Chin #ifdef AF_INET6 2937c2fbfb3SApril Chin case AF_INET6: 294da2e3ebdSchin #endif 2957c2fbfb3SApril Chin #ifdef IPPROTO_SCTP 2967c2fbfb3SApril Chin if (prot == IPPROTO_SCTP) 2977c2fbfb3SApril Chin s = "sctp"; 2987c2fbfb3SApril Chin else 2997c2fbfb3SApril Chin #endif 3007c2fbfb3SApril Chin s = "tcp"; 301da2e3ebdSchin break; 302da2e3ebdSchin } 3037c2fbfb3SApril Chin break; 3047c2fbfb3SApril Chin #ifdef SOCK_RAW 3057c2fbfb3SApril Chin case SOCK_RAW: 3067c2fbfb3SApril Chin s = "raw"; 3077c2fbfb3SApril Chin break; 3087c2fbfb3SApril Chin #endif 3097c2fbfb3SApril Chin #ifdef SOCK_RDM 3107c2fbfb3SApril Chin case SOCK_RDM: 3117c2fbfb3SApril Chin s = "rdm"; 3127c2fbfb3SApril Chin break; 3137c2fbfb3SApril Chin #endif 3147c2fbfb3SApril Chin #ifdef SOCK_SEQPACKET 3157c2fbfb3SApril Chin case SOCK_SEQPACKET: 3167c2fbfb3SApril Chin s = "seqpacket"; 3177c2fbfb3SApril Chin break; 3187c2fbfb3SApril Chin #endif 3197c2fbfb3SApril Chin } 320da2e3ebdSchin if (!s) 3217c2fbfb3SApril Chin { 3227c2fbfb3SApril Chin for (type = 0; family[type].name && family[type].value != addr.sin_family; type++); 3237c2fbfb3SApril Chin if (!(s = (char*)family[type].name)) 3247c2fbfb3SApril Chin sfsprintf(s = num, sizeof(num), "family.%d", addr.sin_family); 3257c2fbfb3SApril Chin } 3267c2fbfb3SApril Chin port = 0; 3277c2fbfb3SApril Chin #ifdef INET6_ADDRSTRLEN 3287c2fbfb3SApril Chin if (a = (char*)inet_ntop(addr.sin_family, &addr.sin_addr, nam, sizeof(nam))) 3297c2fbfb3SApril Chin port = ntohs(addr.sin_port); 3307c2fbfb3SApril Chin else 3317c2fbfb3SApril Chin #endif 3327c2fbfb3SApril Chin if (addr.sin_family == AF_INET) 3337c2fbfb3SApril Chin { 3347c2fbfb3SApril Chin a = inet_ntoa(addr.sin_addr); 3357c2fbfb3SApril Chin port = ntohs(addr.sin_port); 3367c2fbfb3SApril Chin } 3377c2fbfb3SApril Chin else 3387c2fbfb3SApril Chin { 3397c2fbfb3SApril Chin a = fam; 3407c2fbfb3SApril Chin e = (b = (unsigned char*)&addr) + addrlen; 3417c2fbfb3SApril Chin while (b < e && a < &fam[sizeof(fam)-1]) 3427c2fbfb3SApril Chin a += sfsprintf(a, &fam[sizeof(fam)] - a - 1, ".%d", *b++); 3437c2fbfb3SApril Chin a = a == fam ? "0" : fam + 1; 3447c2fbfb3SApril Chin } 3457c2fbfb3SApril Chin if (port) 346*34f9b3eeSRoland Mainz sfprintf(sp, "%02d %s%s %s /dev/%s/%s/%d\n", i, m, x, fmtmode(st.st_mode, 0), s, a, port); 3477c2fbfb3SApril Chin else 348*34f9b3eeSRoland Mainz sfprintf(sp, "%02d %s%s %s /dev/%s/%s\n", i, m, x, fmtmode(st.st_mode, 0), s, a); 3497c2fbfb3SApril Chin continue; 350da2e3ebdSchin } 351da2e3ebdSchin #endif 352*34f9b3eeSRoland Mainz 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*34f9b3eeSRoland Mainz } 354*34f9b3eeSRoland Mainz if (sp != sfstdout) 355*34f9b3eeSRoland Mainz { 356*34f9b3eeSRoland Mainz sfsetfd(sp, -1); 357*34f9b3eeSRoland Mainz sfclose(sp); 358da2e3ebdSchin } 359da2e3ebdSchin return 0; 360da2e3ebdSchin } 361