2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
20 /***************************************************************************
21 * Copyright (C) 2008 by Intra2net AG - Thomas Jarosch *
22 ***************************************************************************/
23 #include <sys/types.h>
31 #include "daemonfunc.hpp"
32 #include "stringfunc.hxx"
33 #include "filefunc.hxx"
44 * Fork into the background.
52 throw runtime_error("fork() failed");
59 // pid==0 -> child process: continue
63 * Drop root privileges
64 * @param username User to become. Don't change user if empty
65 * @param group Group to become. Don't change group if empty
66 * @param get_group_from_user Get group GID from user information if group is empty.
67 * @return true if all is fine, false otherwise
69 bool drop_root_privileges(const std::string &username,
70 const std::string &group, bool get_group_from_user)
74 Group my_group(group);
75 if (!my_group.is_valid())
78 if (setgid((my_group.Gid)))
82 if (!username.empty())
84 User my_user(username);
85 if (!my_user.is_valid())
88 if (get_group_from_user && group.empty())
90 if (setgid((my_user.Gid)))
94 // Initialize additional groups the user is a member of
95 if (initgroups(username.c_str(), getgid() == -1))
98 if (setuid(my_user.Uid))
106 * @brief determine the pids for a given program
107 * @param[in] name name (or full path) of the binary
108 * @param[out] result the pids associated with the name.
109 * @return @a true if the function performed without errors.
111 * Walk though the /proc/\<pid\>'s and search for the name.
113 * @note Since this function uses /proc, it's system specific. Currently:
116 * @todo check cmdline and stat in /proc/\<pid\> dir for the searched name.
118 bool pid_of(const std::string& name, std::vector< pid_t >& result)
120 std::vector< std::string > entries;
121 std::vector< pid_t > fuzz1_result;
122 std::vector< pid_t > fuzz2_result;
124 if (!get_dir("/proc", entries)) return false;
125 for (std::vector< std::string >::const_iterator it= entries.begin();
130 if (! string_to<pid_t>(*it, pid)) continue;
131 std::string base_path= std::string("/proc/") + *it;
132 std::string exe_path= base_path + "/exe";
133 I2n::Stat stat(exe_path, false);
134 if (not stat or not stat.is_link()) continue;
135 std::string real_exe= read_link(exe_path);
136 if (real_exe == name)
138 result.push_back( pid );
142 std::string proc_stat= read_file( base_path + "/stat");
143 if (proc_stat.empty()) continue; // process vanished
145 //TODO some more fuzz tests here?! (cmdline, stat(us))
147 if (basename(real_exe) == name)
149 fuzz2_result.push_back(pid);
155 result.swap(fuzz1_result);
159 result.swap(fuzz2_result);
162 } // eo pidOf(const std::string&,std::vector< pid_t >&)