99#include < sys/types.h>
1010#include < pwd.h>
1111
12-
13-
14- static int DaemonsShutdownRequest=0 ; // global flag set to 1 to request termination, e.g. on SIGTERM/SIGQUIT signals
12+ static int DaemonsShutdownRequest = 0 ; // global flag set to 1 to request termination, e.g. on SIGTERM/SIGQUIT signals
1513// signal handler to notify exit request
16- static void signalHandler (int ){
17- DaemonsShutdownRequest=1 ;
14+ static void signalHandler (int )
15+ {
16+ DaemonsShutdownRequest = 1 ;
1817}
1918
2019// this function is a replacement of the Linux glibc daemon() function, reported deprecated on MacOS
2120// if flag closeFiles is set, stdin/stdout/stderr are redirected to /dev/null
2221// returns 0 on success, an error code otherwise
23- int createDaemon (int closeFiles) {
22+ int createDaemon (int closeFiles)
23+ {
2424
2525 // fork process
2626 switch (fork ()) {
2727 case -1 :
28- // failure
29- return __LINE__;
28+ // failure
29+ return __LINE__;
3030
3131 case 0 :
32- // child
33- break ;
34-
32+ // child
33+ break ;
34+
3535 default :
36- // terminate calling process immediately
37- _exit (0 );
36+ // terminate calling process immediately
37+ _exit (0 );
3838 }
3939
4040 // create a new session to avoid being killed e.g. on closing parent terminal
4141 if (setsid () == -1 ) {
4242 return __LINE__;
4343 }
44-
45- // redirect stdout/stderr to /dev/null if requested to do so
46- #define REDIRECT_PATH " /dev/null"
44+
45+ // redirect stdout/stderr to /dev/null if requested to do so
46+ #define REDIRECT_PATH " /dev/null"
4747 if (closeFiles) {
48- int fd= open (REDIRECT_PATH, O_RDWR, 0 );
49- if (fd== -1 ) {
48+ int fd = open (REDIRECT_PATH, O_RDWR, 0 );
49+ if (fd == -1 ) {
5050 return __LINE__;
5151 }
5252 dup2 (fd, STDIN_FILENO);
5353 dup2 (fd, STDOUT_FILENO);
5454 dup2 (fd, STDERR_FILENO);
55- if (fd> 2 ) {
55+ if (fd > 2 ) {
5656 close (fd);
5757 } else {
5858 return __LINE__;
@@ -61,187 +61,182 @@ int createDaemon(int closeFiles) {
6161 return 0 ;
6262}
6363
64- Daemon::Daemon (int argc, char * argv[], DaemonConfigParameters *dConfigParams) {
65- isInitialized=0 ;
66-
67- if (dConfigParams!=nullptr ) {
68- params=*dConfigParams;
64+ Daemon::Daemon (int argc, char * argv[], DaemonConfigParameters* dConfigParams)
65+ {
66+ isInitialized = 0 ;
67+
68+ if (dConfigParams != nullptr ) {
69+ params = *dConfigParams;
6970 }
7071
7172 try {
7273 // parse command line parameters
7374 int option;
74- while ((option = getopt (argc, argv, " z:o:" )) != -1 ){
75- switch (option) {
75+ while ((option = getopt (argc, argv, " z:o:" )) != -1 ) {
76+ switch (option) {
7677
77- case ' z' :
78- log.info (" Using configuration %s" ,optarg);
78+ case ' z' :
79+ log.info (" Using configuration %s" , optarg);
7980 try {
8081 config.load (optarg);
81- }
82- catch (std::string err) {
83- log.error (" Failed to load configuration: %s" ,err.c_str ());
82+ } catch (std::string err) {
83+ log.error (" Failed to load configuration: %s" , err.c_str ());
8484 throw __LINE__;
8585 }
8686 break ;
87-
88- case ' o' :
89- {
90- // pass-through option in the format key=value
91- // todo: create a config file tree instead?
92- std::string sOptarg =optarg;
93- size_t qPos=sOptarg .find_first_of (' =' );
94- if (qPos>=sOptarg .length ()) {
95- log.error (" Failed to parse [key=value] in option %s" ,optarg);
96- throw __LINE__;
97- }
98- std::string key=sOptarg .substr (0 ,qPos);
99- std::string value=sOptarg .substr (qPos+1 );
100- if (key==" isInteractive" ) {
101- params.isInteractive =std::stoi (value);
102- } else if (key==" idleSleepTime" ) {
103- params.idleSleepTime =std::stoi (value);;
104- } else if (key==" userName" ) {
105- params.userName =value;
106- } else if (key==" redirectOutput" ) {
107- params.redirectOutput =std::stoi (value);;
108- } else if (key==" logFile" ) {
109- params.logFile =value;
110- } else if (key==" logRotateMaxBytes" ) {
111- params.logRotateMaxBytes =std::stoi (value);
112- } else if (key==" logRotateMaxFiles" ) {
113- params.logRotateMaxFiles =std::stoi (value);
114- } else if (key==" logRotateNow" ) {
115- params.logRotateNow =std::stoi (value);
116- } else {
117- log.error (" Unkown option key %s in option %s" ,key.c_str (),optarg);
118- throw __LINE__;
119- }
87+
88+ case ' o' : {
89+ // pass-through option in the format key=value
90+ // todo: create a config file tree instead?
91+ std::string sOptarg = optarg;
92+ size_t qPos = sOptarg .find_first_of (' =' );
93+ if (qPos >= sOptarg .length ()) {
94+ log.error (" Failed to parse [key=value] in option %s" , optarg);
95+ throw __LINE__;
12096 }
121- break ;
122-
97+ std::string key = sOptarg .substr (0 , qPos);
98+ std::string value = sOptarg .substr (qPos + 1 );
99+ if (key == " isInteractive" ) {
100+ params.isInteractive = std::stoi (value);
101+ } else if (key == " idleSleepTime" ) {
102+ params.idleSleepTime = std::stoi (value);
103+ ;
104+ } else if (key == " userName" ) {
105+ params.userName = value;
106+ } else if (key == " redirectOutput" ) {
107+ params.redirectOutput = std::stoi (value);
108+ ;
109+ } else if (key == " logFile" ) {
110+ params.logFile = value;
111+ } else if (key == " logRotateMaxBytes" ) {
112+ params.logRotateMaxBytes = std::stoi (value);
113+ } else if (key == " logRotateMaxFiles" ) {
114+ params.logRotateMaxFiles = std::stoi (value);
115+ } else if (key == " logRotateNow" ) {
116+ params.logRotateNow = std::stoi (value);
117+ } else {
118+ log.error (" Unkown option key %s in option %s" , key.c_str (), optarg);
119+ throw __LINE__;
120+ }
121+ } break ;
122+
123123 default :
124124 throw __LINE__;
125- }
126-
125+ }
127126 }
128-
129127
130128 // load daemon configuration parameters from config file, if any
131129 // read from [daemon] section
132- std::string cfgEntryPoint= " daemon" ;
130+ std::string cfgEntryPoint = " daemon" ;
133131 config.getOptionalValue <int >(cfgEntryPoint + " .isInteractive" , params.isInteractive );
134132 config.getOptionalValue <int >(cfgEntryPoint + " .idleSleepTime" , params.idleSleepTime );
135133 config.getOptionalValue <std::string>(cfgEntryPoint + " .userName" , params.userName );
136134 config.getOptionalValue <int >(cfgEntryPoint + " .redirectOutput" , params.redirectOutput );
137- config.getOptionalValue <std::string>(cfgEntryPoint + " .logFile" , params.logFile );
135+ config.getOptionalValue <std::string>(cfgEntryPoint + " .logFile" , params.logFile );
138136 config.getOptionalValue <int >(cfgEntryPoint + " .logRotateMaxBytes" , params.logRotateMaxBytes );
139137 config.getOptionalValue <int >(cfgEntryPoint + " .logRotateMaxFiles" , params.logRotateMaxFiles );
140138 config.getOptionalValue <int >(cfgEntryPoint + " .logRotateNow" , params.logRotateNow );
141-
139+
142140 // open log file, if configured
143- if (params.logFile .length ()> 0 ) {
141+ if (params.logFile .length () > 0 ) {
144142 log.setLogFile (params.logFile .c_str (),
145- params.logRotateMaxBytes , params.logRotateMaxFiles , params.logRotateNow );
143+ params.logRotateMaxBytes , params.logRotateMaxFiles , params.logRotateNow );
146144 }
147145
148146 // become a daemon, if configured to do so
149147 if (!params.isInteractive ) {
150- int err= createDaemon (params.redirectOutput );
148+ int err = createDaemon (params.redirectOutput );
151149 if (err) {
152- log.error (" Could not become daemon: error %d" ,err);
150+ log.error (" Could not become daemon: error %d" , err);
153151 throw __LINE__;
154152 }
155153 }
156- log.info (" Started PID %d" ,getpid ());
154+ log.info (" Started PID %d" , getpid ());
157155
158156 // set daemon user name
159- if (params.userName .length ()> 0 ) {
160- int success= 0 ;
161- struct passwd * passent;
162- passent= getpwnam (params.userName .c_str ());
163- if (passent!= NULL ) {
157+ if (params.userName .length () > 0 ) {
158+ int success = 0 ;
159+ struct passwd * passent;
160+ passent = getpwnam (params.userName .c_str ());
161+ if (passent != NULL ) {
164162 setuid (passent->pw_uid );
165163 // check setuid worked as expected
166- if (getuid ()== passent->pw_uid ) {
167- success= 1 ;
164+ if (getuid () == passent->pw_uid ) {
165+ success = 1 ;
168166 }
169167 }
170168 if (!success) {
171- log.error (" Failed to set user = %s" ,params.userName .c_str ());
169+ log.error (" Failed to set user = %s" , params.userName .c_str ());
172170 throw __LINE__;
173171 } else {
174- log.info (" Changed user to %s" ,params.userName .c_str ());
172+ log.info (" Changed user to %s" , params.userName .c_str ());
175173 }
176174 }
177175
178-
179176 // configure signal handlers for clean exit
180177 struct sigaction signalSettings;
181- bzero (&signalSettings,sizeof (signalSettings));
182- signalSettings.sa_handler = signalHandler;
183- sigaction (SIGTERM,&signalSettings,NULL );
184- sigaction (SIGQUIT,&signalSettings,NULL );
185- sigaction (SIGINT,&signalSettings,NULL );
178+ bzero (&signalSettings, sizeof (signalSettings));
179+ signalSettings.sa_handler = signalHandler;
180+ sigaction (SIGTERM, &signalSettings, NULL );
181+ sigaction (SIGQUIT, &signalSettings, NULL );
182+ sigaction (SIGINT, &signalSettings, NULL );
186183
187- isInitialized= 1 ;
184+ isInitialized = 1 ;
188185 log.info (" Daemon initialized" );
186+ } catch (int errLine) {
187+ log.error (" Failed to initialize daemon - error %d" , errLine);
189188 }
190- catch (int errLine) {
191- log.error (" Failed to initialize daemon - error %d" ,errLine);
192- }
193-
194189}
195190
196-
197- Daemon::~Daemon () {
191+ Daemon::~Daemon ()
192+ {
198193 log.info (" Daemon exiting" );
199194}
200195
201-
202196// This is the main daemon loop
203197// The doLoop() [custom] method is called continuously until one of the following conditions occur:
204198// - global flag DaemonsShutdownRequest is set (e.g. by signal handler)
205199// - doLoop() returns with status Error or Completed
206200// A short pause is done between 2 consecutive calls if status Idle is received.
207201// returns -1 (daemon failed to initialize), 0 (loop exits with success) or 1 (loop exists with error).
208- int Daemon::run () {
209- if (!isInitialized) return -1 ;
210-
211- int errCode=0 ;
202+ int Daemon::run ()
203+ {
204+ if (!isInitialized)
205+ return -1 ;
206+
207+ int errCode = 0 ;
212208 for (;;) {
213- LoopStatus status= doLoop ();
209+ LoopStatus status = doLoop ();
214210 if (DaemonsShutdownRequest) {
215211 log.info (" Exit requested" );
216- break ;
212+ break ;
217213 }
218214 if (status == LoopStatus::Idle) {
219215 usleep (params.idleSleepTime );
220216 } else if (status == LoopStatus::Error) {
221217 log.error (" Error detected" );
222- errCode= 1 ;
218+ errCode = 1 ;
223219 break ;
224220 } else if (status == LoopStatus::Completed) {
225221 log.info (" Work completed" );
226222 break ;
227- }
223+ }
228224 }
229225 return errCode;
230226}
231227
232-
233- bool Daemon::isOk () {
228+ bool Daemon::isOk ()
229+ {
234230 return isInitialized;
235231}
236232
237-
238233// dummy base doLoop() class
239- Daemon::LoopStatus Daemon::doLoop () {
234+ Daemon::LoopStatus Daemon::doLoop ()
235+ {
240236 printf (" ." );
241237 fflush (stdout);
242238 return LoopStatus::Idle;
243239}
244240
245-
246241// todo
247242// boost exceptions?
0 commit comments