libi2ncommon: (reinhard) changes for g++ 4.3.1
[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
82 /**
83  * @brief determine the pids for a given program
84  * @param[in] name name (or full path) of the binary
85  * @param[out] result the pids associated with the name.
86  * @return @a true if the function performed without errors.
87  *
88  * Walk though the /proc/\<pid\>'s and search for the name.
89  *
90  * @note Since this function uses /proc, it's system specific. Currently:
91  * Linux only!
92  *
93  * @todo check cmdline and stat in /proc/\<pid\> dir for the searched name.
94  */
95 bool pid_of(const std::string& name, std::vector< pid_t >& result)
96 {
97    std::vector< std::string > entries;
98    std::vector< pid_t > fuzz1_result;
99    std::vector< pid_t > fuzz2_result;
100    result.clear();
101    if (!get_dir("/proc", entries)) return false;
102    for (std::vector< std::string >::const_iterator it= entries.begin();
103          it != entries.end();
104          ++it)
105    {
106       pid_t pid;
107       if (! string_to<pid_t>(*it, pid)) continue;
108       std::string base_path= std::string("/proc/") + *it;
109       std::string exe_path= base_path + "/exe";
110       I2n::Stat stat(exe_path, false);
111       if (not stat or not stat.is_link()) continue;
112       std::string real_exe= read_link(exe_path);
113       if (real_exe == name)
114       {
115          result.push_back( pid );
116          continue;
117       }
118
119       std::string proc_stat= read_file( base_path + "/stat");
120       if (proc_stat.empty()) continue; // process vanished
121
122       //TODO some more fuzz tests here?! (cmdline, stat(us))
123
124       if (basename(real_exe) == name)
125       {
126          fuzz2_result.push_back(pid);
127          continue;
128       }
129    }
130    if (result.empty())
131    {
132       result.swap(fuzz1_result);
133    }
134    if (result.empty())
135    {
136       result.swap(fuzz2_result);
137    }
138    return true;
139 } // eo pidOf(const std::string&,std::vector< pid_t >&)
140
141 }
142 }