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