DTS Application Library  0.2.3
Application library containing referenced objects and interfaces to common libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
main.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 2012 Gregory Nietsky <gregory@distrotetch.co.za>
3  http://www.distrotech.co.za
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
25 #include <unistd.h>
26 #include <signal.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <stdint.h>
30 #include <string.h>
31 #include <fcntl.h>
32 #include <sys/file.h>
33 
34 #include "include/dtsapp.h"
35 #include "include/private.h"
36 
37 static struct framework_core *framework_core_info = NULL;
38 
39 #ifndef __WIN32__
40 /*
41  * handle signals to cleanup gracefully on exit
42  */
43 static void framework_sig_handler(int sig, siginfo_t *si, void *unused) {
44  /* flag and clean all threads*/
45  switch (sig) {
46  case SIGUSR1:
47  case SIGUSR2:
48  case SIGHUP:
49  case SIGALRM:
50  if (!thread_signal(sig) && framework_core_info->sig_handler) {
51  framework_core_info->sig_handler(sig, si, unused);
52  }
53  break;
54  case SIGTERM:
55  case SIGINT:
56  default:
57  if (!thread_signal(sig)) {
58  if (framework_core_info->sig_handler) {
59  framework_core_info->sig_handler(sig, si, unused);
60  } else {
61  stopthreads(1);
62  exit(-1);
63  }
64  }
65  }
66 }
67 #endif
68 
78 extern void printgnu(const char *pname, int year, const char *dev, const char *email, const char *www) {
79  printf("\n"
80  " %s\n\n"
81  " Copyright (C) %i %s <%s>\n\n"
82  " %s\n\n"
83  " This program comes with ABSOLUTELY NO WARRANTY\n"
84  " This is free software, and you are welcome to redistribute it\n"
85  " under certain conditions.\n\n", pname, year, dev, email, www);
86 }
87 
94 extern void daemonize() {
95  struct framework_core *ci = framework_core_info;
96 
97 #ifndef __WIN32__
98  pid_t forkpid;
99 
100  /* fork and die daemonize*/
101  forkpid = fork();
102  if (forkpid > 0) {
103  /* im all grown up and can pass onto child*/
104  exit(0);
105  } else if (forkpid < 0) {
106  /* could not fork*/
107  exit(-1);
108  }
109 
110  setsid();
111 
112  /* Dont want these as a daemon*/
113  signal(SIGTSTP, SIG_IGN);
114  signal(SIGCHLD, SIG_IGN);
115 #endif
116 
117  /*delayed lock file from FRAMEWORK_MAIN / framework_init*/
118  if (ci && (ci->flags & FRAMEWORK_FLAG_DAEMONLOCK)) {
119  if ((ci->flock = lockpidfile(ci->runfile)) < 0) {
120  printf("Could not lock pid file Exiting\n");
121  while(framework_core_info) {
122  objunref(framework_core_info);
123  }
124  exit (-1);
125  }
126  objunref(ci);
127  }
128 }
129 
135 extern int lockpidfile(const char *runfile) {
136  int lck_fd = 0;
137 #ifndef __WIN32__
138  char pidstr[12];
139  pid_t mypid;
140 
141  mypid = getpid();
142  sprintf(pidstr,"%i\n", (int)mypid);
143  if (runfile && ((lck_fd = open(runfile, O_RDWR|O_CREAT, 0640)) > 0) && (!flock(lck_fd, LOCK_EX | LOCK_NB))) {
144  if (write(lck_fd, pidstr, strlen(pidstr)) < 0) {
145  close(lck_fd);
146  lck_fd = -1;
147  }
148  /* file was opened and not locked*/
149  } else if (runfile && lck_fd) {
150  close(lck_fd);
151  lck_fd = -1;
152  }
153 #endif
154  return (lck_fd);
155 }
156 
157 
158 #ifndef __WIN32__
159 /*
160  * set up signal handler
161  */
162 static void configure_sigact(struct sigaction *sa) {
163  sa->sa_flags = SA_SIGINFO | SA_RESTART;
164  sigemptyset(&sa->sa_mask);
165  sa->sa_sigaction = framework_sig_handler;
166  sigaction(SIGINT, sa, NULL);
167  sigaction(SIGTERM, sa, NULL);
168 
169  /*internal interupts*/
170  sigaction(SIGUSR1, sa, NULL);
171  sigaction(SIGUSR2, sa, NULL);
172  sigaction(SIGHUP, sa, NULL);
173  sigaction(SIGALRM, sa, NULL);
174 }
175 #endif
176 
177 /*
178  * free core
179  */
180 static void framework_free(void *data) {
181  struct framework_core *ci = data;
182  framework_core_info = NULL;
183 
184  if (ci->developer) {
185  free((char *)ci->developer);
186  }
187  if (ci->email) {
188  free((char *)ci->email);
189  }
190  if (ci->www) {
191  free((char *)ci->www);
192  }
193  if (ci->sa) {
194  free(ci->sa);
195  }
196  if (ci->flock >= 0) {
197  close(ci->flock);
198  }
199  if (ci->runfile) {
200  if (ci->flock >= 0) {
201  unlink(ci->runfile);
202  }
203  free((char *)ci->runfile);
204  }
205 }
206 
221 extern void framework_mkcore(char *progname, char *name, char *email, char *web, int year, char *runfile, int flags, syssighandler sigfunc) {
222  struct framework_core *core_info;
223  if (framework_core_info) {
224  objunref(framework_core_info);
225  framework_core_info = NULL;
226  }
227 
228  if (!(core_info = objalloc(sizeof(*core_info), framework_free))) {
229  return;
230  }
231 
232 #ifndef __WIN32__
233  if (core_info && !(core_info->sa = malloc(sizeof(*core_info->sa)))) {
234  free(core_info);
235  return;
236  }
237 #endif
238 
239  ALLOC_CONST(core_info->developer, name);
240  ALLOC_CONST(core_info->email, email);
241  ALLOC_CONST(core_info->www, web);
242  ALLOC_CONST(core_info->runfile, runfile);
243  ALLOC_CONST(core_info->progname, progname);
244  core_info->year = year;
245  core_info->flags = flags;
246 #ifndef __WIN32__
247  core_info->sig_handler = sigfunc;
248 #endif
249  /* Pass reference to static system variable*/
250  framework_core_info = core_info;
251 }
252 
260 extern int framework_init(int argc, char *argv[], frameworkfunc callback) {
261  struct framework_core *ci = framework_core_info;
262  int ret = 0;
263 
264  seedrand();
265  sslstartup();
266 
267  /*prinit out a GNU licence summary*/
268  if (ci && !(ci->flags & FRAMEWORK_FLAG_NOGNU)) {
269  printgnu(ci->progname, ci->year, ci->developer, ci->email, ci->www);
270  }
271 
272  /* grab a ref for framework_core_info to be used latter*/
273  if (ci && ci->flags & FRAMEWORK_FLAG_DAEMONLOCK) {
274  objref(ci);
275  }
276 
277  /* fork the process to daemonize it*/
278  if (ci && ci->flags & FRAMEWORK_FLAG_DAEMON) {
279  daemonize();
280  }
281 
282  /* write pid to lockfile this should be done post daemonize*/
283  if (ci && !(ci->flags & FRAMEWORK_FLAG_DAEMONLOCK)) {
284  if ((ci->flock = lockpidfile(ci->runfile)) < 0) {
285  printf("Could not lock pid file Exiting\n");
286  return -1;
287  }
288  }
289 
290 #ifndef __WIN32__
291  /* interupt handler close clean on term so physical is reset*/
292  configure_sigact(framework_core_info->sa);
293 #endif
294 
295  /*run the code from the application*/
296  if (callback) {
297  ret = callback(argc, argv);
298  /* wait for all threads to end*/
299  stopthreads(1);
300  }
301 
302  /* turn off the lights*/
303  objunref(ci);
304  if (framework_core_info && framework_core_info->flags & FRAMEWORK_FLAG_DAEMONLOCK) {
305  objunref(framework_core_info);
306  }
308  return (ret);
309 }
310 
const char * email
Email address of copyright holder.
Definition: dtsapp.h:330
void(* syssighandler)(int, siginfo_t *, void *)
Callback to user supplied signal handler.
Definition: dtsapp.h:228
const char * progname
Detailed application name.
Definition: dtsapp.h:336
int objref(void *data)
Reference a object.
Definition: refobj.c:153
void framework_mkcore(char *progname, char *name, char *email, char *web, int year, char *runfile, int flags, syssighandler sigfunc)
Initilise application data structure and return a reference.
Definition: main.c:221
struct sigaction * sa
sigaction structure allocated on execution
Definition: dtsapp.h:342
const char * developer
Developer/Copyright holder.
Definition: dtsapp.h:328
void stopthreads(int join)
Signal manager to stop and cancel all running threads.
Definition: thread.c:303
int flock
if there is a file locked this is the FD that will be unlocked and unlinked
Definition: dtsapp.h:340
void * objalloc(int size, objdestroy)
Allocate a referenced lockable object.
Definition: refobj.c:129
const char * www
URL displayed (use full URL ie with http://)
Definition: dtsapp.h:332
void sslstartup(void)
Initialise SSL support this should be called at startup.
Definition: sslutil.c:639
int framework_init(int argc, char *argv[], frameworkfunc callback)
Initilise the application daemonise and join the manager thread.
Definition: main.c:260
int flags
Application Options.
Definition: dtsapp.h:348
int lockpidfile(const char *runfile)
Lock the run file in the framework application info.
Definition: main.c:135
int year
Copyright year.
Definition: dtsapp.h:338
void unrefconfigfiles(void)
Empty out and unreference config files.
Definition: config.c:78
DTS Application library API Include file.
int(* frameworkfunc)(int, char **)
Framework callback function.
Definition: dtsapp.h:219
int thread_signal(int sig)
Handle signal if its for me.
Definition: thread.c:496
Create lockfile on daemonize latter.
Definition: dtsapp.h:319
void seedrand(void)
Seed openssl random number generator.
Definition: util.c:68
Application framework data.
Definition: dtsapp.h:326
Dont print GNU copyright.
Definition: dtsapp.h:314
void daemonize()
Daemonise the application using fork/exit.
Definition: main.c:94
const char * runfile
File to write PID too and lock.
Definition: dtsapp.h:334
#define ALLOC_CONST(const_var, val)
Macro to assign values to char const.
Definition: dtsapp.h:959
void printgnu(const char *pname, int year, const char *dev, const char *email, const char *www)
Print a brief GNU copyright notice on console.
Definition: main.c:78
int objunref(void *data)
Drop reference held.
Definition: refobj.c:184
syssighandler sig_handler
Signal handler to pass signals too.
Definition: dtsapp.h:345
Allow application daemonization.
Definition: dtsapp.h:312