summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..1921e14
--- /dev/null
+++ b/main.c
@@ -0,0 +1,190 @@
+/**
+ * Fd-enum is a simple tool to list open file descriptors of a pid by type
+ * Copyright (C) 2021 Aaron Ball <nullspoon@oper.io>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/stat.h>
+
+struct config {
+ int pid;
+ char dead;
+ char live;
+ char sockets;
+ char inodes;
+ char pipes;
+ char showstats;
+};
+
+int fexists(char* path) {
+ FILE *fd = fopen(path, "r");
+ if(!fd)
+ return 0;
+ fclose(fd);
+ return 1;
+}
+
+void get_help() {
+ puts("Usage: \n\
+ -d, --dead Print list of dead file descriptors (deleted but still open)\n\
+ -i, --inodes Print list of inode file descriptors\n\
+ -l, --live Print list of live file descriptors (open and existing)\n\
+ -p, --pipes Print list of pipe file descriptors\n\
+ -s, --sockets Print list of socket file descriptors\n\
+\n\
+ -n, --no-stats Hide file descriptor statistics\n\
+ -h, --help Print this help text\n\
+");
+}
+
+int parse_args(int argc, char* argv[], struct config* c) {
+ // Initialize config struct
+ c->pid = -1;
+ c->dead = 0;
+ c->live = 0;
+ c->sockets = 0;
+ c->pipes = 0;
+ c->inodes = 0;
+ c->showstats = 1;
+ int i = 1;
+
+ while(i < argc) {
+ if(strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--dead") == 0) {
+ c->dead = 1;
+ } else if(strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "--live") == 0) {
+ c->live = 1;
+ } else if(strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--sockets") == 0) {
+ c->sockets = 1;
+ } else if(strcmp(argv[i], "-i") == 0 || strcmp(argv[i], "--inodes") == 0) {
+ c->inodes = 1;
+ } else if(strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "--pipes") == 0) {
+ c->pipes = 1;
+ } else if(strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "--no-stats") == 0) {
+ c->showstats = 0;
+ } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
+ get_help();
+ exit(1);
+ } else {
+ c->pid = strtol(argv[i], NULL, 10);
+ }
+
+ i++;
+ }
+
+ if(c->pid == -1) {
+ fprintf(stderr, "Must specify valid pid\n");
+ return 2;
+ }
+ return 0;
+}
+
+int main(int argc, char* argv[]) {
+ struct config c;
+
+ char pidpath_fd[32] = {'\0'};
+ char fdpath[289] = {'\0'};
+ char lnpath[512] = {'\0'};
+ int retval = 0;
+ int len = 0;
+ unsigned long unknown = 0;
+ unsigned long dead = 0;
+ unsigned long live = 0;
+ unsigned long sockets = 0;
+ unsigned long inodes = 0;
+ unsigned long pipes = 0;
+
+ struct stat sb;
+
+ DIR *dp = NULL;
+ struct dirent *de = NULL;
+
+ if(parse_args(argc, argv, &c) != 0)
+ return 1;
+
+ // Construct the pid path
+ sprintf(pidpath_fd, "/proc/%d/fd", c.pid);
+
+ dp = opendir(pidpath_fd);
+ while((de = readdir(dp)) != NULL) {
+ sprintf(fdpath, "%s/%s%c", pidpath_fd, de->d_name, '\0');
+
+ retval = stat(fdpath, &sb);
+ len = readlink(fdpath, lnpath, 512);
+
+ if(len <= 0)
+ continue;
+ lnpath[len] = '\0';
+
+ // Sockets
+ if(S_ISSOCK(sb.st_mode)) {
+ sockets++;
+ if(c.sockets)
+ printf("%s -> %s\n", fdpath, lnpath);
+
+ // Pipes
+ } else if(S_ISFIFO(sb.st_mode)) {
+ pipes++;
+ if(c.pipes)
+ printf("%s -> %s\n", fdpath, lnpath);
+
+ // Char device links
+ } else if(S_ISCHR(sb.st_mode)) {
+ live++;
+ if(c.live)
+ printf("%s -> %s\n", fdpath, lnpath);
+
+ // File desccriptors
+ } else if(S_ISREG(sb.st_mode)
+ || S_ISDIR(sb.st_mode)) {
+ // Exists
+ if(retval == 0 && fexists(lnpath)) {
+ live++;
+ if(c.live)
+ printf("%s -> %s\n", fdpath, lnpath);
+
+ // Does not exist
+ } else {
+ dead++;
+ if(c.dead)
+ printf("%s -> %s\n", fdpath, lnpath);
+ }
+
+ // Inodes
+ } else if(sb.st_mode == 384) {
+ inodes++;
+ if(c.inodes)
+ printf("%s -> %s\n", fdpath, lnpath);
+
+ } else {
+ unknown++;
+ }
+ }
+ closedir(dp);
+
+ if(c.showstats) {
+ printf("dead: %ld\n", dead);
+ printf("live: %ld\n", live);
+ printf("sockets: %ld\n", sockets);
+ printf("anon_inodes: %ld\n", inodes);
+ printf("pipes: %ld\n", pipes);
+ printf("unknown: %ld\n", unknown);
+ }
+
+ return 0;
+}

Generated by cgit