#include <stdio.h>#include <stddef.h>#include <stdlib.h>#include <limits.h>#include <unistd.h>#include <errno.h>#include <string.h>#include <time.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/wait.h>#include <fcntl.h>#include <signal.h>Include dependency graph for run_kannel_box.c:

Go to the source code of this file.
Defines | |
| #define | NUM_EXTRA ((int) (sizeof(extra_arguments) / sizeof(*extra_arguments))) |
Functions | |
| void | print_usage (FILE *stream) |
| void | build_box_arglist (char *boxfile, int argc, char **argv) |
| void | write_pidfile (void) |
| void | remove_pidfile (void) |
| void | rebind_standard_streams (void) |
| int | open_max (void) |
| void | close_extra_files (void) |
| void | signal_transfer (int signum) |
| void | signal_transfer_and_die (int signum) |
| void | setup_signals (void) |
| int | main_loop (char *boxfile) |
| int | main (int argc, char *argv[]) |
Variables | |
| char * | progname |
| char ** | box_arglist |
| int | min_restart_delay = 60 |
| pid_t | child_box |
| char * | pidfile |
| int | use_extra_args = 1 |
| char * | extra_arguments [] |
|
|
Definition at line 84 of file run_kannel_box.c. Referenced by build_box_arglist(). |
|
||||||||||||||||
|
Definition at line 96 of file run_kannel_box.c. References box_arglist, extra_arguments, free, malloc, NUM_EXTRA, and progname. Referenced by main(). 00097 {
00098 int i;
00099 char **argp;
00100
00101 if (box_arglist) {
00102 free(box_arglist);
00103 }
00104
00105 /* one for the boxfile name itself, one for each extra argument,
00106 * one for each normal argument, and one for the terminating NULL */
00107 box_arglist = malloc((1 + NUM_EXTRA + argc + 1) * sizeof(*box_arglist));
00108 if (!box_arglist) {
00109 fprintf(stderr, "%s: malloc: %s\n", progname, strerror(errno));
00110 exit(1);
00111 }
00112
00113 /* Have argp walk down box_arglist and set each argument. */
00114 argp = box_arglist;
00115
00116 *argp++ = boxfile;
00117 if (use_extra_args) {
00118 for (i = 0; i < NUM_EXTRA; i++) {
00119 *argp++ = extra_arguments[i];
00120 }
00121 }
00122 for (i = 0; i < argc; i++) {
00123 *argp++ = argv[i];
00124 }
00125 *argp++ = (char *)NULL;
00126 }
|
|
|
Definition at line 209 of file run_kannel_box.c. References open_max(). Referenced by main(). 00210 {
00211 int max = open_max();
00212 int fd;
00213
00214 for (fd = 3; fd < max; fd++) {
00215 close(fd);
00216 }
00217 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 307 of file run_kannel_box.c. References build_box_arglist(), close_extra_files(), main_loop(), min_restart_delay, pidfile, print_usage(), progname, rebind_standard_streams(), remove_pidfile(), setup_signals(), use_extra_args, and write_pidfile(). 00308 {
00309 int i;
00310 char *boxfile = NULL;
00311 pid_t childpid;
00312
00313 progname = argv[0];
00314
00315 if (argc == 1) {
00316 print_usage(stderr);
00317 exit(2);
00318 }
00319
00320 /* Parse the options meant for the wrapper, and get the name of
00321 * the box to wrap. */
00322 for (i = 1; i < argc && !boxfile; i++) {
00323 if (strcmp(argv[i], "--pidfile") == 0) {
00324 if (i+1 >= argc) {
00325 fprintf(stderr, "Missing argument for option %s\n", argv[i]);
00326 exit(2);
00327 }
00328 pidfile = argv[i+1];
00329 i++;
00330 } else if (strcmp(argv[i], "--min-delay") == 0) {
00331 if (i+1 >= argc) {
00332 fprintf(stderr, "Missing argument for option %s", argv[i]);
00333 exit(2);
00334 }
00335 min_restart_delay = atoi(argv[i+1]);
00336 i++;
00337 } else if (strcmp(argv[i], "--no-extra-args") == 0) {
00338 use_extra_args = 0;
00339 } else if (argv[i][0] == '-') {
00340 fprintf(stderr, "Unknown option %s\n", argv[i]);
00341 exit(2);
00342 } else {
00343 boxfile = argv[i];
00344 }
00345 }
00346
00347 /* Check if we have everything */
00348 if (!boxfile) {
00349 print_usage(stderr);
00350 exit(2);
00351 }
00352
00353 /* The remaining arguments should be passed to the box */
00354 build_box_arglist(boxfile, argc - i, argv + i);
00355
00356 /* Ready to rock. Begin daemonization. */
00357
00358 /* Fork a child process and have the parent exit.
00359 * This makes us run in the background. */
00360 childpid = fork();
00361 if (childpid < 0) {
00362 fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
00363 exit(1);
00364 }
00365 if (childpid != 0) {
00366 exit(0); /* parent exits immediately */
00367 }
00368
00369 /* The child continues here. Now call setsid() to disconnect
00370 * from our terminal and from the parent's session and process
00371 * group. */
00372 if (setsid() < 0) {
00373 fprintf(stderr, "%s: setsid: %s\n", progname, strerror(errno));
00374 exit(1);
00375 }
00376
00377 /* Change to the root directory, so that we don't keep a
00378 * file descriptor open on an unknown directory. */
00379 if (chdir("/") < 0) {
00380 fprintf(stderr, "%s: chdir to root: %s\n", progname, strerror(errno));
00381 exit(1);
00382 }
00383
00384 atexit(remove_pidfile);
00385 write_pidfile();
00386
00387 /* Set the umask to a known value, rather than inheriting
00388 * an unknown one. */
00389 umask(077);
00390
00391 /* Leave file descriptors 0, 1, and 2 pointing to harmless
00392 * places, and close all other file descriptors. */
00393 rebind_standard_streams();
00394 close_extra_files();
00395
00396 setup_signals();
00397 return main_loop(boxfile);
00398 }
|
Here is the call graph for this function:

|
|
Definition at line 262 of file run_kannel_box.c. References box_arglist, and child_box. 00263 {
00264 time_t next_fork = 0;
00265
00266 /* We can't report any errors here, because we are running
00267 * as a daemon and we have no logfile of our own. So we
00268 * exit with errno as the exit code, to offer a minimal clue. */
00269
00270 for (;;) {
00271
00272 /* Make sure we don't fork in an endless loop if something
00273 * is drastically wrong. This code limits it to one
00274 * per minute (or whatever min_restart_delay is set to). */
00275 time_t this_time = time(NULL);
00276 if (this_time <= next_fork) {
00277 sleep(next_fork - this_time);
00278 }
00279 next_fork = this_time + min_restart_delay;
00280
00281 child_box = fork();
00282 if (child_box < 0) {
00283 return errno;
00284 }
00285 if (child_box == 0) {
00286 /* child. exec the box */
00287 execvp(boxfile, box_arglist);
00288 exit(127);
00289 }
00290
00291 while (waitpid(child_box, (int *)NULL, 0) != child_box) {
00292 if (errno == ECHILD) {
00293 /* Something went wrong... we don't know what,
00294 * but we do know that our child does not
00295 * exist. So restart it. */
00296 break;
00297 }
00298 if (errno == EINTR) {
00299 continue;
00300 }
00301 /* Something weird happened. */
00302 return errno;
00303 }
00304 }
00305 }
|
|
|
Definition at line 193 of file run_kannel_box.c. Referenced by close_extra_files(). 00194 {
00195 #ifdef OPEN_MAX
00196 return OPEN_MAX;
00197 #else
00198 int max;
00199
00200 max = sysconf(_SC_OPEN_MAX);
00201 if (max <= 0) {
00202 return 1024; /* guess */
00203 }
00204 return max;
00205 #endif
00206 }
|
|
|
Definition at line 86 of file run_kannel_box.c. References progname. Referenced by main(). 00087 {
00088 fprintf(stream,
00089 "Usage: %s [--pidfile PIDFILE] [--min-delay SECONDS] BOXPATH [boxoptions...]\n",
00090 progname);
00091 }
|
|
|
Definition at line 165 of file run_kannel_box.c. References progname. Referenced by main(). 00166 {
00167 int devnullfd;
00168 int devfullfd;
00169
00170 devnullfd = open("/dev/null", O_RDONLY);
00171 if (devnullfd < 0) {
00172 fprintf(stderr, "%s: cannot open /dev/null: %s\n",
00173 progname, strerror(errno));
00174 exit(2);
00175 }
00176 devfullfd = open("/dev/full", O_WRONLY);
00177 if (devfullfd < 0) {
00178 devfullfd = devnullfd;
00179 }
00180
00181 /* Alert: The dup on stderr is done last, so that the error message
00182 * works regardless of which dup fails. */
00183 if (dup2(devnullfd, 0) < 0 ||
00184 dup2(devfullfd, 1) < 0 ||
00185 dup2(devfullfd, 2) < 0) {
00186 fprintf(stderr, "%s: dup2: %s\n", progname, strerror(errno));
00187 exit(1);
00188 }
00189 }
|
|
|
Definition at line 155 of file run_kannel_box.c. References pidfile. Referenced by main(), and signal_transfer_and_die(). 00156 {
00157 if (!pidfile)
00158 return;
00159
00160 unlink(pidfile);
00161 }
|
|
|
Definition at line 250 of file run_kannel_box.c. References signal_transfer(), and signal_transfer_and_die(). Referenced by main(). 00251 {
00252 signal(SIGHUP, &signal_transfer);
00253 signal(SIGINT, &signal_transfer_and_die);
00254 signal(SIGQUIT, &signal_transfer_and_die);
00255 signal(SIGTERM, &signal_transfer_and_die);
00256 signal(SIGUSR1, &signal_transfer);
00257 signal(SIGUSR2, &signal_transfer);
00258 }
|
Here is the call graph for this function:

|
|
Definition at line 221 of file run_kannel_box.c. References child_box. Referenced by setup_signals(). 00222 {
00223 if (child_box > 0) {
00224 kill(child_box, signum);
00225 }
00226 }
|
|
|
Definition at line 231 of file run_kannel_box.c. References child_box, and remove_pidfile(). Referenced by setup_signals(). 00232 {
00233 /* First send it to the child process */
00234 if (child_box > 0) {
00235 kill(child_box, signum);
00236 }
00237
00238 /* Prepare to die. Normally the atexit handler would take care
00239 * of this when we exit(), but we're going to die from a signal. */
00240 remove_pidfile();
00241
00242 /* Then send it to self. First set the default handler, to
00243 * avoid catching the signal with this handler again. This
00244 * is not a race, because it doesn't matter if we die from
00245 * the signal we're going to send or from a different one. */
00246 signal(signum, SIG_DFL);
00247 kill(getpid(), signum);
00248 }
|
Here is the call graph for this function:

|
|
Definition at line 128 of file run_kannel_box.c. References pidfile, and progname. Referenced by main(). 00129 {
00130 int fd;
00131 FILE *f;
00132
00133 if (!pidfile)
00134 return;
00135
00136 fd = open(pidfile, O_WRONLY|O_NOCTTY|O_TRUNC|O_CREAT, 0644);
00137 if (fd < 0) {
00138 fprintf(stderr, "%s: open: %s: %s\n", progname, pidfile, strerror(errno));
00139 exit(1);
00140 }
00141
00142 f = fdopen(fd, "w");
00143 if (!f) {
00144 fprintf(stderr, "%s: fdopen: %s\n", progname, strerror(errno));
00145 exit(1);
00146 }
00147
00148 fprintf(f, "%ld\n", (long)getpid());
00149 if (fclose(f) < 0) {
00150 fprintf(stderr, "%s: writing %s: %s\n", progname, pidfile, strerror(errno));
00151 exit(1);
00152 }
00153 }
|
|
|
Definition at line 74 of file run_kannel_box.c. Referenced by build_box_arglist(), and main_loop(). |
|
|
Definition at line 76 of file run_kannel_box.c. Referenced by main_loop(), signal_transfer(), and signal_transfer_and_die(). |
|
|
Initial value: {
"-v", "4",
}
Definition at line 81 of file run_kannel_box.c. Referenced by build_box_arglist(). |
|
|
Definition at line 75 of file run_kannel_box.c. Referenced by main(). |
|
|
Definition at line 77 of file run_kannel_box.c. Referenced by main(), remove_pidfile(), and write_pidfile(). |
|
|
Definition at line 73 of file run_kannel_box.c. |
|
|
Definition at line 78 of file run_kannel_box.c. Referenced by main(). |