libi2ncommon: (tomj) modified filefunc according to our new style guide.
[libi2ncommon] / src / daemonfunc.cpp
1 /***************************************************************************
2  *   Copyright (C) 2008 by Intra2net AG - Thomas Jarosch                   *
3  *   thomas.jarosch@intra2net.com                                          *
4  *   http://www.intra2net.com                                              *
5  ***************************************************************************/
6 #include <sys/types.h>
7 #include <unistd.h>
8 #include <pwd.h>
9 #include <grp.h>
10
11 #include <string>
12 #include <stdexcept>
13 #include "daemonfunc.hxx"
14 #include "stringfunc.hxx"
15 #include "filefunc.hxx"
16
17 // TODO: Remove me once libi2ncommon is completly switched to I2n
18 using namespace i2n;
19
20 namespace I2n
21 {
22 namespace daemon
23 {
24
25 using namespace std;
26
27 /**
28  * Fork into the background.
29  */
30 void daemonize()
31 {
32     int pid=fork();
33
34     if (pid < 0)
35     {
36         throw runtime_error("fork() failed");
37     }
38     if (pid > 0)
39     {
40         // parent process
41         exit (0);
42     }
43     // pid==0 -> child process: continue
44 }
45
46 /**
47  * Drop root privileges
48  * @param username User to become. Don't change user if empty
49  * @param group Group to become. Don't change group if empty
50  */
51 void drop_root_privileges(const std::string &username,
52                                                  const std::string &group)
53 {
54 /*
55     if (!group.empty()) {
56         if (setgid(daemon::lookup_gid(group))) {
57             throw runtime_error("Can't change to group " + group);
58         }
59     }
60
61     if (!username.empty()) {
62         if (setuid(daemon::lookup_uid(username))) {
63             throw runtime_error("Can't change to user " + username);
64         }
65     }
66 */
67 }
68
69 /**
70  * @brief determine the pids for a given program
71  * @param[in] name name (or full path) of the binary
72  * @param[out] result the pids associated with the name.
73  * @return @a true if the function performed without errors.
74  *
75  * Walk though the /proc/\<pid\>'s and search for the name.
76  *
77  * @note Since this function uses /proc, it's system specific. Currently:
78  * Linux only!
79  *
80  * @todo check cmdline and stat in /proc/\<pid\> dir for the searched name.
81  */
82 bool pid_of(const std::string& name, std::vector< pid_t >& result)
83 {
84     std::vector< std::string > entries;
85     std::vector< pid_t > fuzz1_result;
86     std::vector< pid_t > fuzz2_result;
87     result.clear();
88     if (!get_dir("/proc", entries)) return false;
89     for(std::vector< std::string >::const_iterator it= entries.begin();
90         it != entries.end();
91         ++it)
92     {
93         pid_t pid;
94         if (! stringTo<pid_t>(*it, pid)) continue;
95         std::string base_path= std::string("/proc/") + *it;
96         std::string exe_path= base_path + "/exe";
97         I2n::Stat stat(exe_path, false);
98         if (not stat or not stat.is_link()) continue;
99         std::string real_exe= read_link(exe_path);
100         if (real_exe == name)
101         {
102             result.push_back( pid );
103             continue;
104         }
105
106         std::string proc_stat= read_file( base_path + "/stat");
107         if (proc_stat.empty()) continue; // process vanished
108
109         //TODO some more fuzz tests here?! (cmdline, stat(us))
110
111         if (basename(real_exe) == name)
112         {
113             fuzz2_result.push_back(pid);
114             continue;
115         }
116     }
117     if (result.empty())
118     {
119         result.swap(fuzz1_result);
120     }
121     if (result.empty())
122     {
123         result.swap(fuzz2_result);
124     }
125     return true;
126 } // eo pidOf(const std::string&,std::vector< pid_t >&)
127
128 }
129 }