startup process when pazpar2 is used in start scripts such as Debian's
start-stop-daemon. Without -D, pazpar2 would have to be started using
-b for start-stop-daemon. Refer to man page start-stop-daemon(8).
This change also makes pazpar2 change uid before the daemon is running.
We just ensure that HTTP binding and YAZ log files, PID files are dealt with
before any setuid takes place.. Pazpar2 makes log entry with version
info. The daemon mode refuses to start if -l is not given. This is to ensure
that logfile output is not dumped to /dev/null by accident.
-/* $Id: pazpar2.c,v 1.89 2007-06-12 13:02:38 adam Exp $
+/* $Id: pazpar2.c,v 1.90 2007-06-18 11:10:20 adam Exp $
Copyright (c) 2006-2007, Index Data.
This file is part of Pazpar2.
Copyright (c) 2006-2007, Index Data.
This file is part of Pazpar2.
int main(int argc, char **argv)
{
int main(int argc, char **argv)
{
+ int log_file_in_use = 0;
char *arg;
const char *pidfile = "pazpar2.pid";
const char *uid = 0;
char *arg;
const char *pidfile = "pazpar2.pid";
const char *uid = 0;
yaz_log_init_prefix("pazpar2");
yaz_log_init_prefix("pazpar2");
- while ((ret = options("f:h:p:t:u:l:dX", argv, argc, &arg)) != -2)
+ while ((ret = options("f:h:p:t:u:l:dDX", argv, argc, &arg)) != -2)
break;
case 'l':
yaz_log_init_file(arg);
break;
case 'l':
yaz_log_init_file(arg);
+ log_file_in_use = 1;
+ break;
+ case 'D':
+ daemon = 1;
break;
case 'X':
global_parameters.debug_mode = 1;
break;
case 'X':
global_parameters.debug_mode = 1;
" -t settings\n"
" -u uid\n"
" -d (show internal records)\n"
" -t settings\n"
" -u uid\n"
" -d (show internal records)\n"
+ " -D Daemon mode (background)\n"
" -l file log to file\n"
" -X debug mode\n"
);
" -l file log to file\n"
" -X debug mode\n"
);
+ yaz_log(YLOG_LOG, "Pazpar2 %s started", VERSION);
+ if (daemon && !log_file_in_use)
+ {
+ yaz_log(YLOG_FATAL, "Logfile must be given (option -l) for daemon "
+ "mode");
+ exit(1);
+ }
if (!config)
{
yaz_log(YLOG_FATAL, "Load config with -f");
if (!config)
{
yaz_log(YLOG_FATAL, "Load config with -f");
global_parameters.server = config->servers;
start_http_listener();
global_parameters.server = config->servers;
start_http_listener();
- pazpar2_process(global_parameters.debug_mode,
+ pazpar2_process(global_parameters.debug_mode, daemon,
child_handler, 0 /* child_data */,
pidfile, uid);
return 0;
child_handler, 0 /* child_data */,
pidfile, uid);
return 0;
-/* $Id: pazpar2.h,v 1.42 2007-06-15 19:35:17 adam Exp $
+/* $Id: pazpar2.h,v 1.43 2007-06-18 11:10:20 adam Exp $
Copyright (c) 2006-2007, Index Data.
This file is part of Pazpar2.
Copyright (c) 2006-2007, Index Data.
This file is part of Pazpar2.
void session_alert_watch(struct session *s, int what);
void pull_terms(NMEM nmem, struct ccl_rpn_node *n, char **termlist, int *num);
void session_alert_watch(struct session *s, int what);
void pull_terms(NMEM nmem, struct ccl_rpn_node *n, char **termlist, int *num);
-int pazpar2_process(int debug,
+int pazpar2_process(int debug, int daemon,
void (*work)(void *data), void *data,
const char *pidfile, const char *uid);
void (*work)(void *data), void *data,
const char *pidfile, const char *uid);
-/* $Id: process.c,v 1.2 2007-06-12 13:02:38 adam Exp $
+/* $Id: process.c,v 1.3 2007-06-18 11:10:20 adam Exp $
Copyright (c) 2006-2007, Index Data.
This file is part of Pazpar2.
Copyright (c) 2006-2007, Index Data.
This file is part of Pazpar2.
#endif
#include <signal.h>
#endif
#include <signal.h>
#include <unistd.h>
#include <assert.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <assert.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include <pwd.h>
#include <yaz/log.h>
#include <pwd.h>
#include <yaz/log.h>
-int pazpar2_process(int debug,
+int pazpar2_process(int debug, int daemon,
void (*work)(void *data), void *data,
const char *pidfile, const char *uid /* not yet used */)
{
void (*work)(void *data), void *data,
const char *pidfile, const char *uid /* not yet used */)
{
int run = 1;
int cont = 1;
void (*old_sighup)(int);
void (*old_sigterm)(int);
int run = 1;
int cont = 1;
void (*old_sighup)(int);
void (*old_sigterm)(int);
if (debug)
{
/* in debug mode.. it's quite simple */
if (debug)
{
/* in debug mode.. it's quite simple */
+ write_pidfile(pidfile);
/* running in production mode. */
if (uid)
{
/* running in production mode. */
if (uid)
{
- yaz_log(YLOG_LOG, "getpwnam");
- // OK to use the non-thread version here
- if (!(pw = getpwnam(uid)))
+ /* OK to use the non-thread version here */
+ struct passwd *pw = getpwnam(uid);
+ if (!pw)
{
yaz_log(YLOG_FATAL, "%s: Unknown user", uid);
exit(1);
}
{
yaz_log(YLOG_FATAL, "%s: Unknown user", uid);
exit(1);
}
+ if (setuid(pw->pw_uid) < 0)
+ {
+ yaz_log(YLOG_FATAL|YLOG_ERRNO, "setuid");
+ exit(1);
+ }
+ if (daemon)
+ {
+ /* create pipe so that parent waits until child has created
+ PID (or failed) */
+ static int hand[2]; /* hand shake for child */
+ if (pipe(hand) < 0)
+ {
+ yaz_log(YLOG_FATAL|YLOG_ERRNO, "pipe");
+ return 1;
+ }
+ switch (fork())
+ {
+ case 0:
+ break;
+ case -1:
+ return 1;
+ default:
+ close(hand[1]);
+ while(1)
+ {
+ char dummy[1];
+ int res = read(hand[0], dummy, 1);
+ if (res < 0 && errno != EINTR)
+ {
+ yaz_log(YLOG_FATAL|YLOG_ERRNO, "read fork handshake");
+ break;
+ }
+ else if (res >= 0)
+ break;
+ }
+ close(hand[0]);
+ _exit(0);
+ }
+ /* child */
+ close(hand[0]);
+ if (setsid() < 0)
+ return 1;
+
+ close(0);
+ close(1);
+ close(2);
+ open("/dev/null", O_RDWR);
+ dup(0); dup(0);
+ close(hand[1]);
+ }
/* keep signals in their original state and make sure that some signals
/* keep signals in their original state and make sure that some signals
- to parent process also gets sent to the child.. Normally this
- should not happen. We want the _child_ process to be terminated
- normally. However, if the parent process is terminated, we
- kill the child too */
+ to parent process also gets sent to the child..
+ */
old_sighup = signal(SIGHUP, kill_child_handler);
old_sigterm = signal(SIGTERM, kill_child_handler);
while (cont)
old_sighup = signal(SIGHUP, kill_child_handler);
old_sigterm = signal(SIGTERM, kill_child_handler);
while (cont)
signal(SIGHUP, old_sighup); /* restore */
signal(SIGTERM, old_sigterm);/* restore */
signal(SIGHUP, old_sighup); /* restore */
signal(SIGTERM, old_sigterm);/* restore */
- write_pidfile(pidfile);
-
- if (pw)
- {
- if (setuid(pw->pw_uid) < 0)
- {
- yaz_log(YLOG_FATAL|YLOG_ERRNO, "setuid");
- exit(1);
- }
- }
-
child_pid = p;
p1 = wait(&status);
child_pid = p;
p1 = wait(&status);
/* disable signalling in kill_child_handler */
child_pid = 0;
/* disable signalling in kill_child_handler */
child_pid = 0;