Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

ch12: exercises completed (sherlock.c)

  • Loading branch information...
commit 40e1c3ea571746d6595b4599c2f930aa0856a6a0 1 parent 4094aa4
@posborne authored
Showing with 165 additions and 11 deletions.
  1. +55 −1 ch12/ch12-exercises.txt
  2. +110 −10 ch12/sherlock.c
View
56 ch12/ch12-exercises.txt
@@ -276,4 +276,58 @@ See sherlock.c (haha, clever)...
Example output:
-
+Processes with handles to "/dev/null":
+mate-session (pid: 1658)
+dbus-launch (pid: 1696)
+dbus-daemon (pid: 1697)
+mateconfd-2 (pid: 1704)
+mate-keyring-da (pid: 1708)
+mate-settings-d (pid: 1716)
+gvfsd (pid: 1720)
+gvfs-fuse-daemo (pid: 1722)
+gvfs-gdu-volume (pid: 1733)
+gvfs-afc-volume (pid: 1743)
+gvfs-gphoto2-vo (pid: 1746)
+mate-panel (pid: 1751)
+caja (pid: 1754)
+mate-power-mana (pid: 1758)
+deja-dup-monito (pid: 1759)
+zeitgeist-datah (pid: 1762)
+matecomponent-a (pid: 1767)
+mate-bluetooth- (pid: 1769)
+polkit-mate-aut (pid: 1775)
+nm-applet (pid: 1776)
+zeitgeist-daemo (pid: 1787)
+mate-settings-d (pid: 1790)
+gnome-do (pid: 1791)
+mate-settings-d (pid: 1793)
+update-notifier (pid: 1798)
+zeitgeist-fts (pid: 1805)
+applet.py (pid: 1813)
+wnck-applet (pid: 1820)
+pulseaudio (pid: 1822)
+mate-screensave (pid: 1830)
+clock-applet (pid: 1833)
+multiload-apple (pid: 1835)
+notification-ar (pid: 1837)
+gnome-do (pid: 1855)
+gvfsd-trash (pid: 2026)
+gconfd-2 (pid: 2033)
+gconf-helper (pid: 2054)
+gvfsd-metadata (pid: 2085)
+chrome (pid: 2105)
+chrome (pid: 2112)
+chrome (pid: 2114)
+nacl_helper_boo (pid: 2116)
+chrome (pid: 2217)
+at-spi-bus-laun (pid: 2316)
+mixer_applet2 (pid: 2592)
+emacs (pid: 2932)
+notify-osd (pid: 3202)
+dconf-service (pid: 3210)
+eclipse (pid: 10392)
+java (pid: 10463)
+firefox (pid: 14552)
+plugin-containe (pid: 14587)
+mate-terminal (pid: 14721)
+marco (pid: 19678)
View
120 ch12/sherlock.c
@@ -1,27 +1,127 @@
/*
-Write a program that lists all processes that have a particular file
-pathname open. This can be achieved by inspecting the contents of all
-of the /proc/PID/fd/* symbolic links. This will require nested loops
-employing readdir(3) to scan all /proc/PID directories, and then the
-contents of all /proc/PID/fd entries within each /proc/PID directory.
-To read the contents of a /proc/PID/fd/n symbolic link requires the
-use of readlink(), described in Section 18.5.
-
-*/
+ * Write a program that lists all processes that have a particular file
+ * pathname open. This can be achieved by inspecting the contents of all
+ * of the /proc/PID/fd/* symbolic links. This will require nested loops
+ * employing readdir(3) to scan all /proc/PID directories, and then the
+ * contents of all /proc/PID/fd entries within each /proc/PID directory.
+ * To read the contents of a /proc/PID/fd/n symbolic link requires the
+ * use of readlink(), described in Section 18.5.
+ */
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+#define PROCFS_ROOT "/proc"
static void print_usage(int argc, char **argv)
{
fprintf(stderr, "Usage: %s <filepath>", argv[0]);
}
+static int print_proc(char *dirname)
+{
+ char filename[256];
+ char linebuf[256];
+ char procname[256];
+ char pid[32];
+ char ppid[32];
+ char *key;
+ char *value;
+ FILE *p_file;
+ strcpy(filename, dirname);
+ strcat(filename, "/status");
+ p_file = fopen(filename, "r");
+ if (p_file == NULL) {
+ return 1; /* just ignore, this is fine I guess */
+ }
+ while (fgets(linebuf, sizeof(linebuf), p_file) != NULL) {
+ key = strtok(linebuf, ":");
+ value = strtok(NULL, ":");
+ if (key != NULL && value != NULL) {
+ trim(key); trim(value);
+ if (strcmp(key, "Pid") == 0) {
+ strcpy(pid, value);
+ } else if (strcmp(key, "Name") == 0) {
+ strcpy(procname, value);
+ }
+ }
+ }
+ printf("%s (pid: %s)\n", procname, pid);
+ return 0;
+}
+
+
+static int check_process(char *dirname, char *match)
+{
+ char linkpath[256];
+ char linktarget[1024];
+ char linebuf[256];
+ char procname[256];
+ struct stat st;
+ DIR *dirp;
+ struct dirent *directory_entry;
+ int len;
+
+ /* first check that this dir has an fd subdir */
+ strcpy(linkpath, dirname);
+ strcat(linkpath, "/fd");
+ if ((dirp = opendir(linkpath)) == NULL) {
+ return 1;
+ }
+ do {
+ if ((directory_entry = readdir(dirp)) != NULL) {
+ if (directory_entry->d_type == DT_LNK) {
+ strcpy(linkpath, dirname);
+ strcat(linkpath, "/fd/");
+ strcat(linkpath, directory_entry->d_name);
+ len = readlink(linkpath, linktarget, sizeof(linktarget) - 1);
+ if (len > 0) {
+ linktarget[len] = '\0';
+ if (strcmp(linktarget, match) == 0) {
+ return 0;
+ }
+ }
+ }
+ }
+ } while (directory_entry != NULL);
+ return 1;
+}
+
+
int main(int argc, char **argv)
{
+ DIR *dirp;
+ struct dirent *directory_entry;
+ char dirname[256];
+
if (argc != 2) {
print_usage(argc, argv);
return 1;
}
-
+
+ printf("Processes with handles to \"%s\":\n", argv[1]);
+
+ /* walk through each /proc/PID entry */
+ if ((dirp = opendir(PROCFS_ROOT)) == NULL) {
+ perror("Unabled to open /proc");
+ return 1;
+ }
+ do {
+ if ((directory_entry = readdir(dirp)) != NULL) {
+ if (directory_entry->d_type == DT_DIR) {
+ strcpy(dirname, PROCFS_ROOT);
+ strcat(dirname, "/");
+ strcat(dirname, directory_entry->d_name);
+ if (!check_process(dirname, argv[1])) {
+ print_proc(dirname);
+ }
+ }
+ }
+ } while (directory_entry != NULL);
+
return 0;
}
Please sign in to comment.
Something went wrong with that request. Please try again.