170bf67152e41d09b9ae41663a4906c89dbd3f45
[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 <stdlib.h>
9 #include <pwd.h>
10 #include <grp.h>
11
12 #include <string>
13 #include <stdexcept>
14 #include "daemonfunc.hpp"
15 #include "stringfunc.hxx"
16 #include "filefunc.hxx"
17
18
19 namespace I2n
20 {
21 namespace Daemon
22 {
23
24 using namespace std;
25
26 /**
27  * Fork into the background.
28  */
29 void daemonize()
30 {
31    int pid=fork();
32
33    if (pid < 0)
34    {
35       throw runtime_error("fork() failed");
36    }
37    if (pid > 0)
38    {
39       // parent process
40       exit (0);
41    }
42    // pid==0 -> child process: continue
43 }
44
45 /**
46  * Drop root privileges
47  * @param username User to become. Don't change user if empty
48  * @param group Group to become. Don't change group if empty
49  * @param get_group_from_user Get group GID from user information if group is empty.
50  * @return true if all is fine, false otherwise
51  */
52 bool drop_root_privileges(const std::string &username,
53                           const std::string &group, bool get_group_from_user)
54 {
55    if (!group.empty())
56    {
57       Group my_group(group);
58       if (!my_group.is_valid())
59          return false;
60
61       if (setgid((my_group.Gid)))
62          return false;
63    }
64
65    if (!username.empty())
66    {
67       User my_user(username);
68       if (!my_user.is_valid())
69          return false;
70
71       if (get_group_from_user && group.empty())
72       {
73          if (setgid((my_user.Gid)))
74             return false;
75       }
76
77       if (setuid(my_user.Uid))
78          return false;
79    }
80
81     return true;
82 }
83
84 /**
85  * @brief determine the pids for a given program
86  * @param[in] name name (or full path) of the binary
87  * @param[out] result the pids associated with the name.
88  * @return @a true if the function performed without errors.
89  *
90  * Walk though the /proc/\<pid\>'s and search for the name.
91  *
92  * @note Since this function uses /proc, it's system specific. Currently:
93  * Linux only!
94  *
95  * @todo check cmdline and stat in /proc/\<pid\> dir for the searched name.
96  */
97 bool pid_of(const std::string& name, std::vector< pid_t >& result)
98 {
99    std::vector< std::string > entries;
100    std::vector< pid_t > fuzz1_result;
101    std::vector< pid_t > fuzz2_result;
102    result.clear();
103    if (!get_dir("/proc", entries)) return false;
104    for (std::vector< std::string >::const_iterator it= entries.begin();
105          it != entries.end();
106          ++it)
107    {
108       pid_t pid;
109       if (! string_to<pid_t>(*it, pid)) continue;
110       std::string base_path= std::string("/proc/") + *it;
111       std::string exe_path= base_path + "/exe";
112       I2n::Stat stat(exe_path, false);
113       if (not stat or not stat.is_link()) continue;
114       std::string real_exe= read_link(exe_path);
115       if (real_exe == name)
116       {
117          result.push_back( pid );
118          continue;
119       }
120
121       std::string proc_stat= read_file( base_path + "/stat");
122       if (proc_stat.empty()) continue; // process vanished
123
124       //TODO some more fuzz tests here?! (cmdline, stat(us))
125
126       if (basename(real_exe) == name)
127       {
128          fuzz2_result.push_back(pid);
129          continue;
130       }
131    }
132    if (result.empty())
133    {
134       result.swap(fuzz1_result);
135    }
136    if (result.empty())
137    {
138       result.swap(fuzz2_result);
139    }
140    return true;
141 } // eo pidOf(const std::string&,std::vector< pid_t >&)
142
143 }
144 }