Fix iconv include directory
[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>
5efd35b1 8#include <stdlib.h>
0a654ec0
TJ
9#include <pwd.h>
10#include <grp.h>
11
12#include <string>
13#include <stdexcept>
1eb904be 14#include "daemonfunc.hpp"
6a93d84a
TJ
15#include "stringfunc.hxx"
16#include "filefunc.hxx"
17
a287a306
TJ
18
19namespace I2n
6a93d84a 20{
1eb904be 21namespace Daemon
6a93d84a 22{
0a654ec0
TJ
23
24using namespace std;
25
26/**
27 * Fork into the background.
28 */
6a93d84a 29void daemonize()
0a654ec0 30{
90246b4a
TJ
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
0a654ec0
TJ
43}
44
45/**
09684efc 46 * Drop root privileges
0a654ec0
TJ
47 * @param username User to become. Don't change user if empty
48 * @param group Group to become. Don't change group if empty
90246b4a
TJ
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
0a654ec0 51 */
90246b4a
TJ
52bool drop_root_privileges(const std::string &username,
53 const std::string &group, bool get_group_from_user)
0a654ec0 54{
90246b4a
TJ
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 }
e43beb91
TJ
80
81 return true;
6a93d84a
TJ
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 */
97bool pid_of(const std::string& name, std::vector< pid_t >& result)
98{
90246b4a
TJ
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;
6a93d84a
TJ
141} // eo pidOf(const std::string&,std::vector< pid_t >&)
142
143}
0a654ec0 144}