#include <stdlib.h>
#include <pwd.h>
#include <grp.h>
+#include <errno.h>
+#include <string.h>
#include <string>
#include <stdexcept>
return true;
}
+static const char *const EXE_DELETED_MARKER = " (deleted)";
+
+/** @brief Remove the deletion marker from a binary name, if applicable.
+ *
+ * @param exe Binary name as obtained from ``/proc/$PID/exe``.
+ *
+ * @return The input binary name with a trailing `` (deleted)`` removed.
+ *
+ * From proc(5):
+ *
+ * /proc/[pid]/exe
+ * […] If the pathname has been unlinked, the symbolic link will
+ * contain the string '(deleted)' appended to the original pathname.
+ *
+ * Which introduces an ambiguity if the path of the actual binary ends in
+ * `` (deleted)``.
+ */
+static inline std::string
+strip_deleted_marker (const std::string &exe)
+{
+ if (exe.size () <= sizeof (*EXE_DELETED_MARKER)) {
+ /* This binary name can’t possibly contain a deleted marker. */
+ return exe;
+ }
+
+ const size_t found = exe.rfind (EXE_DELETED_MARKER);
+ if (found == std::string::npos) {
+ /* Input does not contain the deleted marker. */
+ return exe;
+ }
+
+ return exe.substr (0, found);
+}
+
/**
* @brief determine the pids for a given program
* @param[in] name name (or full path) of the binary
if (!real_exe.empty())
{
// we got the path of the exe
- if (real_exe == name)
+ if (real_exe == name || strip_deleted_marker (real_exe) == name)
{
- result.push_back( pid );
- continue;
+ result.push_back( pid );
+ continue;
}
-
+
std::string proc_stat= read_file( base_path + "/stat");
if (proc_stat.empty()) continue; // process vanished
-
+
//TODO some more fuzz tests here?! (cmdline, stat(us))
-
- if (basename(real_exe) == name)
+
+ real_exe = basename (real_exe);
+ if (real_exe == name || strip_deleted_marker (real_exe) == name)
{
- fuzz2_result.push_back(pid);
- continue;
+ fuzz2_result.push_back(pid);
+ continue;
}
}
else
return true;
} // eo pidOf(const std::string&,std::vector< pid_t >&)
+/**
+ * @brief establish a new session for the current process.
+ *
+ * @return the id of the new session.
+ *
+ * This wraps setsid(2); to be called from a child process after forking.
+ * Raises ``runtime_error`` if the call fails.
+ */
+pid_t create_session (void)
+{
+ pid_t sid;
+
+ errno = 0;
+ if ((sid = setsid ()) == -1)
+ {
+ throw std::runtime_error
+ ((std::string)
+ "create_session: setsid() returned an error ("
+ + I2n::to_string (errno)
+ + "): " + strerror (errno));
+ }
+
+ return sid;
+}
+
}
}